ALLNET® ALL4176 6-way IP socket outlet

Hey there,

this is how to connect an ALLNET® ALL4176 6-way IP socket outlet to your OpenHAB (>= 2.3) server.

I’m using ALL4176 Software 3.35 (Patch 1088), Hardware 0.03

Architecture
Device has a password protected HTTP JSON interface, we will use that for interacting with the device.
Security precaution: HTTP is an unencrypted protocol, network sniffing in your network will allow an attacker to gain your credentials take over control over that device. Device supports HTTPS too, but that will require little more effort (e.g. to make SSL certificate known to Java) which will not be covered by this tutorial.

OpenHAB Prerequisites
OpenHAB: Version 2.3.0 or newer (could be adapted to older versions by not using Units Of Measurement in items definition)
Bindings: http1
Transformations: JavaScript, JsonPath

Setup IP Socket
For basic setup consult the manual. (I couldn’t find that online, conrad.de has a german one of quite similar ALL4076)
We need a fixed hostname / ipaddress, I will use <ipaddress> in my examples.
In device HTTP Webinterface -> Configuration -> Servers and users -> User settings you need to add a new <user> with <password> that has type Remote Control and rights View & Switch

Testing HTTP interface
Point your browser to http://<ipaddress>/xml/ and put in <user> and <password> you set up above, this will show a small help on how to use that interface:

XML Help

http://<ipaddress>/xml?mode=*&type=**&id=***&action=****

Parameter
=========

   without: This help screen

     *mode: possible values actor, sensor, info
    **type: list/switch
     ***id: actor/sensor ID (optional)
****action: 0/1 (optional)

This is an XML based interface, I will use http://<ipaddress>/xml/json.php and jsonswitch.php which offers quite the same functionality, but is based on JSON.

OpenHAB Configuration
This is how to do it:

  1. Add a HTTP cache that gets queried for our device (reduces HTTP load on the device)

services/http.cfg

ALL4176_StatusCache.url=http://<ipaddress>/xml/json.php?mode=all{Authorization=Basic <base64-user:password>}
ALL4176_StatusCache.updateInterval=1000

The part <base64-user:password> is a Base64 encoded string of »<user>:<password>«, see http1 binding documentation for details
Side note: I use mode=all here, which isn’t documented in above help but works anyways - otherwise I would have to set up two HTTP caches for mode=sensor and mode=actor which will double the HTTP load

  1. Add a JavaScript transformation for each socket - as passing parameters to JavaScript isn’t possible, you need to add one file for each socket:

transform/ALL4176switch_1.js

(function(dataString) {
    var data = JSON.parse(dataString);
    var value = 'UNDEF';
    for (var i = 0; i < data.length; i++) {
        if (data[i].id == '1') {
            value = data[i].value;
            break;
        }
    }
    if (value != 'UNDEF') {
        if (value == '0.00') {
            value = 'OFF';
        } else {
            value = 'ON';
        }
    }
    return value;
})(input)

Do this for socket 2 to 6 by replacing 1 in filename and '1' in line 5 of the script by corresponding socket number.

  1. Add items
    Now we can add our items:

items/ALL4176.items

Switch ALL4176_Relais1        "Relais 1"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=1&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=1&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais1Status  "Relais 1 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_1.js)]" }
Switch ALL4176_Relais2        "Relais 2"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=2&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=2&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais2Status  "Relais 2 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_2.js)]" }
Switch ALL4176_Relais3        "Relais 3"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=3&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=3&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais3Status  "Relais 3 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_3.js)]" }
Switch ALL4176_Relais4        "Relais 4"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=4&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=4&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais4Status  "Relais 4 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_4.js)]" }
Switch ALL4176_Relais5        "Relais 5"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=5&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=5&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais5Status  "Relais 5 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_5.js)]" }
Switch ALL4176_Relais6        "Relais 6"      <poweroutlet> { http=">[ON:POST:http://<ipaddress>/xml/jsonswitch.php?id=6&set=1{Authorization=Basic <base64User:Password>}] >[OFF:POST:http://<ipaddress>/xml/jsonswitch.php?id=6&set=0{Authorization=Basic <base64User:Password>}]" }
Switch ALL4176_Relais6Status  "Relais 6 [%s]"               { http="<[ALL4176_StatusCache:1000:JS(ALL4176switch_6.js)]" }

Number:ElectricPotential ALL4176_Voltage   "Voltage [%.2f V]"    <line> { http="<[ALL4176_StatusCache:10000:JSONPATH($[?(@.id == '14')].value)]" }
Number:ElectricCurrent   ALL4176_Current   "Current [%.2f A]"    <line> { http="<[ALL4176_StatusCache:10000:JSONPATH($[?(@.id == '15')].value)]" }
Number:Power             ALL4176_Power     "Power [%.2f W]"      <line> { http="<[ALL4176_StatusCache:10000:JSONPATH($[?(@.id == '16')].value)]" }
Number:Frequency         ALL4176_Frequency "Frequency [%.2f Hz]" <line> { http="<[ALL4176_StatusCache:10000:JSONPATH($[?(@.id == '18')].value)]" }
  1. Make a rule to keep hardware status in sync
    Device has buttons on each socket to switch on/off a socket, so we need to keep track of that change in OpenHAB too. We do this with a rule, updating our items when status changes

rules/ALL4176_Sensors.rules

rule "Update ALL4176 Relais status from hardware"
when
    Item ALL4176_Relais1Status changed or
    Item ALL4176_Relais2Status changed or
    Item ALL4176_Relais3Status changed or
    Item ALL4176_Relais4Status changed or
    Item ALL4176_Relais5Status changed or
    Item ALL4176_Relais6Status changed
then
    if(ALL4176_Relais1Status.state != ALL4176_Relais1.state)   { ALL4176_Relais3.postUpdate(ALL4176_Relais1Status.state) }
    if(ALL4176_Relais2Status.state != ALL4176_Relais2.state)   { ALL4176_Relais4.postUpdate(ALL4176_Relais2Status.state) }
    if(ALL4176_Relais3Status.state != ALL4176_Relais3.state)   { ALL4176_Relais3.postUpdate(ALL4176_Relais3Status.state) }
    if(ALL4176_Relais4Status.state != ALL4176_Relais4.state)   { ALL4176_Relais4.postUpdate(ALL4176_Relais4Status.state) }
    if(ALL4176_Relais5Status.state != ALL4176_Relais5.state)   { ALL4176_Relais5.postUpdate(ALL4176_Relais5Status.state) }
    if(ALL4176_Relais6Status.state != ALL4176_Relais6.state)   { ALL4176_Relais6.postUpdate(ALL4176_Relais6Status.state) }
end
  1. Add items to your existing sitemap
Frame label="ALL4176 Relais" {
    Switch item=ALL4176_Relais1
    Switch item=ALL4176_Relais2
    Switch item=ALL4176_Relais3
    Switch item=ALL4176_Relais4
    Switch item=ALL4176_Relais5
    Switch item=ALL4176_Relais6
}
Frame label="ALL4176 Sensors" {
    Text item=ALL4176_Voltage
    Text item=ALL4176_Current
    Text item=ALL4176_Power
    Text item=ALL4176_Frequency
}
Frame label="ALL4176 Relais status (for debugging)" {
    Text item=ALL4176_Relais1Status
    Text item=ALL4176_Relais2Status
    Text item=ALL4176_Relais3Status
    Text item=ALL4176_Relais4Status
    Text item=ALL4176_Relais5Status
    Text item=ALL4176_Relais6Status
}

Volà, we are done.

Notes
This configuration will update status/sensors once a second, I found that to be enough.
Switch actions from OpenHAB will generate a HTTP request immediately.

Further work
Provided JSON string provides more sensors like cos ϕ, USB monitoring, connected sensors (sold seperately), … even the name of the sockets and their color configured in HTTP interface are available.
Add items as you need, just remember to refer to them by their ID as I did in above examples.
With mode=info in URL you can get network configuration, MAC, uptime (as string), memory, … of the device, I didn’t have use for that.

Known Bugs
Measured power can sometimes be negative, I observed »-0.1 W«, so keep that in mind when you write rules based on that value.

Questions and suggestions for improvement are welcome!

2 Likes

Related topics that led to this solution:
How to pass an aditional parameter to JS transform in item definition
[SOLVED] Use jsonPath in JavaScript transformation?
HTTP binding outages of 1-3 minutes - why?

Thanks @vzorglub, @lfs_alp5, @wborn for pointing me the right directions and @dim, @mhilbush, @rlkoshak for helping me with bugs/errors along that way.

1 Like