diff --git a/bundles/org.openhab.binding.shelly/README.md b/bundles/org.openhab.binding.shelly/README.md index d97e9b24c8ca..5dc297d93595 100644 --- a/bundles/org.openhab.binding.shelly/README.md +++ b/bundles/org.openhab.binding.shelly/README.md @@ -129,6 +129,9 @@ end |----------|-------------|---------|---------|---------------------------------------------------------------------------------| |relay |output |Switch |r/w |Controls the relay's output channel (on/off) | | |input |Switch |yes |ON: Input/Button is powered, see General Notes on Channels | +|sensors |temperature1 |Number |yes |Temperature value of external sensor #1 (if connected to device) | +| |temperature2 |Number |yes |Temperature value of external sensor #2 (if connected to device) | +| |temperature3 |Number |yes |Temperature value of external sensor #3 (if connected to device) | ### Shelly 1PM (thing-type: shelly1pm) @@ -143,6 +146,9 @@ end | |lastPower3 |Number |yes |Energy consumption in Watts for a round minute, 3 minutes ago | | |totalKWH |Number |yes |Total energy consumption in Watts since the device powered up (reset on restart) | | |timestamp |String |yes |Timestamp of the last measurement | +|sensors |temperature1 |Number |yes |Temperature value of external sensor #1 (if connected to device) | +| |temperature2 |Number |yes |Temperature value of external sensor #2 (if connected to device) | +| |temperature3 |Number |yes |Temperature value of external sensor #3 (if connected to device) | ### Shelly EM (thing-type: shellyem) diff --git a/bundles/org.openhab.binding.shelly/doc/DEVNOTES - API JSON Samples.md b/bundles/org.openhab.binding.shelly/doc/DEVNOTES - API JSON Samples.md deleted file mode 100644 index eec7d0298ca9..000000000000 --- a/bundles/org.openhab.binding.shelly/doc/DEVNOTES - API JSON Samples.md +++ /dev/null @@ -1,1722 +0,0 @@ -# Shelly Binding (org.openhab.binding.shelly) - -This openHAB 2 Binding implements control for the Shelly series of devices. -This includes sending commands to the devices as well as reading the device status and sensor data. - -Author: Markus Michels (markus7017) -Check https://community.openhab.org/t/shelly-binding/ for more information, questions and contributing ideas. Any comments are welcome! - -Also check section **Additional Information** at the end of the document. -This includes some general comments, information how to debug and request new features. - ---- - -### Alpha/Beta versions - -The binding is work in progress. You have to expect bugs etc. and each version might be incompatible to the existing thing definition, which means no backware compatibility. - -Channel definitions are subject to change with any alpha or beta release. Please make sure to **delete all Shelly things before updating*** the binding and clean out the JSON DB: - -- **remove all shelly entries from paperui** -- stop oh2 service -- openhab-cli clear-cache -- copy jar into addons (set correct permission) -- start oh2 service -- **re-discover things** -- the channel/item linkage should be restored automatically - -If you hit a problem make sure to post a TRACE log (or send PM) so I could look into the details. - -### Instalation - -As described above the binding will be installed by copying the jar into the addons folder of your OH installation. -Once a stable state is reached the binding may become part of the openHAB 2.5 distribution, but this will take some time. -The binding was developed an tested on OH version 2.4 and 2.5. -Please post an info if you also verified compatibility to version 2.3. -However, this release is not officially supported. - -# Additional Notes - -## General - -* You should use firmware version 1.5.2 or never. -It might be that the binding is working with older versions, but this was never tested. -List of Firmware Versions for the different devices could be found here: https://api.shelly.cloud/files/firmware - - -* If you gave multiple network interfaces you should check openHAB's default setting. - -Open PaperUI and go to Configuration:System-:Network Settings and verify the selected interface. -If the Shelly devices are not on the same network you could try to add them manually. -However, devices in different networks have not been tested yet (please post a comment in the community thread if you are successful). - -## Reporting a problem/bug - -If you encounter a problem you could put the device into DEBUG or TRACE mode - -- open OH console (execute "openhab-cli console") -- set the debug level ("log:set DEBUG org.openhab.binding.shelly") -- issue command or wait until problem occurs -- post an extract of openhab.log to the community thread (or send the author a PM - make sure the log extract has enough information, some more lines are fine) - -## Feature Request - -Any comment or feature request is welcome. Post the idea to the community thread, all of us will benefit. - -## Other devices - -The thing definition of the following devices is primarily. -If you have one of those devices send a PM to marks7017 and we could work on the implementation/testing. - -- thing-type: shellysmoke -- thing-type: shellysense -- thing-type: shellyplug - -## Supporting new devices - -You could help to integrate and support new devices. In general the following information is a good start - -- open a browser and issue the following urls -- http://<device ip>/settings -- http://<device ip>/status - -once basic discovery is implemented the Coap Discription could be discovered - -- enable CoIoT events within the thing configuration -- open the thing properties ([Show Properties]) -- and copy&paste the coapDescr property - -post this information in the community thread or send a PM to the author. -Depending on the device type and complexity of the integration you should be prepared to run test cycles with snapshort binds of the binding incl. back and forth communication with the author. - -# REST API JSON Sample Data - -## Shelly1 - -### Shelly1: /status/relay/0 - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.1","rssi":-70}, - "cloud":{"enabled":false, "connected":false}, - "mqtt":{"connected":true}, - "time":"15:36","serial":1,"has_update":false,"mac":"XXXXXXXXXXXX", - "relays" :[ - {"ison":false,"has_timer":false} - ], - "meters":[ - {"power":0.00,"is_valid":"true"} - ], - "update":{"status":"idle","has_update":false,"new_version":"20190711-084053/v1.5.0-hotfix4@3b4f7414","old_version":"20190711-084053/v1.5.0-hotfix4@3b4f7414"}, - "ram_total":51104,"ram_free":40356,"fs_size":233681,"fs_free":175951,"uptime":3455 -} -``` - -### COAP Device Description Shelly1 - -``` -{ - "blk":[ - {"I":0,"D":"Relay0"} - ], - "sen":[ - {"I":112,"T":"Switch","R":"0/1","L":0} - ], - "act":[ - {"I":211,"D":"Switch","L":0,"P":[ - {"I":2011,"D":"ToState","R":"0/1"} - ] - } - ] -} -``` - - -## Shelly 1PM - -### Shelly 1PM - /settings - -``` -{ - "device": { - "type": "SHSW-PM", - "mac": "XXXXXXXX", - "hostname": "shelly1pm-XXXXXX", - "num_outputs": 1, - "num_meters": 1 - }, - "wifi_ap": { - "enabled": false, - "ssid": "shelly1pm-XXXXXX", - "key": "" - }, - "wifi_sta": { - "enabled": true, - "ssid": "iot-wlan", - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "wifi_sta1": { - "enabled": false, - "ssid": null, - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "mqtt": { - "enable": false, - "server": "10.0.0.2:1883", - "user": "", - "id": "shelly1pm-XXXXXX", - "reconnect_timeout_max": 60.0, - "reconnect_timeout_min": 2.0, - "clean_session": true, - "keep_alive": 60, - "max_qos": 0, - "retain": false, - "update_period": 30 - }, - "sntp": { - "server": "time.google.com" - }, - "login": { - "enabled": false, - "unprotected": false, - "username": "admin", - "password": "admin" - }, - "pin_code": "RPSR$p", - "name": "", - "fw": "20191127-095910/v1.5.6@0d769d69", - "build_info": { - "build_id": "20191127-095910/v1.5.6@0d769d69", - "build_timestamp": "2019-11-27T09:59:10Z", - "build_version": "1.0" - }, - "cloud": { - "enabled": true, - "connected": true - }, - "timezone": "Europe/Berlin", - "lat": 50.252491, - "lng": 5.779092, - "tzautodetect": false, - "time": "12:41", - "hwinfo": { - "hw_revision": "prod-190329", - "batch_id": 1 - }, - "max_power": 3500, - "mode": "relay", - "relays": [ - { - "name": null, - "ison": false, - "has_timer": false, - "default_state": "off", - "btn_type": "edge", - "btn_reverse": 0, - "auto_on": 0.0, - "auto_off": 0.0, - "btn_on_url": null, - "btn_off_url": null, - "out_on_url": "http://10.0.0.20:8080/shelly/event/shelly1pm-e5bed0/relay/0?type=out_on", - "out_off_url": "http://10.0.0.2:8080/shelly/event/shelly1pm-e5bed0/relay/0?type=out_off", - "longpush_url": null, - "shortpush_url": null, - "schedule": false, - "schedule_rules": [], - "max_power": 3500 - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117676, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 2262 - } - ] -} -``` - -### Shelly 1PM /status - -``` -{ - "wifi_sta": { - "connected": true, - "ssid": "iot-wlan", - "ip": "10.0.0.2", - "rssi": -49 - }, - "cloud": { - "enabled": true, - "connected": true - }, - "mqtt": { - "connected": false - }, - "time": "12:41", - "serial": 23, - "has_update": false, - "mac": "XXXXXXXXXXXX", - "relays": [ - { - "ison": false, - "has_timer": false, - "overpower": false - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117691, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 2262 - } - ], - "inputs": [ - { - "input": 0 - } - ], - "ext_temperature": {}, - "temperature": 45.51, - "overtemperature": false, - "tmp": { - "tC": 45.51, - "tF": 113.93, - "is_valid": "true" - }, - "update": { - "status": "idle", - "has_update": false, - "new_version": "20191127-095910/v1.5.6@0d769d69", - "old_version": "20191127-095910/v1.5.6@0d769d69" - }, - "ram_total": 50704, - "ram_free": 35428, - "fs_size": 233681, - "fs_free": 172437, - "uptime": 237010 -} -``` - -## Shelly2 - -### /settings - -``` -{ - "device" : { - "type":"SHSW-21","mac":"XXXXXXXXXXXX","hostname":"shellyswitch-XXXXXX", - "num_outputs":2,"num_meters":1,"num_rollers":1 - }, - "wifi_ap":{"enabled":false,"ssid":"shellyswitch-XXXXXX","key":"}, - "wifi_sta":{"enabled":true,"ssid":"iot-wlan","ipv4_method":"static","ip":"10.0.0.10","gw":"10.0.0.1","mask":"255.0.0.0","dns":"10.0.0.1"}, - "wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":true,"server":"10.0.0.7:1883","user":"admin","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000, - "clean_session":true,"keep_alive":60,"will_topic":"shellies/shellyswitch-XXXXXX/online","will_message":"false", max_qos":0,"retain":true,"update_period":30}, - "sntp": {"server":"time.google.com"}, - "login":{"enabled":true,"unprotected":false,"username":"xxx","password":"xxx"},"pin_code":"", - "coiot_execute_enable":true,"name":"", - "fw":"20190531-075812/v1.5.0-hotfix2@022ec015","build_info":{"build_id":"20190531-075812/v1.5.0-hotfix2@022ec015","build_timestamp":"2019-05-31T07:58:12Z","build_version":"1.0"}, - "cloud":{"enabled":false,"connected":false}, - "timezone":"Europe/Berlin","lat":45.864700,"lng":7.625460,"tzautodetect":true,"time":"23:02", - "hwinfo":{"hw_revision":"prod-2018-10c", "batch_id":5}, - "mode":"relay","max_power":1840, - "relays":[ - { - "name":null,"ison":false,"has_timer":false,"overpower":falsem "default_state":"last","btn_type":"edge", "btn_reverse":0, - "auto_on":0.00,"auto_off":0.00,"btn_on_url":null,"btn_off_url":null,"out_on_url":null,"out_off_url":null,"schedule":false, - "schedule_rules":[] - }, - { - "name":null,"ison":false,"has_timer":false,"overpower":false,"default_state":"off","btn_type":"edge","btn_reverse":0, - "auto_on":0.00,"auto_off":0.00, - "btn_on_url":null,"btn_off_url":null,"out_on_url":null,"out_off_url":null, - "schedule":false,"schedule_rules":[]} - ], - "rollers":[ - { - "maxtime":20.00,"maxtime_open":20.00,"maxtime_close":20.00,"default_state":"stop","swap":false,"swap_inputs":false,"input_mode":"openclose", - "button_type":"toggle","btn_reverse":0, - "state":"stop", - "power":0.00, - "is_valid":true,"safety_switch":false, - "schedule":false,"schedule_rules":[], - "obstacle_mode":"disabled","obstacle_action":"stop","obstacle_power":200,"obstacle_delay":1,"safety_mode":"while_opening","safety_action":"stop", - "safety_allowed_on_trigger":"none","off_power":2, - "positioning":true - } - ], - "meters":[ - {"power":0.00,"is_valid":true,"timestamp":1562713329,"counters":[0.000, 0.000, 0.000],"total":19111} - ] - } -``` - -### Shelly 2 /settings/relay/0 - -``` -{ - "name":null, "ison":false,"has_timer":false, - "overpower":false,"default_state":"last", - "btn_type":"edge","btn_reverse":0, - "auto_on":0.00,"auto_off":0.00, - "btn_on_url":null, - "btn_off_url":null, - "out_on_url":null, - "out_off_url":null, - "schedule":false, - "schedule_rules":[] -} -``` - -### Shelly 2: /status/relay/0 - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.1","rssi":-70}, - "cloud":{"enabled":false, "connected":false}, - "mqtt":{"connected":true}, - "time":"15:36","serial":1,"has_update":false,"mac":"XXXXXXXXXXXX","serial":1, - "has_update":true,"mac":"XXXXXXXXXXXX", - "relays":[ - {"ison":false,"has_timer":false,"overpower":false,"is_valid":true}, - {"ison":false,"has_timer":false,"overpower":false,"is_valid":true} - ], - "rollers":[ - {"state":"stop","power":0.00,"is_valid":true,"safety_switch":false,"stop_reason":"normal","last_direction":"open","current_pos":101,"calibrating":false,"positioning":true} - ], - "meters":[ - {"power":0.00,"is_valid":true,"timestamp":1563292829,"counters":[0.000, 0.000, 0.000],"total":35473} - ], - "update":{"status":"pending","has_update":true,"new_version":"20190711-084105/v1.5.0-hotfix4@3b4f7414","old_version":"20190531-075812/v1.5.0-hotfix2@022ec015"}, - "ram_total":50264,"ram_free":37548, - "fs_size":233681, - "fs_free":155620, - "uptime":1352018 -} -``` - - -### Shelly2: /status/device - -``` -{ - "enabled":true, "ssid":"iot-wlan", "ipv4_method":"static","ip":"10.0.0.10","gw":"10.0.0.1","mask":"255.0.0.0","dns":"10.0.0.1" - -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.1","rssi":-69}, - "cloud":{"enabled":false,"connected":false}, - "mqtt":{"connected":true}, - "time":"00:17","serial":1,"has_update":false,"mac":"XXXXXXXXXXXX", - "relays":[ - { - "ison":false, - "has_timer":false, - "overpower":false, - "is_valid":true - }, - { - "ison":false, - "has_timer":false, - "overpower":false, - "is_valid":true - } - ], - "rollers":[ - { - "state":"stop", - "power":0.00, - "is_valid":true, - "safety_switch":false, - "stop_reason":"normal", - "last_direction":"stop", - "current_pos":101, - "calibrating":false, - "positioning":true - } - ], - "meters":[ - { - "power":0.00, - "is_valid":true, - "timestamp":1562717876, - "counters":[0.000, 0.000, 0.000], - "total":19111 - } - ], - "update":{ - "status":"idle", - "has_update":false, - "new_version":"20190531-075812/v1.5.0-hotfix2@022ec015", - "old_version":"20190531-075812/v1.5.0-hotfix2@022ec015" - }, - "ram_total":50264,"ram_free":37884,"fs_size":233681,"fs_free":156373,"uptime":777069 -} -``` - -## Shelly 2.5 - -### Shelly 2.5-Relay: /settings - -``` -{ - "device": { - "type": "SHSW-25", - "mac": "XXXXXXXXXXXX", - "hostname": "shellyswitch25-XXXXXX", - "num_outputs": 2, - "num_meters": 2, - "num_rollers": 1 - }, - "wifi_ap": { - "enabled": false, - "ssid": "shellyswitch25-XXXXXX", - "key": "" - }, - "wifi_sta": { - "enabled": true, - "ssid": "iot-wlan", - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "wifi_sta1": { - "enabled": false, - "ssid": null, - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "mqtt": { - "enable": false, - "server": "10.0.0.2:1883", - "user": "", - "id": "shellyswitch25-XXXXXX", - "reconnect_timeout_max": 60.0, - "reconnect_timeout_min": 2.0, - "clean_session": true, - "keep_alive": 60, - "max_qos": 0, - "retain": false, - "update_period": 30 - }, - "sntp": { - "server": "time.google.com" - }, - "login": { - "enabled": false, - "unprotected": false, - "username": "admin", - "password": "admin" - }, - "pin_code": "Y}e!BK", - "name": "", - "fw": "20191127-095444/v1.5.6@0d769d69", - "build_info": { - "build_id": "20191127-095444/v1.5.6@0d769d69", - "build_timestamp": "2019-11-27T09:54:44Z", - "build_version": "1.0" - }, - "cloud": { - "enabled": true, - "connected": true - }, - "timezone": "Europe/Berlin", - "lat": 50.252491, - "lng": 5.779092, - "tzautodetect": false, - "time": "12:42", - "hwinfo": { - "hw_revision": "prod-2019-03", - "batch_id": 1 - }, - "mode": "relay", - "max_power": 1840, - "relays": [ - { - "name": null, - "ison": false, - "has_timer": false, - "overpower": false, - "default_state": "off", - "btn_type": "edge", - "btn_reverse": 0, - "auto_on": 0.0, - "auto_off": 0.0, - "max_power": 0, - "btn_on_url": null, - "btn_off_url": null, - "out_on_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-0043e0/relay/0?type=out_on", - "out_off_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-0043e0/relay/0?type=out_off", - "longpush_url": null, - "shortpush_url": null, - "schedule": false, - "schedule_rules": [] - }, - { - "name": null, - "ison": false, - "has_timer": false, - "overpower": false, - "default_state": "off", - "btn_type": "edge", - "btn_reverse": 0, - "auto_on": 0.0, - "auto_off": 0.0, - "max_power": 0, - "btn_on_url": null, - "btn_off_url": null, - "out_on_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-0043e0/relay/1?type=out_on", - "out_off_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-0043e0/relay/1?type=out_off", - "longpush_url": null, - "shortpush_url": null, - "schedule": false, - "schedule_rules": [] - } - ], - "rollers": [ - { - "maxtime": 20.0, - "maxtime_open": 20.0, - "maxtime_close": 20.0, - "default_state": "stop", - "swap": false, - "swap_inputs": false, - "input_mode": "openclose", - "button_type": "toggle", - "btn_reverse": 0, - "state": "stop", - "power": 0.0, - "is_valid": true, - "safety_switch": false, - "roller_open_url": null, - "roller_close_url": null, - "roller_stop_url": null, - "schedule": false, - "schedule_rules": [], - "obstacle_mode": "disabled", - "obstacle_action": "stop", - "obstacle_power": 200, - "obstacle_delay": 1, - "safety_mode": "while_opening", - "safety_action": "stop", - "safety_allowed_on_trigger": "none", - "off_power": 2, - "positioning": true - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117725, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 47 - }, - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117725, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 10215 - } - ] -} -``` - -### Shelly 2.5 Relay Mode: /status - -``` -{ - "wifi_sta": { - "connected": true, - "ssid": "iot_wlan", - "ip": "10.0.0.2", - "rssi": -48 - }, - "cloud": { - "enabled": true, - "connected": true - }, - "mqtt": { - "connected": false - }, - "time": "12:42", - "serial": 83, - "has_update": false, - "mac": "XXXXXXXXXXXX", - "relays": [ - { - "ison": false, - "has_timer": false, - "overpower": false, - "overtemperature": false, - "is_valid": true - }, - { - "ison": false, - "has_timer": false, - "overpower": false, - "overtemperature": false, - "is_valid": true - } - ], - "rollers": [ - { - "state": "stop", - "power": 0.0, - "is_valid": true, - "safety_switch": false, - "overtemperature": false, - "stop_reason": "normal", - "last_direction": "stop", - "current_pos": 101, - "calibrating": false, - "positioning": true - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117739, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 47 - }, - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117739, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 10215 - } - ], - "inputs": [ - { - "input": 0 - }, - { - "input": 0 - } - ], - "temperature": 61.76, - "overtemperature": false, - "tmp": { - "tC": 61.76, - "tF": 143.16, - "is_valid": "true" - }, - "update": { - "status": "idle", - "has_update": false, - "new_version": "20191127-095444/v1.5.6@0d769d69", - "old_version": "20191127-095444/v1.5.6@0d769d69" - }, - "ram_total": 49568, - "ram_free": 34720, - "fs_size": 233681, - "fs_free": 156624, - "voltage": 237.72, - "uptime": 237037 -} -``` - -### Shelly 2.5 Generic Coap Status - -``` -{ - "G":[ - [0,112,0], - [0,122,0], - [0,111,0.000000] - ] -} -``` - -### Shelly 2.5 Coap Description - - -``` -{"blk":[ - {"I":0,"D":"Relay0"},{"I":1,"D":"Relay1"}, - {"I":2,"D":"Device"}],"sen":[ - {"I":112,"T":"S","D":"State","R":"0/1","L":0}, - {"I":122,"T":"S","D":"State","R":"0/1","L":1}, - {"I":111,"T":"W","D":"Power","R":"0/2300","L":0}, - {"I":121,"T":"W","D":"Power","R":"0/2300","L":1}, - {"I":113,"T":"S","D":"Position","R":"0/100","L":2} - ], - "act":[ - {"I":211,"D":"Switch","L":0,"P":[{"I":2011,"D":"ToState","R":"0/1"}]}, - {"I":221,"D":"Switch","L":1,"P":[{"I":2021,"D":"ToState","R":"0/1"}]} - ] -} -``` - - -``` -{ - "blk":[ - {"I":0,"D":"Relay0"}, - {"I":1,"D":"Relay1"}, - {"I":2,"D":"Device"} - ], - "sen":[ - {"I":112,"T":"S","D":"State","R":"0/1","L":0}, - {"I":122,"T":"S","D":"State","R":"0/1","L":1}, - {"I":111,"T":"W","D":"Power","R":"0/3680","L":2}, - {"I":113,"T":"S","D":"Position","R":"0/100","L":2} - ], - "act":[ - {"I":211,"D":"Switch","L":0,"P":[ - {"I":2011,"D":"ToState","R":"0/1"} - ] - }, - {"I":221,"D":"Switch","L":1,"P":[ - {"I":2021,"D":"ToState","R":"0/1"} - ] - }] -} -``` - -### SHelly 2.5 Roller Mode: /settings - -``` -{ - "device": { - "type": "SHSW-25", - "mac": "XXXXXXXXXXXX", - "hostname": "shellyswitch25-XXXXXX", - "num_outputs": 2, - "num_meters": 2, - "num_rollers": 1 - }, - "wifi_ap": { - "enabled": false, - "ssid": "shellyswitch25-XXXXXX", - "key": "" - }, - "wifi_sta": { - "enabled": true, - "ssid": "iot-wlan", - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "wifi_sta1": { - "enabled": false, - "ssid": null, - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "mqtt": { - "enable": false, - "server": "10.0.0.2:1883", - "user": "", - "id": "shellyswitch25-XXXXXX", - "reconnect_timeout_max": 60.0, - "reconnect_timeout_min": 2.0, - "clean_session": true, - "keep_alive": 60, - "max_qos": 0, - "retain": false, - "update_period": 30 - }, - "sntp": { - "server": "time.google.com" - }, - "login": { - "enabled": false, - "unprotected": false, - "username": "admin", - "password": "admin" - }, - "pin_code": "!pw5e5", - "name": "", - "fw": "20191127-095444/v1.5.6@0d769d69", - "build_info": { - "build_id": "20191127-095444/v1.5.6@0d769d69", - "build_timestamp": "2019-11-27T09:54:44Z", - "build_version": "1.0" - }, - "cloud": { - "enabled": true, - "connected": true - }, - "timezone": "Europe/Berlin", - "lat": 50.252491, - "lng": 5.779092, - "tzautodetect": false, - "time": "12:42", - "hwinfo": { - "hw_revision": "prod-2019-03", - "batch_id": 1 - }, - "mode": "roller", - "max_power": 1840, - "relays": [ - { - "name": null, - "ison": false, - "has_timer": false, - "overpower": false, - "default_state": "off", - "btn_type": "toggle", - "btn_reverse": 0, - "auto_on": 0.0, - "auto_off": 0.0, - "max_power": 0, - "btn_on_url": null, - "btn_off_url": null, - "out_on_url": null, - "out_off_url": null, - "longpush_url": null, - "shortpush_url": null, - "schedule": false, - "schedule_rules": [] - }, - { - "name": null, - "ison": false, - "has_timer": false, - "overpower": false, - "default_state": "off", - "btn_type": "toggle", - "btn_reverse": 0, - "auto_on": 0.0, - "auto_off": 0.0, - "max_power": 0, - "btn_on_url": null, - "btn_off_url": null, - "out_on_url": null, - "out_off_url": null, - "longpush_url": null, - "shortpush_url": null, - "schedule": false, - "schedule_rules": [] - } - ], - "rollers": [ - { - "maxtime": 20.0, - "maxtime_open": 23.0, - "maxtime_close": 22.0, - "default_state": "stop", - "swap": false, - "swap_inputs": false, - "input_mode": "openclose", - "button_type": "momentary", - "btn_reverse": 0, - "state": "stop", - "power": 0.0, - "is_valid": true, - "safety_switch": false, - "roller_open_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-XXXXXX/roller/0?type=roller_open", - "roller_close_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-XXXXXX/roller/0?type=roller_close", - "roller_stop_url": "http://10.0.0.2:8080/shelly/event/shellyswitch25-XXXXXX/roller/0?type=roller_stop", - "schedule": false, - "schedule_rules": [ - "0700-0123456-10%", - "0000bss-0123456-open" - ], - "obstacle_mode": "disabled", - "obstacle_action": "stop", - "obstacle_power": 200, - "obstacle_delay": 1, - "safety_mode": "while_opening", - "safety_action": "stop", - "safety_allowed_on_trigger": "none", - "off_power": 2, - "positioning": true - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117752, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 44 - }, - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117752, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 44 - } - ] -} -``` - -### Shelly 2.5 Roller Mode: /status - -``` -{ - "wifi_sta": { - "connected": true, - "ssid": "iot_wlan", - "ip": "10.0.0.1", - "rssi": -54 - }, - "cloud": { - "enabled": true, - "connected": true - }, - "mqtt": { - "connected": false - }, - "time": "12:42", - "serial": 16, - "has_update": false, - "mac": "XXXXXXXXXXXX", - "relays": [ - { - "ison": false, - "has_timer": false, - "overpower": false, - "overtemperature": false, - "is_valid": true - }, - { - "ison": false, - "has_timer": false, - "overpower": false, - "overtemperature": false, - "is_valid": true - } - ], - "rollers": [ - { - "state": "stop", - "power": 0.0, - "is_valid": true, - "safety_switch": false, - "overtemperature": false, - "stop_reason": "normal", - "last_direction": "open", - "current_pos": 100, - "calibrating": false, - "positioning": true - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117766, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 44 - }, - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117766, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 44 - } - ], - "inputs": [ - { - "input": 0 - }, - { - "input": 0 - } - ], - "temperature": 63.62, - "overtemperature": false, - "tmp": { - "tC": 63.62, - "tF": 146.52, - "is_valid": "true" - }, - "update": { - "status": "idle", - "has_update": false, - "new_version": "20191127-095444/v1.5.6@0d769d69", - "old_version": "20191127-095444/v1.5.6@0d769d69" - }, - "ram_total": 49568, - "ram_free": 34712, - "fs_size": 233681, - "fs_free": 156122, - "voltage": 231.83, - "uptime": 237263 -} -``` - - - -## Shelly Plug-S - -###Shelly Plug-S: /settings - -``` -{ - "device": { - "type": "SHPLG-S", - "mac": "XXXXXXXXXXXX", - "hostname": "shellyplug-s-XXXX", - "num_outputs": 1, - "num_meters": 1 - }, - "wifi_ap": { - "enabled": false, - "ssid": "shellyplug-s-XXXX", - "key": "" - }, - "wifi_sta": { - "enabled": true, - "ssid": "iot-wlan", - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "wifi_sta1": { - "enabled": false, - "ssid": null, - "ipv4_method": "dhcp", - "ip": null, - "gw": null, - "mask": null, - "dns": null - }, - "mqtt": { - "enable": false, - "server": "10.0.0.2:1883", - "user": "", - "id": "shellyplug-s-XXXXXX", - "reconnect_timeout_max": 60.0, - "reconnect_timeout_min": 2.0, - "clean_session": true, - "keep_alive": 60, - "max_qos": 0, - "retain": false, - "update_period": 30 - }, - "sntp": { - "server": "time.google.com" - }, - "login": { - "enabled": false, - "unprotected": false, - "username": "admin", - "password": "admin" - }, - "pin_code": "adIL-{", - "name": "", - "fw": "20191127-095857/v1.5.6@0d769d69", - "build_info": { - "build_id": "20191127-095857/v1.5.6@0d769d69", - "build_timestamp": "2019-11-27T09:58:57Z", - "build_version": "1.0" - }, - "cloud": { - "enabled": true, - "connected": true - }, - "timezone": "Europe/Berlin", - "lat": 50.252491, - "lng": 5.779092, - "tzautodetect": false, - "time": "12:43", - "hwinfo": { - "hw_revision": "prod-190516", - "batch_id": 1 - }, - "max_power": 2500, - "led_status_disable": true, - "led_power_disable": false, - "relays": [ - { - "ison": false, - "has_timer": false, - "overpower": false, - "default_state": "off", - "auto_on": 0.0, - "auto_off": 0.0, - "btn_on_url": null, - "out_on_url": "http://10.0.0.1:8080/shelly/event/shellyplug-s-041b29/relay/0?type=out_on", - "out_off_url": "http://10.0.0.1:8080/shelly/event/shellyplug-s-041b29/relay/0?type=out_off", - "schedule": true, - "schedule_rules": [ - "0700-0123456-off" - ], - "max_power": 2500 - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117787, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 0 - } - ] -}``` - -### Shelly Plug-S: /status - -{ - "wifi_sta": { - "connected": true, - "ssid": "iot_wlan", - "ip": "10.0.0.2", - "rssi": -52 - }, - "cloud": { - "enabled": true, - "connected": true - }, - "mqtt": { - "connected": false - }, - "time": "12:43", - "serial": 1, - "has_update": false, - "mac": "XXXXXXXXXXXX", - "relays": [ - { - "ison": false, - "has_timer": false, - "overpower": false - } - ], - "meters": [ - { - "power": 0.0, - "is_valid": true, - "timestamp": 1575117798, - "counters": [ - 0.0, - 0.0, - 0.0 - ], - "total": 0 - } - ], - "temperature": 30.71, - "overtemperature": false, - "tmp": { - "tC": 30.71, - "tF": 87.28, - "is_valid": "true" - }, - "update": { - "status": "idle", - "has_update": false, - "new_version": "20191127-095857/v1.5.6@0d769d69", - "old_version": "20191127-095857/v1.5.6@0d769d69" - }, - "ram_total": 50784, - "ram_free": 37312, - "fs_size": 233681, - "fs_free": 173441, - "uptime": 237171 -} -``` - -### ### Shelly Plug-S Coap Description - -``` -{ - “blk”:[ - {“I”:0,“D”:“Relay0”} - ], - “sen”:[ - {“I”:111,“T”:“W”,“R”:“0/2500”,“L”:0}, - {“I”:112,“T”:“Switch”,“R”:“0/1”,“L”:0}, - {“I”:113,“T”:“tC”,“R”:"-40/300",“L”:0}, - {“I”:114,“T”:“tF”,“R”:"-40/300",“L”:0}, - {“I”:115,“T”:“Overtemp”,“R”:“0/1”,“L”:0} - ], - “act”:[{“I”:211,“D”:“Switch”,“L”:0,“P”:[{“I”:2011,“D”:“ToState”,“R”:“0/1”}]}] - } - - ``` - -## Shelly EM - -### Shelly EM /settings - -``` -{ - "device":{ - "type":"SHEM","mac":"XXXXXXXXXXXX","hostname":"shellyem-XXXXXX", - "num_outputs":1, "num_meters": 0, "num_emeters":2 - }, - "wifi_ap":{"enabled":false,"ssid":"shellyem-XXXXXX","key":""},"wifi_sta":{"enabled":true,"ssid":"iot_wlan","ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null},"wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":false,"server":"10.0.0.1:1883","user":"","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive":60,"will_topic":"shellies/shellyem-XXXXXX/online","will_message":"false","max_qos":0,"retain":false,"update_period":30}, - "sntp": {"server":"time.google.com"},"login":{"enabled":false,"unprotected":false,"username":"admin","password":"admin"},"pin_code":"BZ1Xg+", - "coiot_execute_enable":false,"name":"","fw":"20190821-095337/v1.5.2@4148d2b7","build_info":{"build_id":"20190821-095337/v1.5.2@4148d2b7","build_timestamp":"2019-08-21T09:53:37Z","build_version":"1.0"}, - "cloud":{"enabled":true,"connected":true},"timezone":"Europe/Berlin","lat":45.775398,"lng":9.181760,"tzautodetect":true,"time":"22:50","hwinfo":{"hw_revision":"prod-2019-06", "batch_id":0},"max_power":0, - "relays":[{"name":null,"ison":true,"has_timer":false,"overpower":false,"default_state":"last","auto_on":0.00,"auto_off":0.00,"max_power":0, - "out_on_url":"http://10.0.10.254:8080/shelly/event/shellyem-b9f355/relay/0?type=out_on", - "out_off_url":"http://10.0.10.254:8080/shelly/event/shellyem-b9f355/relay/0?type=out_off","schedule":false, - "schedule_rules":[]}], - "emeters":[{"ctraf_type":120},{"ctraf_type":120}] -} -``` - -### Shelly EM /status - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"172.16.12.26","rssi":-54},"cloud":{"enabled":true,"connected":true}, - "mqtt":{"connected":false},"time":"22:56","serial":13416, - "has_update":false,"mac":"XXXXXXXXXXXX", - "relays":[{"ison":true,"has_timer":false,"overpower":false,"is_valid":true}], - "emeters":[ - {"power":98.55,"reactive":-159.32,"voltage":239.38,"is_valid":true,"total":9188.8,"total_returned":16477.0}, - {"power":0.00,"reactive":0.00,"voltage":239.38,"is_valid":true,"total":0.0,"total_returned":0.0} - ], - "update":{"status":"idle","has_update":false,"new_version":"20190821-095337/v1.5.2@4148d2b7","old_version":"20190821-095337/v1.5.2@4148d2b7"}, - "ram_total":49960,"ram_free":33784,"fs_size":233681,"fs_free":169425,"uptime":174189 -} -``` - -### Shelly Dimmer /settings - -``` -{ - "device":{ - "type":"SHDM-1","mac":"XXXXXXXXXXXX","hostname":"shellydimmer-XXXXXX", - "num_outputs":1,"num_meters":1}, - "wifi_ap":{"enabled":false,"ssid":"shellydimmer-XXXXXX","key":""}, - "wifi_sta":{"enabled":true,"ssid":"iot-wlan","ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":false,"server":"10.0.0.1:1883","user":"","id":"shellydimmer-4200A0","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive":60,"will_topic":"shellies/shellydimmer-4200A0/online","will_message":"false","max_qos":0,"retain":false,"update_period":30}, - "sntp": {"server":"time.google.com"},"login":{"enabled":false,"unprotected":false,"username":"XXXXXX","password":"XXXXXX"},"pin_code":"lFTBFP","coiot_execute_enable":false,"name":"", - "fw":"20191018-133016/master@a8aed1ac","build_info":{"build_id":"20191018-133016/master@a8aed1ac","build_timestamp":"2019-10-18T13:30:16Z","build_version":"1.0"}, - "cloud":{"enabled":true,"connected":true},"timezone":"Europe/Berlin","lat":45.252491,"lng":7.779092,"tzautodetect":false,"time":"06:57", - "hwinfo":{"hw_revision":"dev-prototype","batch_id":0},"mode":"white","pulse_mode":2, - "calibrated":false,"transition":2000,"fade_rate":1, - "lights":[ - { - "name":"","ison":false,"default_state":"off","auto_on":0.00,"auto_off":0.00, - "btn1_on_url":"","btn1_off_url":"","btn2_on_url":"","btn2_off_url":"","out_on_url":"","out_off_url":"", - "schedule":false,"schedule_rules":[], - "btn_type":"edge","swap_inputs":0 - } - ], - "night_mode":{"enabled":0, "start_time":"21:00", "end_time":"00:00", "brightness":10} -} -``` - - -### Shelly Dimmer /status - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.195","rssi":-75}, - "cloud":{"enabled":true,"connected":true}, - "mqtt":{"connected":false}, - "time":"13:35","serial":9496,"has_update":false,"mac":"XXXXXXXXXXXX", - "lights":[ - {"ison":true,"mode":"white","brightness":100} - ], - "meters":[{"power":22.83, "is_valid":true, "timestamp":1568986518,"counters":[8.305, 3.153, 8.892],"total":782}], - "inputs":[ - {"input":0}, - {"input":0} - ], - "tmp":{"tC":56.73,"tF":134.11, "is_valid":"true"}, - "overtemperature":false, - "loaderror":false, - "overload":false - "update":{"status":"unknown","has_update":false,"new_version":"","old_version":"20190913-140549/master@d040e20e"}, - "ram_total":49888,"ram_free":38540,"fs_size":233681,"fs_free":149596,"uptime":561474 -} -``` - - -## Shelly Bulb - -Firmware Version 1.5.2 - -### Shelly Bulb /settings - -``` -{ - "device":{"type":"SHBLB-1","mac":"XXXXXXXXXXXX","hostname":"shellybulb-XXXXXX","num_outputs":1}, - "wifi_ap":{"enabled":false,"ssid":"shellybulb-XXXXXX","key":""}, - "wifi_sta":{"enabled":true,"ssid":iot-wlan","ipv4_method":"static","ip":"10.0.0.10,"gw":"10.0.0.1","mask":"255.0.0.0","dns":"10.0.0.1"}, - "wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":false,"server":"10.0.0.10:1883","user":"","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive";60,"will_topic":"shellies/shellybulb-XXXXXX/online","will_message":"false","max_qos":0,"retain":false,"update_period":30}, - "sntp": {"server":"time.google.com"}, - "login":{"enabled":false,"unprotected":false,"username":"admin","password":"admin"}, - "pin_code":"aXJ9eE","coiot_execute_enable":true,"name":"", - "fw":"20190821-094813/v1.5.2@4148d2b7","build_info":{"build_id":"20190821-094813/v1.5.2@4148d2b7","build_timestamp":"2019-08-21T09:48:13Z","build_version":"1.0"}, - "cloud":{"enabled":true,"connected":true},"timezone":"Europe/Berlin","lat":51.394344,"lng":8.571319,"tzautodetect":false,"time":"10:40", - "hwinfo": {"hw_revision":"prod-1.3","batch_id":1}, - "mode":"color", - "lights":[ - {"ison":true,"red":255,"green":182,"blue":27,"white":0,"gain":100,"temp":3648,"brightness":86,"effect":0,"default_state":"on","auto_on":0.00,"auto_off":0.00,"power":0.00,"schedule":false,"schedule_rules":[]} - ] -} -``` - - -### Shelly Bulb /status - - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlank","ip":"10.0.0.10","rssi":-74}, - "cloud":{"enabled":true,"connected":true},"mqtt":{"connected":false},"time":"10:41","serial":133,"has_update":false,"mac":"XXXXXXXXXXXX", - "lights":[ - {"ison":true,"mode":"color","red":255,"green":182,"blue":27,"white":0,"gain":100,"temp":3648,"brightness":86,"effect":0} - ], - "meters":[{"power":0.00,"is_valid":"true"}], - "update":{"status":"idle","has_update":false,"new_version":"20190821-094813/v1.5.2@4148d2b7","old_version":"20190821-094813/v1.5.2@4148d2b7"}, - "ram_total":51032,"ram_free":37420,"fs_size":233681,"fs_free":171182,"uptime":3125051 -} -``` - -### Shelly Bulb Coap Description - Color Mode - -``` -{ - "blk":[{"I":1,"D":"RGBW"}], - "sen":[ - {"I":111,"T":"Red","R":"0/255","L":0}, - {"I":121,"T":"Green","R":"0/255","L":0}, - {"I":131,"T":"Blue","R":"0/255","L":0}, - {"I":141,"T":"White","R":"0/255","L":0}, - {"I":151,"T":"Gain","R":"0/100","L":0}, - {"I":161,"T":"Temp","R":"3000/6500","L":0}, - {"I":171,"T":"Brightness","R":"0/100","L":0}, - {"I":181,"T":"VSwitch","R":"0/1","L":0} - ], - "act":[ - {"I":211,"D":"RGBW","L":0,"P":[{"I":2011,"T":"Red","R":"0/255"}, - {"I":2021,"T":"Green","R":"0/255"},{"I":2031,"T":"Blue","R":"0/255"}, - {"I":2041,"T":"White","R":"0/255"},{"I":2051,"T":"Gain","R":"0/100"}, - {"I":2061,"T":"Temp","R":"3000/6500"}, - {"I":2071,"T":"Brightness","R":"0/100"}, - {"I":2081,"T":"VSwitch","R":"0/1"}]} - ] -} -``` - -### Shelly Bulb Coap Description - White Mode - -``` -{ - "blk":[{"I":1,"D":"RGBW"}], - "sen":[ - {"I":111,"T":"Red","R":"0/255","L":0}, - {"I":121,"T":"Green","R":"0/255","L":0}, - {"I":131,"T":"Blue","R":"0/255","L":0}, - {"I":141,"T":"White","R":"0/255","L":0}, - {"I":151,"T":"Gain","R":"0/100","L":0}, - {"I":161,"T":"Temp","R":"3000/6500","L":0}, - {"I":171,"T":"Brightness","R":"0/100","L":0}, - {"I":181,"T":"VSwitch","R":"0/1","L":0} - ], - "act":[...] - } - ``` - - -## Shelly RGBW2 - -### Shelly RGW2 /settiings in color mode - -``` -{ - "device":{ - "type":"SHRGBW2", - "mac":"XXXXXXXXXXXX", - "hostname":"shellyrgbw2-XXXXXX", - "num_outputs":4 - }, - "wifi_ap":{"enabled":false, "ssid":"shellyrgbw2-XXXXXX", "key":""}, - "wifi_sta":{"enabled":true,"ssid":"iot-wlan","ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":false,"server":"10.0.0.3:1883","user":"","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive":60,"will_topic":"","will_message":"","max_qos":0,"retain":false,"update_period":30}, - "sntp": {"server":"time.google.com"}," - login":{"enabled":false,"unprotected":false,"xxx":"xxx","password":"xxx"}, - "pin_code":"PIpf!A", - "coiot_execute_enable":false,"name":"", - "fw":"20190711-084448/v1.5.0-hotfix4@3b4f7414", - "build_info":{"build_id":"20190711-084448/v1.5.0-hotfix4@3b4f7414","build_timestamp":"2019-07-11T08:44:48Z","build_version":"1.0"}, - "cloud":{"enabled":true,"connected":true}, - "timezone":"Europe/Berlin","lat":45.252491,"lng":7.779092,"tzautodetect":false,"time":"07:13", - "hwinfo": {"hw_revision":"prod-190410b","batch_id":1}, - "mode":"color"," - dcpower":1, - lights":[ - { - "ison":false, - "red":255,"green":0,"blue":0,"white":255, - "gain":29, - "effect":0, - "default_state":"off", - "auto_on":0.00,"auto_off":0.00, - "schedule":false, - "btn_type":"detached", - "btn_reverse":0,"schedule_rules":[] - } - ] -} -``` - -### RGW2 /status color mode - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.100","rssi":-69}, - "cloud":{"enabled":true,"connected":true}, - "mqtt":{"connected":false},"time":"07:12", - "serial":112, - "has_update":false,"mac":"XXXXXXXXXXXX", - "mode":"color", - "input":0, - "lights":[ - {"ison":false,"mode":"color", "red":255,"green":0,"blue":0,"white":255, "gain":29,"effect":0, "power":0.00,"overpower":false} - ], - "meters":[ - {"power":0.00,"is_valid":true} - ], - "update":{"status":"idle","has_update":false,"new_version":"20190711-084448/v1.5.0-hotfix4@3b4f7414","old_version":"20190711-084448/v1.5.0-hotfix4@3b4f7414"}, - "ram_total":50448,"ram_free":35824,"fs_size":233681,"fs_free":162648,"uptime":30380 -} -``` - -### RGBW2 /settings in white mode - -``` -{ - "device":{"type":"SHRGBW2","mac":"XXXXXXXXXXXX","hostname":"shellyrgbw2-XXXXXX","num_outputs":4}, - "wifi_ap":{"enabled":false,"ssid":"shellyrgbw2-XXXXXX","key":""}, - "wifi_sta":{"enabled":true,"ssid":"iot_wlan","ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null}, - "mqtt": {"enable":false,"server":"10.0.0.1:1883","user":"","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive":60,"will_topic":"","will_message":"","max_qos":0,"retain":false,"update_period":30}, - "sntp": {"server":"time.google.com"}," - login":{"enabled":false,"unprotected":false,"username":"xxx","password":"xxx"}, - "pin_code":"PIpf!A", - "coiot_execute_enable":false, - "name":"", - "fw":"20190711-084448/v1.5.0-hotfix4@3b4f7414", - "build_info":{"build_id":"20190711-084448/v1.5.0-hotfix4@3b4f7414","build_timestamp":"2019-07-11T08:44:48Z","build_version":"1.0"}, - "cloud":{"enabled":true,"connected":true}, - "timezone":"Europe/Berlin","lat":45.252491,"lng":7.779092,"tzautodetect":false,"time":"20:33", - "hwinfo": {"hw_revision":"prod-190410b","batch_id":1}, - "mode":"white", - "dcpower":1, - "lights":[ - {"ison":true,"brightness":50,"default_state":"on","auto_on":0.00,"auto_off":0.00,"schedule":false,"btn_type":"detached","btn_reverse":0,"schedule_rules":[]}, - {"ison":false,"brightness":50,"default_state":"on","auto_on":0.00,"auto_off":0.00,"schedule":false,"schedule_rules":[]}, - {"ison":false,"brightness":50,"default_state":"on","auto_on":0.00,"auto_off":0.00,"schedule":false,"schedule_rules":[]}, - {"ison":false,"brightness":50,"default_state":"on","auto_on":0.00,"auto_off":0.00,"schedule":false,"schedule_rules":[]} - ] -} -``` - -### RGBW2 set/statustings in white mode - -``` -{ - "wifi_sta":{"connected":true,"ssid":"iot_wlan","ip":"10.0.0.100","rssi":-36}, - "cloud":{"enabled":true,"connected":true}, - "mqtt":{"connected":false},"time":"20:33","serial":42, - "has_update":false,"mac":"XXXXXXXXXXXX","mode":"white","input":0, - "lights":[ - {"ison":true,"mode":"white","brightness":50,"power":1.20,"overpower":false}, - {"ison":false,"mode":"white","brightness":50,"power":0.00,"overpower":false}, - {"ison":false,"mode":"white","brightness":50,"power":0.00,"overpower":false}, - {"ison":false,"mode":"white","brightness":50,"power":0.00,"overpower":false} - ], - "meters":[ - {"power":1.20,"is_valid":true}, - {"power":0.00,"is_valid":true}, - {"power":0.00,"is_valid":true}, - {"power":0.00,"is_valid":true} - ], - "update":{"status":"idle","has_update":false,"new_version":"20190711-084448/v1.5.0-hotfix4@3b4f7414","old_version":"20190711-084448/v1.5.0-hotfix4@3b4f7414"}, - "ram_total":50448,"ram_free":35360,"fs_size":233681,"fs_free":162648, - "uptime":7201 -} -``` - -## Shelly Sense - -### Shelly Sense: /settings - -``` -{"device":{"type":"SHSEN-1","mac":"XXXXXXXXXXXX","hostname":"shellysense-XXXXXX"},"wifi_ap":{"enabled":false,"ssid":"shellysense-XXXXXX","key":""},"wifi_sta":{"enabled":true,"ssid":"iot-wlan","ipv4_method":"static","ip":"10.0.0.2","gw":"10.0.0.1","mask":"255.255.255.0","dns":"10.0.0.1"},"wifi_sta1":{"enabled":false,"ssid":null,"ipv4_method":"dhcp","ip":null,"gw":null,"mask":null,"dns":null},"mqtt": {"enable":false,"server":"10.0.0.10:1883","user":"","reconnect_timeout_max":60.000000,"reconnect_timeout_min":2.000000,"clean_session":true,"keep_alive":60,"will_topic":"shellies/shellysense-XXXXXXX/online","will_message":"false","max_qos":0,"retain":false,"update_period":30},"sntp": {"server":"time.google.com"},"login":{"enabled":false,"unprotected":false,"username":"admin","password":"admin"},"pin_code":"bS^Mtq","coiot_execute_enable":true,"name":"","fw":"20190821-095017/v1.5.2@4148d2b7","build_info":{"build_id":"20190821-095017/v1.5.2@4148d2b7","build_timestamp":"2019-08-21T09:50:17Z","build_version":"1.0"},"cloud":{"enabled":true,"connected":true},"timezone":"Europe/Berlin","lat":51.394344,"lng":8.571319,"tzautodetect":false,"time":"19:32","light_sensor":"NOA1305","schedule":false,"schedule_rules":[],"sensors":{"motion_duration":20,"motion_led":false,"temperature_unit":"C"}} -``` - -### Shelly Sense /status - -``` -{"wifi_sta":{"connected":true,"ssid":"iot-wlan","ip":"10.0.0.2","rssi":-69},"cloud":{"enabled":true,"connected":true},"mqtt":{"connected":false},"time":"19:32","serial":4768,"has_update":false,"mac":"XXXXXXXXXXXX","motion":false,"charger":true,"tmp":{"value":24.249284,"is_valid":true,"units":"C"},"hum":{"value":44.250477,"is_valid":true},"lux":{"value":12.987013,"is_valid":true},"bat":{"value":40},"update":{"status":"idle","has_update":false,"new_version":"20190821-095017/v1.5.2@4148d2b7","old_version":"20190821-095017/v1.5.2@4148d2b7"},"ram_total":51112,"ram_free":26848,"fs_size":83081,"fs_free":26857,"uptime":1823498} -``` - -### Shelly Sense /ir/list - -``` -[ - ["1_231_pwr","tv(231) - Power"],["1_231_chdwn","tv(231) - Channel Down"],["1_231_chup","tv(231) - Channel Up"],["1_231_voldwn","tv(231) - Volume Down"], - ["1_231_volup","tv(231) - Volume Up"],["1_231_mute","tv(231) - Mute"],["1_231_menu","tv(231) - Menu"],["1_231_inp","tv(231) - Input"],["1_231_info","tv(231) - Info"], - ["1_231_left","tv(231) - Left"],["1_231_up","tv(231) - Up"],["1_231_right","tv(231) - Right"],["1_231_ok","tv(231) - OK"],["1_231_down","tv(231) - Down"], - ["1_231_back","tv(231) - Back"],["6_546_pwr","receiver(546) - Power"],["6_546_voldwn","receiver(546) - Volume Down"],["6_546_volup","receiver(546) - Volume Up"], - ["6_546_mute","receiver(546) - Mute"],["6_546_menu","receiver(546) - Menu"],["6_546_info","receiver(546) - Info"],["6_546_left","receiver(546) - Left"], - ["6_546_up","receiver(546) - Up"],["6_546_right","receiver(546) - Right"],["6_546_ok","receiver(546) - OK"],["6_546_down","receiver(546) - Down"],["6_546_back","receiver(546) - Back"] -] -``` - -### Shelly Sense Coap Description - -``` -{ - "blk":[{"I":1, "D":"sensors"}], - "sen":[ - {"I":11, "D":"motion", "T":"S", "R":"0/1", "L":1}, - {"I":22, "D":"charger", "T":"S", "R":"0/1", "L":1}, - {"I":33, "D":"temperature", "T":"T", "R":"-40/125", "L":1}, - {"I":44, "D":"humidity", "T":"H", "R":"0/100", "L":1}, - {"I":66, "D":"lux", "T":"L", "R":"0/1", "L":1}, - {"I":77, "D":"battery", "T":"H", "R":"0/100", "L":1} - ] -} -``` - -## Shelly Flood - -### Shelly Flood /settings - -``` -{ - “device”:{“type”:“SHWT-1”,“mac”:“XXXXXXXX”,“hostname”:“shellyflood-XXXXXX”,“sleep_mode”:true}, - “wifi_ap”:{“enabled”:false,“ssid”:“shellyflood-XXXXXX”,“key”:""}, - “wifi_sta”:{“enabled”:true,“ssid”:“iot-wlan”,“ipv4_method”:“dhcp”,“ip”:null,“gw”:null,“mask”:null,“dns”:null}, - “wifi_sta1”:{“enabled”:false,“ssid”:null,“ipv4_method”:“dhcp”,“ip”:null,“gw”:null,“mask”:null,“dns”:null}, - “mqtt”: {“enable”:true,“server”:“XXXXXX”,“user”:“XXXXXX”,“reconnect_timeout_max”:60.000000,“reconnect_timeout_min”:2.000000,“clean_session”:true,“keep_alive”:60,“will_topic”:“shellies/shellyflood-XXXXXX/online”,“will_message”:“false”,“max_qos”:0,“retain”:false,“update_period”:30}, - “sntp”: {“server”:“time.google.com”},login”:{“enabled”:true,“unprotected”:false,“username”:“XXXXXXX”,“password”:“XXXXXX”},“pin_code”:"",“coiot_execute_enable”:false, - “name”:"",“fw”:“20190821-095233/v1.5.2@4148d2b7”,“build_info”:{“build_id”:“20190821-095233/v1.5.2@4148d2b7”,“build_timestamp”:“2019-08-21T09:52:33Z”,“build_version”:“1.0”}, - “cloud”:{“enabled”:false,“connected”:false},“timezone”:“Europe/Berlin”,“lat”:50.110901,“lng”:8.682130,“tzautodetect”:true,“time”:“11:09”, - “sensors”:{ - “temperature_threshold”:1.0, - “temperature_unit”:“C” - }, - “sleep_mode”:{“period”:24,“unit”:“h”}, - “report_url”:null, - “rain_sensor”:false -} -``` - -### Shelly Flood /status - -``` -{ - “wifi_sta”:{“connected”:true,“ssid”:“XXXXX”,“ip”:"XXXXXXXX“,“rssi”:-88}, - “cloud”:{“enabled”:false,“connected”:false},“mqtt”:{“connected”:true}, - “time”:“11:07”,“serial”:1,“has_update”:false,“mac”:“XXXXXXXXXXXX”, - “is_valid”:true, - “flood”:false, - “tmp”:{“value”:21.62,“units”:“C”,“tC”:21.62,“tF”:70.93, “is_valid”:true}, - “bat”:{“value”:95,“voltage”:2.92},“act_reasons”:[“button”], - “rain_sensor”:false, - “update”:{“status”:“idle”,“has_update”:false,“new_version”:“20190821-095233/v1.5.2@4148d2b7”,“old_version”:“20190821-095233/v1.5.2@4148d2b7”}, - “ram_total”:50592,“ram_free”:39632,“fs_size”:233681,“fs_free”:154365,“uptime”:22 -} -``` - - - -# COAP API JSON - - - - -### Decoded Device Description - -``` - id=0: Relay0 - id=1: Relay1 - id=2: Device - Adding 5 sensor definitions - id 112: State, Type=S, Range=0/1, Links=0 - id 122: State, Type=S, Range=0/1, Links=1 - id 111: Power, Type=W, Range=0/2300, Links=0 - id 121: Power, Type=W, Range=0/2300, Links=1 - id 113: Position, Type=S, Range=0/100, Links=2 - Device has 2 actors - id=211: Switch, Links=0 - P[2011]: ToState, Range=0/1 - id=221: Switch, Links=1 - P[2021]: ToState, Range=0/1 -``` - - \ No newline at end of file diff --git a/bundles/org.openhab.binding.shelly/pom.xml b/bundles/org.openhab.binding.shelly/pom.xml index 2d268caaf63a..8dd6e51bab79 100644 --- a/bundles/org.openhab.binding.shelly/pom.xml +++ b/bundles/org.openhab.binding.shelly/pom.xml @@ -1,15 +1,17 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.2-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.2-SNAPSHOT + - org.openhab.binding.shelly - openHAB Add-ons :: Bundles :: Shelly Binding - + org.openhab.binding.shelly + openHAB Add-ons :: Bundles :: Shelly Binding + diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java index c961844d51b3..205ee9b78674 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java @@ -131,6 +131,8 @@ public class ShellyBindingConstants { public static final String PROPERTY_UPDATE_CURR_VERS = "updateCurrentVersion"; public static final String PROPERTY_UPDATE_NEW_VERS = "updateNewVersion"; public static final String PROPERTY_COAP_DESCR = "coapDeviceDescr"; + public static final String PROPERTY_STATS_TIMEOUTS = "statsTimeoutErrors"; + public static final String PROPERTY_STATS_TRECOVERED = "statsTimeoutsRecovered"; // Relay public static final String CHANNEL_GROUP_RELAY_CONTROL = "relay"; @@ -144,6 +146,12 @@ public class ShellyBindingConstants { public static final String CHANNEL_TIMER_AUTOOFF = "autoOff"; public static final String CHANNEL_TIMER_ACTIVE = "timerActive"; + // External sensors for Shelly1/1PM + public static final String CHANNEL_GROUP_ETEMP_SENSORS = "sensors"; + public static final String CHANNEL_ETEMP_SENSOR1 = "temperature1"; + public static final String CHANNEL_ETEMP_SENSOR2 = "temperature2"; + public static final String CHANNEL_ETEMP_SENSOR3 = "temperature3"; + // Roller public static final String CHANNEL_GROUP_ROL_CONTROL = "roller"; public static final String CHANNEL_ROL_CONTROL_CONTROL = "control"; @@ -223,11 +231,10 @@ public class ShellyBindingConstants { public static final String SERVICE_TYPE = "_http._tcp.local."; public static final String SHELLY_API_MIN_FWVERSION = "v1.5.2"; - public static final int SHELLY_API_TIMEOUT_MS = 6000; + public static final int SHELLY_API_TIMEOUT_MS = 5000; // Alarm types/messages public static final String ALARM_TYPE_NONE = "NONE"; - public static final String ALARM_TYPE_WEAKSIGNAL = "WEAK_SIGNAL"; public static final String ALARM_TYPE_RESTARTED = "RESTARTED"; public static final String ALARM_TYPE_OVERTEMP = "OVERTEMP"; public static final String ALARM_TYPE_OVERPOWER = "OVERPOWER"; @@ -298,7 +305,6 @@ public class ShellyBindingConstants { // Minimum signal strength for basic connectivity. Packet delivery may be unreliable. public static final int HEALTH_CHECK_INTERVAL_SEC = 300; - public static final int SIGNAL_ALARM_MIN_RSSI = -80; public static final int DIM_STEPSIZE = 5; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJson.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJsonDTO.java similarity index 96% rename from bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJson.java rename to bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJsonDTO.java index e0c55fc9fb04..27349e9e880d 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJson.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJsonDTO.java @@ -17,11 +17,11 @@ import com.google.gson.annotations.SerializedName; /** - * The {@link ShellyApiJson} is used for the JSon/GSon mapping + * The {@link ShellyApiJsonDTO} is used for the JSon/GSon mapping * * @author Markus Michels - Initial contribution */ -public class ShellyApiJson { +public class ShellyApiJsonDTO { public static final String SHELLY_API_ON = "on"; public static final String SHELLY_API_OFF = "off"; @@ -223,8 +223,8 @@ public static class ShellySettingsDimmer { public static final String SHELLY_EVENT_BTN2_OFF = "btn2_off"; public static final String SHELLY_EVENT_SHORTPUSH = "shortpush"; public static final String SHELLY_EVENT_LONGPUSH = "longpush"; - public static final String SHELLY_EVENT_OUT_ON = "btn2_off"; - public static final String SHELLY_EVENT_OUT_OFF = "btn_on"; + public static final String SHELLY_EVENT_OUT_ON = "out_on"; + public static final String SHELLY_EVENT_OUT_OFF = "out_off"; public static final String SHELLY_EVENT_ROLLER_OPEN = "roller_open"; public static final String SHELLY_EVENT_ROLLER_CLOSE = "roller_close"; public static final String SHELLY_EVENT_ROLLER_STOP = "roller_stop"; @@ -310,7 +310,6 @@ public static class ShellySettingsEMeter { // ShellyEM meter public Double total; // Total consumed energy, Wh @SerializedName("total_returned") public Double totalReturned; // Total returned energy, Wh - public Long timestamp; } public static class ShellySettingsUpdate { @@ -410,6 +409,7 @@ public static class ShellySettingsStatus { public String mac; public ArrayList relays; public ArrayList rollers; + public Integer input; // RGBW2 has no JSON array public ArrayList inputs; public ArrayList lights; public ArrayList dimmers; @@ -459,6 +459,9 @@ public static class ShellyShortStatusRelay { public Boolean overpower; // Shelly1PM only if maximum allowed power was exceeded public Double temperature; // Internal device temperature public Boolean overtemperature; // Device over heated + + @SerializedName("ext_temperature") + public ShellyStatusSensor.ShellyExtTemperature extTemperature; // Shelly 1/1PM: sensor values } public static class ShellyShortLightStatus { @@ -593,6 +596,22 @@ public static class ShellySensorLux { public Double value; } + public static class ShellyExtTemperature { + public static class ShellyShortTemp { + public Double tC; // temperature in deg C + public Double tF; // temperature in deg F + } + + // Shelly 1/1PM have up to 3 sensors + // for whatever reasons it's not an array, but 3 independent elements + @SerializedName("0") + public ShellyShortTemp sensor1; + @SerializedName("1") + public ShellyShortTemp sensor2; + @SerializedName("2") + public ShellyShortTemp sensor3; + } + public ShellySensorTmp tmp; public ShellySensorHum hum; public ShellySensorLux lux; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java index 18bdfb7b073c..e538f65e446d 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java @@ -14,7 +14,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.SHELLYDT_DIMMER; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.util.HashMap; import java.util.Map; @@ -25,7 +25,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.shelly.internal.ShellyBindingConstants; import org.openhab.binding.shelly.internal.ShellyUtils; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsGlobal; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsGlobal; import com.google.gson.Gson; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpApi.java index b57b923ca8ae..f2cc7971abeb 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpApi.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpApi.java @@ -14,7 +14,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.io.IOException; import java.util.Base64; @@ -29,16 +29,16 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyControlRoller; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySendKeyList; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySenseKeyCode; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsDevice; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsLight; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyShortLightStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusLight; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusRelay; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusSensor; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySendKeyList; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySenseKeyCode; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDevice; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsLight; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLight; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor; import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +56,8 @@ public class ShellyHttpApi { private final Logger logger = LoggerFactory.getLogger(ShellyHttpApi.class); private final ShellyThingConfiguration config; private final String thingName = ""; + private int timeoutErrors = 0; + private int timeoutsRecovered = 0; private Gson gson = new Gson(); private @Nullable ShellyDeviceProfile profile; @@ -135,9 +137,14 @@ public void setRelayTurn(Integer relayIndex, String turnMode) throws IOException + "?" + SHELLY_LIGHT_TURN + "=" + turnMode.toLowerCase()); } - public void setDimmerBrightness(Integer relayIndex, Integer brightness) throws IOException { - request(SHELLY_URL_CONTROL_LIGHT + "/" + relayIndex.toString() + "?" + SHELLY_LIGHT_TURN + "=" + SHELLY_API_ON - + "&brightness=" + brightness.toString()); + public void setDimmerBrightness(Integer relayIndex, Integer brightness, boolean autoOn) throws IOException { + if (autoOn) { + request(SHELLY_URL_CONTROL_LIGHT + "/" + relayIndex.toString() + "?" + SHELLY_LIGHT_TURN + "=" + + SHELLY_API_ON + "&brightness=" + brightness.toString()); + } else { + request(SHELLY_URL_CONTROL_LIGHT + "/" + relayIndex.toString() + "?" + "&brightness=" + + brightness.toString()); + } } @Nullable @@ -459,40 +466,77 @@ private void setEventUrls(Integer index) throws IOException { * @param uri: URI (e.g. "/settings") */ private String request(String uri) throws IOException { - String httpResponse = "ERROR"; - String url = "http://" + config.deviceIp + uri; - // boolean acquired = false; + String result = ""; + boolean retry = false; try { - logger.trace("HTTP GET for {}: {}", thingName, url); - - Properties headers = new Properties(); - if (!config.userId.isEmpty()) { - String value = config.userId + ":" + config.password; - headers.put(HTTP_HEADER_AUTH, - HTTP_AUTH_TYPE_BASIC + " " + Base64.getEncoder().encodeToString(value.getBytes())); - } - - httpResponse = HttpUtil.executeUrl(HttpMethod.GET, url, headers, null, "", SHELLY_API_TIMEOUT_MS); - Validate.notNull(httpResponse, "httpResponse must not be null"); - // all api responses are returning the result in Json format. If we are getting - // something else it must - // be an error message, e.g. http result code - if (httpResponse.contains(APIERR_HTTP_401_UNAUTHORIZED)) { + result = innerRequest(uri); + } catch (IOException e) { + String type = StringUtils.substringAfterLast(e.getCause().toString(), "."); + if (e.getMessage().contains("Timeout") || type.toLowerCase().contains("timeout") + || e.getMessage().contains("Connection reset")) { + logger.debug("{}: Shelly API timeout ({}), retry", thingName, type); + timeoutErrors++; + retry = true; + } else { throw new IOException( - APIERR_HTTP_401_UNAUTHORIZED + ", set/correct userid and password in the thing/binding config"); + thingName + ": Shelly API call failed (" + type + "), uri=" + uri); } - if (!httpResponse.startsWith("{") && !httpResponse.startsWith("[")) { - throw new IOException("Unexpected http response: " + httpResponse); + } + if (retry && !profile.hasBattery) { + try { + // retry to recover + result = innerRequest(uri); + timeoutsRecovered++; + logger.debug("Shelly API timeout recovered"); + } catch (IOException e) { + String type = StringUtils.substringAfterLast(e.getCause().toString(), "."); + if (e.getMessage().contains("Timeout") || type.toLowerCase().contains("timeout") + || e.getMessage().contains("Connection reset")) { + throw new IOException( + thingName + ": Shelly API timeout (" + type + "), uri=" + uri); + } else { + throw new IOException( + thingName + ": Shelly API call failed: " + type + ", uri=" + uri); + } } + } + return result; + } - logger.trace("HTTP response from {}: {}", thingName, httpResponse); - return httpResponse; - } catch (IOException e) { - if (e.getMessage().contains("Timeout")) { - throw new IOException("Shelly API call failed: Timeout (" + SHELLY_API_TIMEOUT_MS + " ms)"); - } else { - throw new IOException("Shelly API call failed: " + e.getMessage() + ", url=" + url); - } + private String innerRequest(String uri) throws IOException { + String httpResponse = "ERROR"; + String url = "http://" + config.deviceIp + uri; + logger.trace("{}: HTTP GET for {}", thingName, url); + + Properties headers = new Properties(); + if (!config.userId.isEmpty()) { + String value = config.userId + ":" + config.password; + headers.put(HTTP_HEADER_AUTH, + HTTP_AUTH_TYPE_BASIC + " " + Base64.getEncoder().encodeToString(value.getBytes())); + } + + httpResponse = HttpUtil.executeUrl(HttpMethod.GET, url, headers, null, "", SHELLY_API_TIMEOUT_MS); + Validate.notNull(httpResponse, "httpResponse must not be null"); + // all api responses are returning the result in Json format. If we are getting + // something else it must + // be an error message, e.g. http result code + if (httpResponse.contains(APIERR_HTTP_401_UNAUTHORIZED)) { + throw new IOException( + APIERR_HTTP_401_UNAUTHORIZED + ", set/correct userid and password in the thing/binding config"); + } + if (!httpResponse.startsWith("{") && !httpResponse.startsWith("[")) { + throw new IOException("Unexpected http response: " + httpResponse); } + + logger.trace("HTTP response from {}: {}", thingName, httpResponse); + return httpResponse; + } + + public int getTimeoutErrors() { + return timeoutErrors; + } + + public int getTimeoutsRecovered() { + return timeoutsRecovered; } } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapHandler.java index aaf2d973421e..b9b424641197 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapHandler.java @@ -14,14 +14,15 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; -import static org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; +import static org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.*; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.core.coap.CoAP.Code; @@ -34,20 +35,20 @@ import org.eclipse.californium.core.coap.Response; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.types.State; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotDescrBlk; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotDescrSen; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotDevDescription; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotGenericSensorList; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotSensor; -import org.openhab.binding.shelly.internal.coap.ShellyCoapJSon.CoIotSensorTypeAdapter; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDevDescription; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotGenericSensorList; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor; +import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensorTypeAdapter; import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration; import org.openhab.binding.shelly.internal.handler.ShellyBaseHandler; +import org.openhab.binding.shelly.internal.handler.ShellyColorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -344,7 +345,7 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws return; } - logger.debug("{}: {} status updates received", thingName, list.generic.size()); + logger.debug("{}: {} status updates received", thingName, new Integer(list.generic.size()).toString()); for (int i = 0; i < list.generic.size(); i++) { CoIotSensor s = list.generic.get(i); CoIotDescrSen sen = sensorMap.get(s.index); @@ -389,6 +390,9 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws String mGroup = profile.numMeters == 1 ? CHANNEL_GROUP_METER : CHANNEL_GROUP_METER + rIndex; updateChannel(updates, mGroup, CHANNEL_METER_CURRENTWATTS, toQuantityType(s.value, DIGITS_WATT, SmartHomeUnits.WATT)); + if (profile.isEMeter) { + updateChannel(updates, mGroup, CHANNEL_LAST_UPDATE, getTimestamp()); + } break; case "o": // Overtemp // will be handled by status update @@ -420,19 +424,22 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws toQuantityType(pos, SmartHomeUnits.PERCENT)); break; case "input": - if (!profile.isDimmer) { - // Device has 1 input: 0=off, 1+2 depend on switch mode - updateChannel(updates, rGroup, CHANNEL_INPUT, - s.value == 0 ? OnOffType.OFF : OnOffType.ON); - } else { - // only Dimmer has 2 inputs - Integer idx = getInputId(sen.id); - if (idx != null) { - updateChannel(updates, rGroup, CHANNEL_INPUT + idx.toString(), - s.value == 1 ? OnOffType.ON : OnOffType.OFF); + Integer idx = getInputId(sen.id); + String iGroup = rGroup; + String iChannel = CHANNEL_INPUT; + if (idx != null) { + if (profile.isDimmer || profile.isRoller) { + // Dimmer and Roller things have 2 inputs + iChannel = CHANNEL_INPUT + idx.toString(); + } else { + // Device has 1 input per relay: 0=off, 1+2 depend on switch mode + iGroup = profile.numRelays <= 1 ? CHANNEL_GROUP_RELAY_CONTROL + : CHANNEL_GROUP_RELAY_CONTROL + idx; } } + updateChannel(updates, iGroup, iChannel, s.value == 0 ? OnOffType.OFF : OnOffType.ON); break; + case "flood": updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_FLOOD, s.value == 1 ? OnOffType.ON : OnOffType.OFF); @@ -449,27 +456,27 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws // RGBW2/Bulb case "red": updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_RED, - new DecimalType(s.value)); + ShellyColorUtils.toPercent((int) s.value)); break; case "green": updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_GREEN, - new DecimalType(s.value)); + ShellyColorUtils.toPercent((int) s.value)); break; case "blue": updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_BLUE, - new DecimalType(s.value)); + ShellyColorUtils.toPercent((int) s.value)); break; case "white": updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_WHITE, - new DecimalType(s.value)); + ShellyColorUtils.toPercent((int) s.value)); break; case "gain": updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_GAIN, - new DecimalType(s.value)); + ShellyColorUtils.toPercent((int) s.value, SHELLY_MIN_GAIN, SHELLY_MAX_GAIN)); break; case "temp": - updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_TEMP, - new DecimalType(s.value)); + updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_TEMP, ShellyColorUtils + .toPercent((int) s.value, MIN_COLOR_TEMPERATURE, MAX_COLOR_TEMPERATURE)); break; @@ -494,7 +501,8 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws logger.debug("{}: Process {} CoIoT channel updates", thingName, updates.size()); int i = 0; for (Map.Entry u : updates.entrySet()) { - logger.debug("{}: Update[{}] channel {}, value={}", thingName, i, u.getKey(), u.getValue()); + logger.debug("{}: Update[{}] channel {}, value={} (type {})", thingName, i, u.getKey(), u.getValue(), + u.getValue().getClass()); thingHandler.updateChannel(u.getKey(), u.getValue(), true); i++; } @@ -690,19 +698,24 @@ private void resetSerial() { * @param sensorId The id from the sensor update * @return Index of found entry (+1 will be the suffix for the channel name) or null if sensorId is not found */ + @SuppressWarnings("null") @Nullable private Integer getInputId(String sensorId) { - Integer idx = 1; + Integer idx = 0; for (Map.Entry se : sensorMap.entrySet()) { @Nullable CoIotDescrSen sen = se.getValue(); + if (sen.id.equalsIgnoreCase("Input")) { + idx++; // iterate from input1..2..n + } if (sen.id.equalsIgnoreCase(sensorId)) { + CoIotDescrBlk blk = blockMap.get(sen.links); + if ((blk != null) && StringUtils.substring(blk.desc, 5).equalsIgnoreCase("Relay")) { + idx = Integer.parseInt(StringUtils.substringAfter(blk.desc, "Relay")); + } logger.trace("{}: map to input{} channel", thingName, idx); return idx; } - if (sen.id.equalsIgnoreCase("Input")) { - idx++; // iterate from input1..2..n - } } logger.debug("{}: sensorId {} not found in sensorMap!", thingName, sensorId); return null; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSon.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSonDTO.java similarity index 97% rename from bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSon.java rename to bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSonDTO.java index c8c0bc05befc..b5fdc99b10da 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSon.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapJSonDTO.java @@ -23,11 +23,11 @@ import com.google.gson.stream.JsonWriter; /** - * The {@link ShellyCoapJSon} helps the CoIoT Json into Java objects + * The {@link ShellyCoapJSonDTO} helps the CoIoT Json into Java objects * * @author Markus Michels - Initial contribution */ -public class ShellyCoapJSon { +public class ShellyCoapJSonDTO { public static final String COIOT_TAG_BLK = "blk"; public static final String COIOT_TAG_SEN = "sen"; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java index e84f039117a5..143b9db6c433 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java @@ -22,12 +22,13 @@ @NonNullByDefault public class ShellyThingConfiguration { public String deviceIp = ""; // ip address of thedevice - public int updateInterval = 60; // schedule interval for the update job - public float lowBattery = 20; // threshold for battery value - public String userId = ""; // userid for http basic auth public String password = ""; // password for http basic auth + public int updateInterval = 60; // schedule interval for the update job + public int lowBattery = 20; // threshold for battery value + public boolean brightnessAutoOn = true; // true: turn on device if brightness > 0 is set + public boolean eventsButton = false; // true: register for Relay btn_xxx events public boolean eventsSwitch = true; // true: register for device out_xxx events public boolean eventsPush = true; // true: register for short/long push events diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java index 927104f9e64d..3a2fb01fbb5a 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java @@ -13,7 +13,7 @@ package org.openhab.binding.shelly.internal.discovery; import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java index 47d46e951432..46ab78deaff9 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java @@ -15,7 +15,7 @@ import static org.eclipse.smarthome.core.thing.Thing.*; import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.getThingTypeUID; import java.io.IOException; @@ -29,6 +29,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.CommonTriggerEvents; @@ -40,7 +41,8 @@ import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyInputState; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; import org.openhab.binding.shelly.internal.api.ShellyHttpApi; import org.openhab.binding.shelly.internal.coap.ShellyCoapHandler; @@ -73,6 +75,7 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL private long lastUpdateTs = 0; private long lastUptime = 0; private long lastAlarmTs = 0; + private Integer lastTimeoutErros = -1; private @Nullable ScheduledFuture statusJob; private int skipUpdate = 0; @@ -116,7 +119,6 @@ public ShellyBaseHandler(Thing thing, ShellyBindingConfiguration bindingConfig, */ @Override public void initialize() { - updateStatus(ThingStatus.UNKNOWN); // start background initialization: scheduler.schedule(() -> { boolean start = true; @@ -126,7 +128,8 @@ public void initialize() { logger.debug("{}: Device config: ipAddress={}, http user/password={}/{}, update interval={}", getThing().getLabel(), config.deviceIp, config.userId.isEmpty() ? "" : config.userId, config.password.isEmpty() ? "" : "***", config.updateInterval); - initializeThing(); + updateStatus(ThingStatus.UNKNOWN); + start = initializeThing(); } catch (NullPointerException | IOException e) { if (authorizationFailed(e.getMessage())) { start = false; @@ -166,27 +169,33 @@ public void handleConfigurationUpdate(Map configurationParameter * @throws IOException e.g. http returned non-ok response, check e.getMessage() for details. */ @SuppressWarnings("null") - private void initializeThing() throws IOException { + private boolean initializeThing() throws IOException { // Get the thing global settings and initialize device capabilities channelData = new HashMap<>(); // clear any cached channels refreshSettings = false; lockUpdates = false; Map properties = getThing().getProperties(); + String thingType = getThing().getThingTypeUID().getId(); thingName = properties.get(PROPERTY_SERVICE_NAME) != null ? properties.get(PROPERTY_SERVICE_NAME).toLowerCase() - : ""; - logger.debug("{}: Start initializing, ip address {}, CoIoT: {}", getThing().getLabel(), config.deviceIp, - config.eventsCoIoT); + : thingType; + logger.debug("{}: Start initializing thing {}, type {}, ip address {}, CoIoT: {}", thingName, + getThing().getLabel(), thingType, config.deviceIp, config.eventsCoIoT); + if (config.deviceIp.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/config-status.error.missing-device-ip"); + return false; + } // Initialize API access, exceptions will be catched by initialize() api = new ShellyHttpApi(config); - ShellyDeviceProfile tmpPrf = api.getDeviceProfile(this.getThing().getThingTypeUID().getId()); + ShellyDeviceProfile tmpPrf = api.getDeviceProfile(thingType); thingName = (!thingName.isEmpty() ? thingName : tmpPrf.hostname).toLowerCase(); Validate.isTrue(!thingName.isEmpty(), "initializeThing(): thingName must not be empty!"); if (this.getThing().getThingTypeUID().equals(THING_TYPE_SHELLYUNKNOWN)) { changeThingType(thingName, tmpPrf.mode); - return; // force re-initialization + return false; // force re-initialization } logger.debug("{}: Initializing device {}, type {}, Hardware: Rev: {}, batch {}; Firmware: {} / {} ({})", @@ -228,13 +237,14 @@ private void initializeThing() throws IOException { profile = tmpPrf; // all initialization done, so keep the profile // Validate device mode - String thingType = getThing().getThingTypeUID().getId(); String reqMode = thingType.contains("-") ? StringUtils.substringAfter(thingType, "-") : ""; if (!reqMode.isEmpty() && !tmpPrf.mode.equals(reqMode)) { + logger.info( + "{}: Thing is in mode {}, expecting mode {} - going offline. Re-run discovery to changed device mode.", + thingName, profile.mode, reqMode); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Thing is in mode " + profile.mode + ", required is " + reqMode - + " - going offline. Re-run discovery to find the thing for the requested mode."); - return; + "@text/offline.conf-error-wrong-mode"); + return false; } if (config.eventsCoIoT && (coap == null)) { @@ -246,12 +256,13 @@ private void initializeThing() throws IOException { } fillDeviceStatus(status, false); + postAlarm(ALARM_TYPE_NONE, false); logger.debug("{}: Thing successfully initialized.", thingName); updateStatus(ThingStatus.ONLINE); // if API call was successful the thing must be online requestUpdates(3, false); // request 3 updates in a row (during the first 2+3*3 sec) - postAlarm(ALARM_TYPE_NONE, false); + return true; // success } /** @@ -355,19 +366,25 @@ protected void updateStatus() { } } catch (IOException e) { // http call failed: go offline except for battery devices, which might be in - // sleep mode - // once the next update is successful the device goes back online + // sleep mode. Once the next update is successful the device goes back online + String status = ""; if (e.getMessage().contains("Timeout")) { - logger.debug("Device {} is not reachable, update canceled ({} skips, {} scheduledUpdates)!", thingName, + logger.debug("{}: Device is not reachable, update canceled ({} skips, {} scheduledUpdates)!", thingName, skipCount, scheduledUpdates); + status = "@text/offline.status-error-timeout"; + } else if (e.getMessage().contains(APIERR_HTTP_401_UNAUTHORIZED)) { + logger.debug("{}: Unable to access device, check credentials!", thingName); + status = "@text/offline.conf-error-access-denied"; } else if (e.getMessage().contains("Not calibrated!")) { logger.debug("{}: Roller is not calibrated! Use the Shelly App or Web UI to run calibration.", thingName); + status = "@text/offline.conf-error-not-calibrated"; } else { logger.debug("{}: Unable to update status: {} ({})", thingName, e.getMessage(), e.getClass()); + status = "@text/offline.status-error-unexpected-api-result"; } - if (e.getMessage().contains(APIERR_HTTP_401_UNAUTHORIZED) || (profile != null && !profile.isSensor)) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + if (!status.isEmpty() || (profile != null && !profile.isSensor)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, status); } } catch (NullPointerException e) { logger.warn("{}: Unable to update status: {} ({})", thingName, e.getMessage(), e.getClass()); @@ -392,6 +409,8 @@ private void fillDeviceStatus(ShellySettingsStatus status, boolean updated) { String alarm = ""; boolean force = false; + Map propertyUpdates = new HashMap(); + // Update uptime and WiFi if (updated) { lastUpdateTs = now(); @@ -402,6 +421,12 @@ private void fillDeviceStatus(ShellySettingsStatus status, boolean updated) { toQuantityType(new DecimalType(uptime), SmartHomeUnits.SECOND)); updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_RSSI, mapSignalStrength(rssi)); + if ((api != null) && (lastTimeoutErros != api.getTimeoutErrors())) { + propertyUpdates.put(PROPERTY_STATS_TIMEOUTS, new Integer(api.getTimeoutErrors()).toString()); + propertyUpdates.put(PROPERTY_STATS_TRECOVERED, new Integer(api.getTimeoutsRecovered()).toString()); + lastTimeoutErros = api.getTimeoutErrors(); + } + // Check various device indicators like overheating if ((status.uptime < lastUptime) && (profile != null) && !profile.hasBattery) { alarm = ALARM_TYPE_RESTARTED; @@ -409,9 +434,6 @@ private void fillDeviceStatus(ShellySettingsStatus status, boolean updated) { } lastUptime = uptime; - if ((rssi < SIGNAL_ALARM_MIN_RSSI) && ((lastAlarmTs == 0))) { - alarm = ALARM_TYPE_WEAKSIGNAL; - } if (getBool(status.overtemperature)) { alarm = ALARM_TYPE_OVERTEMP; } @@ -425,6 +447,10 @@ private void fillDeviceStatus(ShellySettingsStatus status, boolean updated) { if (!alarm.isEmpty()) { postAlarm(alarm, force); } + + if (!propertyUpdates.isEmpty()) { + flushProperties(propertyUpdates); + } } /** @@ -461,17 +487,14 @@ public void postAlarm(String alarm, boolean force) { @SuppressWarnings({ "null" }) @Override public boolean onEvent(String deviceName, String deviceIndex, String type, Map parameters) { - if (profile == null) { - logger.debug("OnEvent: Thing not yet initialized, skip event"); - } if (thingName.equalsIgnoreCase(deviceName) || config.deviceIp.equals(deviceName)) { logger.debug("{}: Event received: class={}, index={}, parameters={}", deviceName, type, deviceIndex, parameters.toString()); boolean hasBattery = profile != null && profile.hasBattery ? true : false; if (profile == null) { logger.debug("{}: Device is not yet initialized, event triggers initialization", deviceName); + requestUpdates(1, true); } else { - String group = ""; Integer rindex = !deviceIndex.isEmpty() ? Integer.parseInt(deviceIndex) + 1 : -1; if (type.equals(EVENT_TYPE_RELAY)) { @@ -516,8 +539,33 @@ public boolean onEvent(String deviceName, String deviceIndex, String type, Map properties = editProperties(); properties.replace(PROPERTY_DEV_TYPE, thingType); + properties.replace(PROPERTY_DEV_MODE, mode); updateProperties(properties); changeThingType(thingTypeUID, getConfig()); } @@ -631,6 +680,39 @@ public boolean requestUpdates(int requestCount, boolean refreshSettings) { return false; } + /** + * Map input states to channels + * + * @param groupName Channel Group (relay / relay1...) + * + * @param status Shelly device status + * @return true: one or more inputs were updated + */ + @SuppressWarnings({ "null", "unused" }) + public boolean updateInputs(String groupName, ShellySettingsStatus status, int index) { + boolean updated = false; + if ((status.input != null) && (index == 0)) { + // RGBW2: a single int rather than an array + logger.trace("{}: Updating input with {}", thingName, getInteger(status.input)); + updated |= updateChannel(groupName, CHANNEL_INPUT, + getInteger(status.input) == 0 ? OnOffType.OFF : OnOffType.ON); + } else if (status.inputs != null) { + if (profile.isDimmer || profile.isRoller) { + ShellyInputState state1 = status.inputs.get(0); + ShellyInputState state2 = status.inputs.get(1); + logger.trace("{}: Updating {}#input1 with {}, input2 with {}", thingName, groupName, + getOnOff(state1.input), getOnOff(state2.input)); + updated |= updateChannel(groupName, CHANNEL_INPUT + "1", getOnOff(state1.input)); + updated |= updateChannel(groupName, CHANNEL_INPUT + "2", getOnOff(state2.input)); + } else { + ShellyInputState state = status.inputs.get(index); + logger.trace("{}: Updating input[{}] with {}", thingName, index, getOnOff(state.input)); + updated |= updateChannel(groupName, CHANNEL_INPUT, getOnOff(state.input)); + } + } + return updated; + } + /** * Update one channel. Use Channel Cache to avoid unnecessary updates (and avoid * messing up the log with those updates) @@ -650,7 +732,9 @@ public boolean updateChannel(String channelId, State value, Boolean forceUpdate) // logger.trace("{}: Predict channel {}.{} to become {} (type {}).", thingName, // group, channel, value, value.getClass()); if (!channelCache || forceUpdate || (current == null) || !current.equals(value)) { - updateState(channelId, value); + // For channels that support multiple types (like brightness) a suffix is added + // this gets removed to get the channelId for updateState + updateState(channelId.contains("$") ? StringUtils.substringBefore(channelId, "$") : channelId, value); if (current == null) { channelData.put(channelId, value); } else { @@ -677,8 +761,15 @@ public boolean updateChannel(String group, String channel, State value) { * @param profile The device profile * @param status the /status result */ + @SuppressWarnings("null") protected void updateProperties(ShellyDeviceProfile profile, ShellySettingsStatus status) { Map properties = fillDeviceProperties(profile); + String serviceName = getThing().getProperties().get(PROPERTY_SERVICE_NAME); + String hostname = getString(profile.settings.device.hostname).toLowerCase(); + if ((serviceName == null) || serviceName.isEmpty()) { + properties.put(PROPERTY_SERVICE_NAME, hostname); + logger.trace("{}: Updated serrviceName to {}", thingName, hostname); + } // add status properties Validate.notNull(status, "updateProperties(): status must not be null!"); @@ -697,8 +788,7 @@ protected void updateProperties(ShellyDeviceProfile profile, ShellySettingsStatu for (Map.Entry property : properties.entrySet()) { thingProperties.put(property.getKey(), (String) property.getValue()); } - updateProperties(thingProperties); - logger.trace("{}: Properties updated", thingName); + flushProperties(thingProperties); } /** @@ -718,6 +808,19 @@ public void updateProperties(String key, String value) { logger.trace("{}: Properties updated", thingName); } + public void flushProperties(Map propertyUpdates) { + Map thingProperties = editProperties(); + for (Map.Entry property : propertyUpdates.entrySet()) { + if (thingProperties.containsKey(property.getKey())) { + thingProperties.replace(property.getKey(), property.getValue()); + } else { + thingProperties.put(property.getKey(), property.getValue()); + } + } + updateProperties(thingProperties); + logger.trace("{}: Properties updated", thingName); + } + /** * Get one property from the Thing Properties * diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java index abb5f71ce142..354e63784407 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.shelly.internal.handler; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.math.BigDecimal; @@ -168,11 +168,11 @@ public Integer[] fromRGBW(String rgbwString) { return values; } - private static PercentType toPercent(Integer value) { + public static PercentType toPercent(Integer value) { return toPercent(value, 0, SHELLY_MAX_COLOR); } - private static PercentType toPercent(@Nullable Integer _value, Integer min, Integer max) { + public static PercentType toPercent(@Nullable Integer _value, Integer min, Integer max) { Double range = max.doubleValue() - min.doubleValue(); Double value = _value != null ? _value.doubleValue() : 0; value = value < min ? min.doubleValue() : value; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java index 717238476a65..7ef65214f8a7 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java @@ -14,7 +14,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.io.IOException; @@ -24,10 +24,10 @@ import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsEMeter; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsMeter; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusSensor; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsEMeter; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsMeter; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; /*** @@ -85,8 +85,10 @@ public static boolean updateMeters(ShellyBaseHandler th, ShellySettingsStatus st updated |= th.updateChannel(groupName, CHANNEL_METER_LASTMIN3, toQuantityType(getDouble(meter.counters[2]), DIGITS_WATT, SmartHomeUnits.WATT)); } - th.updateChannel(groupName, CHANNEL_LAST_UPDATE, - getTimestamp(getString(profile.settings.timezone), getLong(meter.timestamp))); + if (updated) { + th.updateChannel(groupName, CHANNEL_LAST_UPDATE, + getTimestamp(getString(profile.settings.timezone), getLong(meter.timestamp))); + } m++; } } @@ -107,8 +109,9 @@ public static boolean updateMeters(ShellyBaseHandler th, ShellySettingsStatus st toQuantityType(getDouble(emeter.reactive), DIGITS_WATT, SmartHomeUnits.WATT)); updated |= th.updateChannel(groupName, CHANNEL_EMETER_VOLTAGE, toQuantityType(getDouble(emeter.voltage), DIGITS_VOLT, SmartHomeUnits.VOLT)); - th.updateChannel(groupName, CHANNEL_LAST_UPDATE, - getTimestamp(getString(profile.settings.timezone), getLong(emeter.timestamp))); + if (updated) { + th.updateChannel(groupName, CHANNEL_LAST_UPDATE, getTimestamp()); + } m++; } } @@ -151,8 +154,10 @@ public static boolean updateMeters(ShellyBaseHandler th, ShellySettingsStatus st updated |= th.updateChannel(groupName, CHANNEL_METER_TOTALKWH, toQuantityType(getDouble(totalWatts), DIGITS_KWH, SmartHomeUnits.KILOWATT_HOUR)); - updated |= th.updateChannel(groupName, CHANNEL_LAST_UPDATE, - getTimestamp(getString(profile.settings.timezone), timestamp)); + if (updated) { + th.updateChannel(groupName, CHANNEL_LAST_UPDATE, + getTimestamp(getString(profile.settings.timezone), timestamp)); + } } } return updated; @@ -203,15 +208,15 @@ public static boolean updateSensors(ShellyBaseHandler th, ShellySettingsStatus s th.logger.trace("{}: Updating flood", th.thingName); updated |= th.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_FLOOD, getOnOff(sdata.flood)); } - if (sdata.bat != null) { + if ((sdata.bat != null) && (sdata.bat.value != null)) { // no update for Sense th.logger.trace("{}: Updating battery", th.thingName); updated |= th.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_LEVEL, toQuantityType(getDouble(sdata.bat.value), DIGITS_PERCENT, SmartHomeUnits.PERCENT)); - if (sdata.bat.value != null) { // no update for Sense - updated |= th.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_LOW, - getDouble(sdata.bat.value) < th.config.lowBattery ? OnOffType.ON : OnOffType.OFF); - updated |= th.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_VOLT, - toQuantityType(getDouble(sdata.bat.voltage), DIGITS_VOLT, SmartHomeUnits.VOLT)); + updated |= th.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_VOLT, + toQuantityType(getDouble(sdata.bat.voltage), DIGITS_VOLT, SmartHomeUnits.VOLT)); + updated |= th.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_LOW, + getDouble(sdata.bat.value) < th.config.lowBattery ? OnOffType.ON : OnOffType.OFF); + if (getDouble(sdata.bat.value) < th.config.lowBattery) { th.postAlarm(ALARM_TYPE_LOW_BATTERY, false); } } @@ -220,7 +225,9 @@ public static boolean updateSensors(ShellyBaseHandler th, ShellySettingsStatus s updated |= th.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_CHARGER, getOnOff(sdata.charger)); } - th.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_LAST_UPDATE, getTimestamp()); + if (updated) { + th.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_LAST_UPDATE, getTimestamp()); + } } } return updated; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java index be3c694ba1a4..8bcb9c4aa085 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java @@ -14,7 +14,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.io.IOException; import java.util.HashMap; @@ -32,10 +32,10 @@ import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyShortLightStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusLight; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusLightChannel; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLight; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLightChannel; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; import org.openhab.binding.shelly.internal.coap.ShellyCoapServer; import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration; @@ -70,7 +70,7 @@ public ShellyLightHandler(Thing thing, ShellyBindingConfiguration bindingConfig, @Override public void initialize() { - logger.debug("Thing is using class {}", this.getClass()); + logger.debug("Thing is using {}", this.getClass()); super.initialize(); } @@ -208,7 +208,7 @@ public boolean handleDeviceCommand(ChannelUID channelUID, Command command) throw } // send changed colors to the device - sendColors(profile, lightId, oldCol, col); + sendColors(profile, lightId, oldCol, col, config.brightnessAutoOn); } return true; @@ -316,8 +316,6 @@ public boolean updateDeviceStatus(ShellySettingsStatus genericStatus) throws IOE Validate.notNull(profile, "updateThingStatus(): profile must not be null!"); Validate.isTrue(profile.isLight, "ERROR: Device " + profile.hostname + " is not a light. but class ShellyHandlerLight is called!"); - - Validate.notNull(profile); ShellyStatusLight status = api.getLightStatus(); Validate.notNull(status, "updateThingStatus(): status must not be null!"); logger.trace("Updating bulb/rgw2 status for {}, in {} mode, {} channel(s)", profile.hostname, profile.mode, @@ -349,6 +347,7 @@ public boolean updateDeviceStatus(ShellySettingsStatus genericStatus) throws IOE updated |= updateChannel(controlGroup, CHANNEL_LIGHT_POWER, getOnOff(light.ison)); updated |= updateChannel(controlGroup, CHANNEL_TIMER_AUTOON, getDecimal(light.autoOn)); updated |= updateChannel(controlGroup, CHANNEL_TIMER_AUTOOFF, getDecimal(light.autoOff)); + updated |= updateInputs(controlGroup, genericStatus, lightId); if (getBool(light.overpower)) { postAlarm(ALARM_TYPE_OVERPOWER, false); } @@ -438,7 +437,7 @@ private void setFullColor(String colorGroup, ShellyColorUtils col) { @SuppressWarnings("null") private void sendColors(@Nullable ShellyDeviceProfile profile, Integer lightId, ShellyColorUtils oldCol, - ShellyColorUtils newCol) throws IOException { + ShellyColorUtils newCol, boolean autoOn) throws IOException { Validate.notNull(profile); // boolean updated = false; @@ -449,7 +448,9 @@ private void sendColors(@Nullable ShellyDeviceProfile profile, Integer lightId, "{}: New color settings for channel {}: RGB {}/{}/{}, white={}, gain={}, brightness={}, color-temp={}", thingName, channelId, newCol.red, newCol.green, newCol.blue, newCol.white, newCol.gain, newCol.brightness, newCol.temp); - parms.put(SHELLY_LIGHT_TURN, profile.inColor || newCol.brightness > 0 ? SHELLY_API_ON : SHELLY_API_OFF); + if (autoOn) { + parms.put(SHELLY_LIGHT_TURN, profile.inColor || newCol.brightness > 0 ? SHELLY_API_ON : SHELLY_API_OFF); + } if (profile.inColor) { if (!oldCol.red.equals(newCol.red) || !oldCol.green.equals(newCol.green) || !oldCol.blue.equals(newCol.blue) || !oldCol.white.equals(newCol.white)) { diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyProtectedHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyProtectedHandler.java index a098ae9c7d2b..b701cad72221 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyProtectedHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyProtectedHandler.java @@ -45,7 +45,7 @@ public ShellyProtectedHandler(Thing thing, ShellyBindingConfiguration bindingCon @Override public void initialize() { - logger.debug("Thing is using class {}", this.getClass()); + logger.debug("Thing is using {}", this.getClass()); super.initialize(); } } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java index 3116499f70f2..77bba451ff51 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java @@ -14,7 +14,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.ShellyUtils.*; -import static org.openhab.binding.shelly.internal.api.ShellyApiJson.*; +import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*; import java.io.IOException; @@ -28,20 +28,20 @@ import org.eclipse.smarthome.core.library.types.PercentType; import org.eclipse.smarthome.core.library.types.StopMoveType; import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.shelly.internal.api.ShellyApiJson; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyControlRoller; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyInputState; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsDimmer; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsRelay; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsRoller; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellySettingsStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyShortLightStatus; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyShortStatusRelay; -import org.openhab.binding.shelly.internal.api.ShellyApiJson.ShellyStatusRelay; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDimmer; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRelay; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRoller; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortStatusRelay; +import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; import org.openhab.binding.shelly.internal.coap.ShellyCoapServer; import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration; @@ -76,7 +76,7 @@ public ShellyRelayHandler(Thing thing, ShellyBindingConfiguration bindingConfig, @Override public void initialize() { - logger.debug("Thing is using class {}", this.getClass()); + logger.debug("Thing is using {}", this.getClass()); super.initialize(); } @@ -199,7 +199,7 @@ private void handleBrightness(Command command, Integer index) throws IOException validateRange("brightness", value, 0, 100); logger.debug("{}: Setting dimmer brightness to {}", thingName, value); - api.setDimmerBrightness(index, value); + api.setDimmerBrightness(index, value, config.brightnessAutoOn); } @@ -306,6 +306,7 @@ public boolean updateRelays(ShellySettingsStatus status) throws IOException { ShellyDeviceProfile profile = getProfile(); boolean updated = false; + // Check for Relay in Standard Mode if (profile.hasRelays && !profile.isRoller && !profile.isDimmer) { logger.trace("{}: Updating {} relay(s)", thingName, profile.numRelays.toString()); @@ -324,6 +325,25 @@ public boolean updateRelays(ShellySettingsStatus status) throws IOException { updated |= updateChannel(groupName, CHANNEL_OUTPUT, getOnOff(relay.ison)); updated |= updateChannel(groupName, CHANNEL_TIMER_ACTIVE, getOnOff(relay.hasTimer)); + if (relay.extTemperature != null) { + // Shelly 1/1PM support up to 3 external sensors + // for whatever reason those are not represented as an array, but 3 elements + logger.debug("{}: Updating external sensor", thingName); + if (relay.extTemperature.sensor1 != null) { + updated |= updateChannel(groupName, CHANNEL_ETEMP_SENSOR1, + toQuantityType(getDouble(relay.extTemperature.sensor1.tC), SIUnits.CELSIUS)); + } + if (relay.extTemperature.sensor2 != null) { + updated |= updateChannel(groupName, CHANNEL_ETEMP_SENSOR2, + toQuantityType(getDouble(relay.extTemperature.sensor2.tC), SIUnits.CELSIUS)); + } + if (relay.extTemperature.sensor3 != null) { + updated |= updateChannel(groupName, CHANNEL_ETEMP_SENSOR3, + toQuantityType(getDouble(relay.extTemperature.sensor3.tC), SIUnits.CELSIUS)); + } + } + + // Update Auto-ON/OFF timer ShellySettingsRelay rsettings = profile.settings.relays.get(i); if (rsettings != null) { updated |= updateChannel(groupName, CHANNEL_TIMER_AUTOON, @@ -331,6 +351,8 @@ public boolean updateRelays(ShellySettingsStatus status) throws IOException { updated |= updateChannel(groupName, CHANNEL_TIMER_AUTOOFF, toQuantityType(getDouble(rsettings.autoOff), SmartHomeUnits.SECOND)); } + + // Update input(s) state updated |= updateInputs(groupName, status, i); i++; } @@ -338,6 +360,8 @@ public boolean updateRelays(ShellySettingsStatus status) throws IOException { } } } + + // Check for Relay in Roller Mode if (profile.hasRelays && profile.isRoller && (status.rollers != null)) { logger.trace("{}: Updating {} rollers", thingName, profile.numRollers.toString()); int i = 0; @@ -390,7 +414,7 @@ public boolean updateDimmers(ShellySettingsStatus orgStatus) throws IOException // the same structure as lights[] from Bulb and RGBW2. The tag gets replaced by dimmers[] so that Gson maps // to a different structure (ShellyShortLight). Gson gson = new Gson(); - ShellySettingsStatus dstatus = gson.fromJson(ShellyApiJson.fixDimmerJson(orgStatus.json), + ShellySettingsStatus dstatus = gson.fromJson(ShellyApiJsonDTO.fixDimmerJson(orgStatus.json), ShellySettingsStatus.class); Validate.notNull(dstatus.dimmers, "dstatus.dimmers must not be null!"); Validate.notNull(dstatus.tmp, "dstatus.tmp must not be null!"); @@ -409,12 +433,12 @@ public boolean updateDimmers(ShellySettingsStatus orgStatus) throws IOException // and send a OFF status to the same channel. // When the device's brightness is > 0 we send the new value to the channel and a ON command if (dimmer.ison) { - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS, OnOffType.ON); - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS, toQuantityType( + updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.ON); + updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", toQuantityType( new Double(getInteger(dimmer.brightness)), DIGITS_NONE, SmartHomeUnits.PERCENT)); } else { - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS, OnOffType.OFF); - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS, + updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.OFF); + updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", toQuantityType(new Double(0), DIGITS_NONE, SmartHomeUnits.PERCENT)); } @@ -433,34 +457,6 @@ public boolean updateDimmers(ShellySettingsStatus orgStatus) throws IOException return updated; } - /** - * Map input states to channels - * - * @param groupName Channel Group (relay / relay1...) - * - * @param status Shelly device status - * @return true: one or more inputs were updated - */ - @SuppressWarnings("null") - private boolean updateInputs(String groupName, ShellySettingsStatus status, int index) { - boolean updated = false; - if (status.inputs != null) { - if (profile.isDimmer || profile.isRoller) { - ShellyInputState state1 = status.inputs.get(0); - ShellyInputState state2 = status.inputs.get(1); - logger.trace("{}: Updating {}#input1 with {}, input2 with {}", thingName, groupName, - getOnOff(state1.input), getOnOff(state2.input)); - updated |= updateChannel(groupName, CHANNEL_INPUT + "1", getOnOff(state1.input)); - updated |= updateChannel(groupName, CHANNEL_INPUT + "2", getOnOff(state2.input)); - } else { - ShellyInputState state = status.inputs.get(index); - logger.trace("{}: Updating input[{}] with {}", thingName, index, getOnOff(state.input)); - updated |= updateChannel(groupName, CHANNEL_INPUT, getOnOff(state.input)); - } - } - return updated; - } - /** * Update LED channels * diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/config/config.xml index 0eaf93c0a3ba..93dad91aa040 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/config/config.xml @@ -10,7 +10,7 @@ - + User ID for HTTP API access. @@ -39,11 +39,68 @@ True if the binding should register to get the Short/Long Push Events. true + false + + + + If enabled, the CoAP protocol is used to receive status updates. + true + false + + + + Interval in seconds to query an update from the device. + 60 + s + true + + + + + + + + + + + User ID for HTTP API access. + + + + Password for HTTP API access. + password + + + + IP-Address of the Shelly device. + network-address + + + + true: Turn device ON if brightness > 0 is set; false: don't touch power status when brightness is set. true + + + True if the binding should register to get the Buttons Events. + true + false + + + + True if the binding should register to get the Relay Switch Events. + true + true + + + + True if the binding should register to get the Short/Long Push Events. + true + false + - If enabled the Coap protocol will be used to receive status updates. + If enabled, the CoAP protocol is used to receive status updates. true false @@ -72,8 +129,8 @@ network-address - - Threshold for the battery level, alert will be signed when battery level is below.. + + Threshold for the battery level, alert will be signed when battery level is below. Default: 20% 20 % @@ -85,7 +142,7 @@ - If enabled the Coap protocol will be used to receive status updates. + If enabled, the CoAP protocol is used to receive status updates. true true @@ -94,6 +151,7 @@ Interval in seconds to query an update from the device. 3600 sec + true diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly.properties b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly.properties new file mode 100644 index 000000000000..4b416c5d30c7 --- /dev/null +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly.properties @@ -0,0 +1,17 @@ +# Config status messages +config-status.error.missing-device-ip=IP address of the Shelly device is missing. + +# Thing status descriptions +offline.conf-error-wrong-mode=Device is no longer in the configured device mode. Delete the thing and re-discover the device. +offline.conf-error-access-denied=Access denied, check user id and password. +offline.conf-error-not-calibrated=Roller is not calibrated, run calibration in Shelly App. +offline.status-error-timeout=Device is not reachable (API timeout). +offline.status-error-unexpected-api-result=An unexpected API response. Please verify the logfile to get more detailed information. + +# Override some channel lables to make them more specific +channel-type.shelly.temperature1.label = Temperature 1 +channel-type.shelly.temperature1.description = Temperature of external sensor #1 +channel-type.shelly.temperature2.label = Temperature 2 +channel-type.shelly.temperature2.description = Temperature of external sensor #2 +channel-type.shelly.temperature3.label = Temperature 3 +channel-type.shelly.temperature3.description = Temperature of external sensor #3 diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly_de.properties b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly_de.properties new file mode 100644 index 000000000000..e5dc0a9b56a7 --- /dev/null +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/i18n/shelly_de.properties @@ -0,0 +1,379 @@ +# binding +binding.shelly.name = Shelly Binding +binding.shelly.description = Dieses Binding integriert Shelly-Komponenten, die ber WiFi gesteuert werden knnen. + +# Config status messages +config-status.error.missing-deviceip=Die IP-Adresse des Shelly Gertes ist nicht konfiguriert. + +# Thing status descriptions +offline.conf-error-wrong-mode=Das Gert befindet sich nicht mehr in der erwarteten Betriebsart. Lschen Sie das Gert und fhren Sie eine erneute Gerteerkennung durch. +offline.conf-error-access-denied=Der Zugriff wurde verweigert. berprfen Sie die konfigurierten Zugangsdaten, oder setzen diese entsprechend (analog zur Shelly App). +offline.conf-error-not-calibrated=Der Rollladen ist nicht kalibriert. Verwenden Sie die Shelly App, um eine Kalibrierung durchzufhren. +offline.status-error-timeout=Das Gert ist nicht erreichbar (API Timeout). +offline.status-error-unexpected-api-result=Es trat ein unerwartetes Problem beim API-Zugriff auf. berprfen Sie die Logdatei fr genauere Informationen. + +# thing types +thing-type.shelly.shelly1.label = Shelly1 (SHSW-1) +thing-type.shelly.shelly1.description = Shelly 1 (1 Relay) +thing-type.shelly.shelly1pm.label = Shelly1PM (SHSW-PM) +thing-type.shelly.shelly1pm.description = Shelly 1PM mit 1xRelais und Strommesser +thing-type.shelly.shellyem.label = ShellyEM (SHEM) +thing-type.shelly.shellyem.description = ShellyEM zur Energiemessung +thing-type.shelly.shelly2-relay.label = Shelly2 Relay (SHSW-21) +thing-type.shelly.shelly2-relay.description = Shelly2 im Relais-Modus (2xRelay, Strommesser) +thing-type.shelly.shelly2-roller.label = Shelly2 Relay (SHSW-21) +thing-type.shelly.shelly2-roller.description = Shelly2 im Rollanden-Modus (1xRolladen, Strommesser) +thing-type.shelly.shelly25-relay.label = Shelly2.5 Relay (SHSW-25) +thing-type.shelly.shelly25-relay.description = Shelly2.5 im Relais-Modus (2xRelais, 2 Strommesser) +thing-type.shelly.shelly25-roller.label = Shelly2.5 Roller (SHSW-25) +thing-type.shelly.shelly25-roller.description = Shelly2.5 im Rollanden-Modus (1xRolladen, Strommesser) +thing-type.shelly.shelly4pro.label = Shelly4 Pro Relay (SHSW-4) +thing-type.shelly.shelly4pro.description = Shelly 4 Pro mit 4 Relais und Strommessern +thing-type.shelly.shellyplug.label = Shelly Plug (SHPLG) +thing-type.shelly.shellyplug.description = Shelly Plug als schaltbare Steckdose +thing-type.shelly.shellyplugs.label = Shelly Plug-S (SHPLG-S) +thing-type.shelly.shellyplugs.description = Shelly Plug-S als schaltbare Steckdose und LEDs zur Statusanzeige +thing-type.shelly.shellydimmer.label = Shelly Dimmer (SHDM-1) +thing-type.shelly.shellydimmer.description = Shelly mit Dimmer-Funktion +thing-type.shelly.shellyht.label = Shelly HT (SHHT-1) +thing-type.shelly.shellyht.description = Shelly HT zur Temperatur- und Feuchtigkeitsmessung +thing-type.shelly.shellysmoke.label = Shelly Smoke +thing-type.shelly.shellysmoke.description = Shelly Rauchmelder +thing-type.shelly.shellyflood.label = Shelly Flood (SHWT-1) +thing-type.shelly.shellyflood.description = Shelly Wassermelder +thing-type.shelly.shellysense.label = Shelly Sense (SHSEN-1) +thing-type.shelly.shellysense.description = Shelly Bewegungsmelder +thing-type.shelly.shellybulb.label = Shelly Bulb (SHBLB-1) +thing-type.shelly.shellybulb.description = Shelly Glhbirne wei/Farbe +thing-type.shelly.shellyrgbw2-color.label = Shelly RGBW2 Color Mode (SHRGBW2) +thing-type.shelly.shellyrgbw2-color.description = Shelly RGBW-Controller im Farbmodus +thing-type.shelly.shellyrgbw2-white.label = Shelly RGBW2 White Mode (SHRGBW2) +thing-type.shelly.shellyrgbw2-white.description = Shelly RGBW-Controller im Wei-Modus, 4 Streifen + +# thing config - generic +thing-type.config.shelly.generic.userId.label = Benutzer +thing-type.config.shelly.generic.userId.description = Benutzerkennung fr API-Zugriff +thing-type.config.shelly.generic.password.label = Passwort +thing-type.config.shelly.generic.password.description = Passwort fr API-Zugriff +thing-type.config.shelly.generic.deviceIp.label = IP Adresse +thing-type.config.shelly.generic.deviceIp.description = IP Adresse der Shelly-Komponente +thing-type.config.shelly.generic.weakSignal.label = Schwaches Signal (dBm) +thing-type.config.shelly.generic.weakSignal.description = Ein Alarm wird ausgelst, wenn das WiFi-Signal diesen Wert unterschreitet. Voreinstellung: -80 dBm +thing-type.config.shelly.generic.eventsButton.label = Button Events +thing-type.config.shelly.generic.eventsButton.description = Aktiviert die Button Action URLS +thing-type.config.shelly.generic.eventsPush.label = Push Events +thing-type.config.shelly.generic.eventsPush.description = Aktiviert die Push Button Action URLS +thing-type.config.shelly.generic.eventsSwitch.label = Output Events +thing-type.config.shelly.generic.eventsSwitch.description = Aktiviert die Output Action URLS +thing-type.config.shelly.generic.eventsCoIoT.label = CoIoT aktivieren +thing-type.config.shelly.generic.eventsCoIoT.description = Aktiviert CoIoT-Protokoll (Coap-baisert) +thing-type.config.shelly.generic.updateInterval.label = Status-Intervall +thing-type.config.shelly.generic.updateInterval.description = Intervall fr die Hintergundaktualisiert + +# thing config - light +thing-type.config.shelly.light.userId.label = Benutzer +thing-type.config.shelly.light.userId.description = Benutzerkennung fr API-Zugriff +thing-type.config.shelly.light.password.label = Passwort +thing-type.config.shelly.light.password.description = Passwort fr API-Zugriff +thing-type.config.shelly.light.deviceIp.label = IP Adresse +thing-type.config.shelly.light.deviceIp.description = IP Adresse der Shelly-Komponente +thing-type.config.shelly.light.weakSignal.label = Schwaches Signal (dBm) +thing-type.config.shelly.light.weakSignal.description = Ein Alarm wird ausgelst, wenn das WiFi-Signal diesen Wert unterschreitet. Voreinstellung: -80 dBm +thing-type.config.shelly.light.brightnessAutoOn.label = Helligkeit Auto-EIN +thing-type.config.shelly.light.brightnessAutoOn.description = AN: Setzen einer Helligkeit > 0 schaltet das Gert automatisch ein; AUS: Gertestatus wird nicht gendert +thing-type.config.shelly.light.eventsButton.label = Button Events +thing-type.config.shelly.light.eventsButton.description = Aktiviert die Button Action URLS +thing-type.config.shelly.light.eventsPush.label = Push Events +thing-type.config.shelly.light.eventsPush.description = Aktiviert die Push Button Action URLS +thing-type.config.shelly.light.eventsSwitch.label = Output Events +thing-type.config.shelly.light.eventsSwitch.description = Aktiviert die Output Action URLS +thing-type.config.shelly.light.eventsCoIoT.label = CoIoT aktivieren +thing-type.config.shelly.light.eventsCoIoT.description = Aktiviert CoIoT-Protokoll (Coap-baisert) +thing-type.config.shelly.light.updateInterval.label = Status-Intervall +thing-type.config.shelly.light.updateInterval.description = Intervall fr die Hintergundaktualisiert + +# thing config - battery +thing-type.config.shelly.battery.userId.label = Benutzer +thing-type.config.shelly.battery.userId.description = Benutzerkennung fr API-Zugriff +thing-type.config.shelly.battery.password.label = Passwort +thing-type.config.shelly.battery.password.description = Passwort fr API-Zugriff +thing-type.config.shelly.battery.deviceIp.label = IP Adresse +thing-type.config.shelly.battery.deviceIp.description = IP Adresse der Shelly-Komponente +thing-type.config.shelly.battery.eventsSensorReport.label = Sensor Events +thing-type.config.shelly.battery.eventsSensorReport.description = Aktiviert die Sensor Action URLS +thing-type.config.shelly.battery.eventsCoIoT.label = CoIoT aktivieren +thing-type.config.shelly.battery.eventsCoIoT.description = Aktiviert CoIoT-Protokoll (Coap-baisert) +thing-type.config.shelly.battery.weakSignal.label = Schwaches Signal (dBm) +thing-type.config.shelly.battery.weakSignal.description = Ein Alarm wird ausgelst, wenn das WiFi-Signal diesen Wert unterschreitet. Voreinstellung: -80 dBm +thing-type.config.shelly.battery.lowBattery.label = Batterie niedrig (%) +thing-type.config.shelly.battery.lowBattery.description = Ein Alarm wird ausgelst, wenn das Gert eine Batterieladung kleiner diesem Schwellwert meldet. Default: 20% +thing-type.config.shelly.battery.updateInterval.label = Status-Intervall +thing-type.config.shelly.battery.updateInterval.description = Intervall fr die Hintergundaktualisiert + +# thing config - unknown +thing-type.config.shellydevice.userId.label = Benutzer +thing-type.config.shellydevice.userId.description = Benutzerkennung fr API-Zugriff +thing-type.config.shellydevice.password.label = Passwort +thing-type.config.shellydevice.password.description = Passwort fr API-Zugriff +thing-type.config.shellydevice.deviceIp.label = IP Adresse +thing-type.config.shellydevice.deviceIp.description = IP Adresse der Shelly-Komponente + +# channel-groups +#thing-type.astro.sun.group.rise.label = Sonnenaufgang +thing-type.shelly.shelly1.group.relay.label = Relais +thing-type.shelly.shelly1.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly1.group.sensors.label = Externe Sensoren +thing-type.shelly.shelly1.group.sensors.description = Temperaturwerte der externen Sensoren (nur wenn angeschlossen) +thing-type.shelly.shelly1.group.device.label = Gertestatus +thing-type.shelly.shelly1.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly1pm.group.relay.label = Relais +thing-type.shelly.shelly1pm.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly1pm.group.meter.label = Verbrauch +thing-type.shelly.shelly1pm.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly1pm.group.sensors.label = Externe Sensoren +thing-type.shelly.shelly1pm.group.sensors.description = Temperaturwerte der externen Sensoren (nur wenn angeschlossen) +thing-type.shelly.shelly1pm.group.device.label = Gertestatus +thing-type.shelly.shelly1pm.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellyem.group.relay.label = Relais +thing-type.shelly.shellyem.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shellyem.group.meter1.label = Verbrauch 1 +thing-type.shelly.shellye,.group.meter1.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyem.group.meter2.label = Verbrauch 2 +thing-type.shelly.shellyem.group.meter2.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyem.group.device.label = Gertestatus +thing-type.shelly.shellyem.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly2-relay.group.relay1.label = Relais 1 +thing-type.shelly.shelly2-relay.group.relay1.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly2-relay.group.relay2.label = Relais 2 +thing-type.shelly.shelly2-relay.group.relay2.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly2-relay.group.meter.label = Verbrauch +thing-type.shelly.shelly2-relay.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly2-relay.group.device.label = Gertestatus +thing-type.shelly.shelly2-relay.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly2-roller.group.roller.label = Rollladen +thing-type.shelly.shelly2-roller.group.roller.description = Rollladensteuerung und Status +thing-type.shelly.shelly2-roller.group.meter.label = Verbrauch +thing-type.shelly.shelly2-roller.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly2-roller.group.device.label = Gertestatus +thing-type.shelly.shelly2-roller.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly25-relay.group.relay1.label = Relais 1 +thing-type.shelly.shelly25-relay.group.relay1.description = Relais Ein-/ausgnge und -Funktionen +thing-type.shelly.shelly25-relay.group.relay2.label = Relais 2 +thing-type.shelly.shelly25-relay.group.relay2.description = Relais Ein-/ausgnge und -Funktionen +thing-type.shelly.shelly25-relay.group.meter1.label = Verbrauch 1 +thing-type.shelly.shelly25-relay.group.meter1.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly25-relay.group.meter2.label = Verbrauch 2 +thing-type.shelly.shelly25-relay.group.meter2.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly25-relay.group.device.label = Gertestatus +thing-type.shelly.shelly25-relay.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly25-roller.group.roller.label = Rollladen +thing-type.shelly.shelly25-roller.group.meter.label = Verbrauch +thing-type.shelly.shelly25-roller.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly25-roller.group.device.label = Gertestatus +thing-type.shelly.shelly25-roller.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shelly4pro.group.relay1.label = Relais 1 +thing-type.shelly.shelly4pro.group.relay1.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly4pro.group.relay2.label = Relais 2 +thing-type.shelly.shelly4pro.group.relay2.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly4pro.group.relay3.label = Relais 3 +thing-type.shelly.shelly4pro.group.relay3.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly4pro.group.relay4.label = Relais 3 +thing-type.shelly.shelly4pro.group.relay4.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shelly4pro.group.meter1.label = Verbrauch 1 +thing-type.shelly.shelly4pro.group.meter1.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly4pro.group.meter2.label = Verbrauch 2 +thing-type.shelly.shelly4pro.group.meter2.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly4pro.group.meter3.label = Verbrauch 3 +thing-type.shelly.shelly4pro.group.meter3.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly4pro.group.meter4.label = Verbrauch 4 +thing-type.shelly.shelly4pro.group.meter4.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shelly4pro.group.device.label = Gertestatus +thing-type.shelly.shelly4pro.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellyplug.group.relay.label = Relais +thing-type.shelly.shellyplug.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shellyplug.group.meter.label = Verbrauch +thing-type.shelly.shellyplug.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyplug.group.device.label = Gertestatus +thing-type.shelly.shellyplug.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellyplugs.group.relay.label = Relais +thing-type.shelly.shellyplugs.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shellyplugs.group.meter.label = Verbrauch +thing-type.shelly.shellyplugs.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyplugs.group.led.label = LEDs +thing-type.shelly.shellyplugs.group.led.description = Einstellungen zur Deaktivierung der LEDS +thing-type.shelly.shellyplugs.group.device.label = Gertestatus +thing-type.shelly.shellyplugs.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellydimmer.group.relay.label = Relais +thing-type.shelly.shellydimmer.group.relay.description = Relais Ein-/Ausgnge und Status +thing-type.shelly.shellydimmer.group.meter.label = Verbrauch +thing-type.shelly.shellypdimmer.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellydimmer.group.device.label = Gertestatus +thing-type.shelly.shellydimmer.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellybulb.group.control.label = Steuerung +thing-type.shelly.shellybulb.group.control.description = Steuerung des Lichts +thing-type.shelly.shellybulb.group.color.label = Farbmodus +thing-type.shelly.shellybulb.group.color.description = Einstellungen fr den Farbmodus +thing-type.shelly.shellybulb.group.white.label = Weiwerte +thing-type.shelly.shellybulb.group.white.description = Einstellungen fr den Wei-Modus +thing-type.shelly.shellybulb.group.device.label = Gertestatus +thing-type.shelly.shellybulb.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellyrgbw2-color.group.control.label = Steuerung +thing-type.shelly.shellyrgbw2-color.group.control.description = Steuerung des Controllers +thing-type.shelly.shellyrgbw2-color.group.color.label = Farben +thing-type.shelly.shellyrgbw2-color.group.color.description = Farbwerte und Profile +thing-type.shelly.shellyrgbw2-color.group.meter.label = Verbrauch +thing-type.shelly.shellyrgbw2-color.group.meter.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyrgbw2-color.group.device.label = Gertestatus +thing-type.shelly.shellyrgbw2-color.group.device.description = Informationen zum Gertestatus +thing-type.shelly.shellyrgbw2-white.group.channel1.label = Kanal 1 +thing-type.shelly.shellyrgbw2-white.group.channel1.description = Einstellungen fr Kanal 1 +thing-type.shelly.shellyrgbw2-white.group.channel2.label = Kanal 2 +thing-type.shelly.shellyrgbw2-white.group.channel2.description = Einstellungen fr Kanal 2 +thing-type.shelly.shellyrgbw2-white.group.channel3.label = Kanal 3 +thing-type.shelly.shellyrgbw2-white.group.channel3.description = Einstellungen fr Kanal 3 +thing-type.shelly.shellyrgbw2-white.group.channel4.label = Kanal 4 +thing-type.shelly.shellyrgbw2-white.group.channel4.description = Einstellungen fr Kanal 4 +thing-type.shelly.shellyrgbw2-white.group.meter1.label = Verbrauch 1 +thing-type.shelly.shellyrgbw2-white.group.meter1.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyrgbw2-white.group.meter2.label = Verbrauch 2 +thing-type.shelly.shellyrgbw2-white.group.meter2.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyrgbw2-white.group.meter3.label = Verbrauch 3 +thing-type.shelly.shellyrgbw2-white.group.meter3.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyrgbw2-white.group.meter4.label = Verbrauch 4 +thing-type.shelly.shellyrgbw2-white.group.meter4.description = Verbrauchswerte und andere Informationen +thing-type.shelly.shellyrgbw2-white.group.device.label = Gertestatus +thing-type.shelly.shellyrgbw2-white.group.device.description = Informationen zum Gertestatus + + +# channels +channel-type.shelly.timerAutoOn.label = Auto-EIN Timer +channel-type.shelly.timerAutoOn.description = Wenn das Relais ausgeschaltet wird, wird dieses autom. wieder nach n Sekunden eingeschaltet. +channel-type.shelly.timerAutoOff.label = Auto-AUS Timer +channel-type.shelly.timerAutoOff.description = Wenn das Relais eingeschaltet wird, wird dieses autom. wieder nach n Sekunden eingeschaltet. +channel-type.shelly.timerActive.label = Timer aktiv +channel-type.shelly.timerActive.description = ON: Auto-On/Off Timer ist aktiv +channel-type.shelly.temperature1.label = Temperatur 1 +channel-type.shelly.temperature1.description = Temperatur des externen Sensors #1 +channel-type.shelly.temperature2.label = Temperatur 2 +channel-type.shelly.temperature2.description = Temperatur des externen Sensors #2 +channel-type.shelly.temperature3.label = Temperatur 3 +channel-type.shelly.temperature3.description = Temperatur des externen Sensors #3 +channel-type.shelly.rollerShutter.label = Steuerung (0=offen, 100=geschlossen) +channel-type.shelly.rollerShutter.description = Steuerung fr den Rollladen: UP, DOWN, STOP, Position (0=offen, 100=geschlossen) +channel-type.shelly.rollerPosition.label = Position (100=offen, 0=zu) +channel-type.shelly.rollerPosition.description = Invertierte Position des Rollladen: 100=offen, 0=zu +channel-type.shelly.rollerStop.label = Stopp-Grund +channel-type.shelly.rollerStop.description = Letzter Grund fr das stoppen des Rollandens (normal=normaler Stopp, safety_switch=Sicherheits-Stopp, obstacle=Rollladen verhakt (Wiederstand erkannt) +channel-type.shelly.rollerDirection.label = Laufrichtung +channel-type.shelly.rollerDirection.description = Letzte Laufrichtung des Rollladen (open=auf, close=zu) +channel-type.shelly.inputState.label = Eingang +channel-type.shelly.inputState.description = Status des Relais-Eingangs +channel-type.shelly.inputState1.label = Eingang 1 +channel-type.shelly.inputState1.description = Status des Relais-Eingangs 1 +channel-type.shelly.inputState2.label = Eingang 2 +channel-type.shelly.inputState2.description = Status des Relais-Eingangs 2 +channel-type.shelly.dimmerBrightness.label = Helligkeit +channel-type.shelly.dimmerBrightness.description = Helligkeit (0-100%, 0=aus) +channel-type.shelly.meterWatts.label = Strom +channel-type.shelly.meterWatts.description = Aktueller Stromverbrauch in Watt +channel-type.shelly.meterReactive.label = Rcklauf +channel-type.shelly.meterReactive.description = Aktueller Stromverbrauch (Watt) des Rcklaufs +channel-type.shelly.lastPower1.label = Schnitte letzte Min +channel-type.shelly.lastPower1.description = Durchschnittsverbrauch der letzten Minute, 60s in Watt/Min +channel-type.shelly.lastPower2.label = Schnitt vorletzte Min +channel-type.shelly.lastPower2.description = Durchschnittsverbrauch der vorletzten Minute, 60s in Watt/Min +channel-type.shelly.lastPower3.label =Schnitt vor 3 Min +channel-type.shelly.lastPower3.description = Durchschnittsverbrauch vor 3 Minuten, 60s in Watt/Min +channel-type.shelly.meterTotal.label = Gesamtverbrauch +channel-type.shelly.meterTotal.description = Gesamtverbrauch seit Neustart in KW/h +channel-type.shelly.meterReturned.label = Rck-Strom +channel-type.shelly.meterReturned.description = Rcklauf in KW/h +channel-type.shelly.meterVoltage.label = Spannung +channel-type.shelly.meterVoltage.description = Spannung in Volt +channel-type.shelly.meterReturned.label = Rck-Strom KW/h +channel-type.shelly.meterReturned.description = Rcklauf in KW/h +channel-type.shelly.timestamp.label = Letzte Aktualisierung +channel-type.shelly.timestamp.description = Zeitstempel der letzten Aktualisierung (lokale Zeitzone) +channel-type.shelly.ledStatusDisable.label = WiFi Status-LED aus +channel-type.shelly.ledStatusDisable.description = ON: Die WiFi Status-LED am Gert ist deaktiviert +channel-type.shelly.ledPowerDisable.label = Betrieb LED +channel-type.shelly.ledPowerDisable.description = ON: Die Betriebsanzeige (LED) am Gert ist deaktiviert +channel-type.shelly.colorMode.label = Farbmodus +channel-type.shelly.colorMode.description = Betriebsart: ON: Farbe, OFF: Wei +channel-type.shelly.colorFull.label = Voll-Farbe +channel-type.shelly.colorFull.description = Ausgewhlte Farbe (red/green/blue/yellow/white) wird auf volle Intensitt gesetzt (255) +channel-type.shelly.colorFull.option.red = Rot +channel-type.shelly.colorFull.option.green = Grn +channel-type.shelly.colorFull.option.blue = Blau +channel-type.shelly.colorFull.option.yellow = Gelb +channel-type.shelly.colorFull.option.white = Wei +channel-type.shelly.colorRed.label = Rot +channel-type.shelly.colorRed.description = Rot-Anteil des RGB-Wertes (0-255) +channel-type.shelly.colorGreen.label = Grn +channel-type.shelly.colorGreen.description = Grn-Anteil des RGB-Wertes (0-255) +channel-type.shelly.colorBlue.label = Blau +channel-type.shelly.colorBlue.description = Blau-Anteil des RGB-Wertes (0-255) +channel-type.shelly.colorWhite.label = Wei +channel-type.shelly.colorWhite.description = Wei-Anteil des RGBW-Wertes (0-255) +channel-type.shelly.colorGain.label = Verstrkung +channel-type.shelly.colorGain.description = Verstrkung des Farbwertes (1-100%) +channel-type.shelly.whiteTemp.label = Lichttemperatur +channel-type.shelly.whiteTemp.description = Temperatur des Weilichtes (3000..6500K) +channel-type.shelly.whiteTemp.label = Helligkeit +channel-type.shelly.whiteTemp.description = Helligkeit des Weilichtes (0-100%, 0=aus) +channel-type.shelly.colorEffectBulb.label = Lichteffekt +channel-type.shelly.colorEffectBulb.description = Lichteffekt: 0: keiner, 1: Meteoritenregen, 2: Verlauf, 3: Atmen, 4: Blitzen, 5: bergang ein/aus, 6: Rot/Grn-Wechsel +channel-type.shelly.colorEffectBulb.option.0 = Aus +channel-type.shelly.colorEffectBulb.option.1 = Meteoritenregen +channel-type.shelly.colorEffectBulb.option.2 = Verlauf +channel-type.shelly.colorEffectBulb.option.3 = Atmen +channel-type.shelly.colorEffectBulb.option.4 = Blitzen +channel-type.shelly.colorEffectBulb.option.5 = bergang ein/aus +channel-type.shelly.colorEffectBulb.option.6 = Rot/Grn-Wechsel +channel-type.shelly.colorEffectRGBW2.label = Farbeffekt +channel-type.shelly.colorEffectRGBW2.description = Lichteffekt: 0: keiner, 1: Meteoritenregen, 2: Farbverlauf, 3: Blitzen +channel-type.shelly.colorEffectRGBW2.option.0 = Aus +channel-type.shelly.colorEffectRGBW2.option.1 = Meteoritenregen +channel-type.shelly.colorEffectRGBW2.option.2 = Farbverlauf +channel-type.shelly.colorEffectRGBW2.option.3 =Blitzen +channel-type.shelly.sensorTemp.label = Temperatur +channel-type.shelly.sensorTemp.description = Aktuelle Temperatur des Sensors in C +channel-type.shelly.sensorTempExt.label = Temperatur +channel-type.shelly.sensorTempExt.description = Aktuelle Temperatur des externen Sensors in C +channel-type.shelly.sensorHumidity.label = Luftfeuchtigkeit +channel-type.shelly.sensorHumidity.description = Relative Luftfeuchtigkeit in % +channel-type.shelly.sensorFlood.label = Wasseralarm +channel-type.shelly.sensorFlood.description = Alarm: Es wurde Wasser erkannt +channel-type.shelly.sensorSmoke.label = Rauchalarm +channel-type.shelly.sensorSmoke.description = Alarm: Es wurde Rauch erkannt +channel-type.shelly.sensorLux.label = Beleuchtungsstrke +channel-type.shelly.sensorLux.description = Beleuchtungsstrke in Lux +channel-type.shelly.sensorCharger.label = Ladegert +channel-type.shelly.sensorCharger.description = ON: Ein Ladegert ist angeschlossen +channel-type.shelly.batVoltage.label = Batteriespannung +channel-type.shelly.batVoltage.description = Batteriespannung in Volt (V) +channel-type.shelly.senseKey.label = IR-Code +channel-type.shelly.senseKey.description = IR Code senden im Pronto- oder HEX64-Format +channel-type.shelly.uptime.label = Laufzeit +channel-type.shelly.uptime.description = Anzahl Sekunden seit dem das Gert mit Strom versorgt wurde +channel-type.shelly.lastUpdate.label = Letzte Aktualisierung +channel-type.shelly.lastUpdate.description = Zeitstempel der letzten Aktualisierung (lokale Zeitzone) +channel-type.shelly.eventTrigger.label = Ereignis +channel-type.shelly.eventTrigger.description = Signalisiert Ereignisse (Trigger): ROLLER_OPEN=Rollanden geffnet, ROLLER_CLOSE=Rollladen geschlossen, ROLLER_STOP=Rollanden angehalten +channel-type.shelly.eventTrigger.option.ROLLER_OPEN = Rollladen geffnet +channel-type.shelly.eventTrigger.option.ROLLER_CLOSE = Rollladen geschlossen +channel-type.shelly.eventTrigger.option.ROLLER_STOP = Rollladen gestoppt +channel-type.shelly.eventTrigger.label = Alarm +channel-type.shelly.eventTrigger.description = Signalisiert Alarme (Trigger): NONE=kein Alarm, WEAK_SIGNAL=Schlechte WiFi-Verbindung, RESTARTED=Gert neu gestartet, OVERTEMP=berhitzung, OVERLOAD=berlast, OVERPOWER=Maximale Last berschritten, LOAD_ERROR=Lastfehler, LOW_BATTERY=Batterie schwach +channel-type.shelly.eventTrigger.option.NONE = kein Alarm +channel-type.shelly.eventTrigger.option.WEAK_SIGNAL=Schlechte WiFi-Verbindung +channel-type.shelly.eventTrigger.option.RESTARTED=Gert neu gestartet +channel-type.shelly.eventTrigger.option.OVERTEMP=berhitzung +channel-type.shelly.eventTrigger.option.OVERLOAD=berlast +channel-type.shelly.eventTrigger.option.OVERPOWER=Maximale Last berschritten +channel-type.shelly.eventTrigger.option.LOAD_ERROR=Lastfehler +channel-type.shelly.eventTrigger.option.LOW_BATTERY=Batterie schwach + +# Status error messages +config-status.error.missing-userid = Keine Benutzerkennung in der Thing Konfiguration + diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/channels.xml index b0da57f85b9b..7da93b7ba047 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/channels.xml @@ -6,13 +6,13 @@ Number:Time - + When Off - Turn On After xx seconds; 0 disables the timer Number:Time - + When ON - Turn On After xx seconds; 0 disables the timer @@ -58,11 +58,6 @@ - - Switch - - Turn light ON or OFF - Switch @@ -90,13 +85,6 @@ Light brightness in % DimmableLight - - Switch - - Error reported load error - - - Number:Power @@ -272,6 +260,17 @@ + + Number:Temperature + + Temperature from the external sensor + Temperature + + CurrentTemperature + + + + Number:Dimensionless diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/lights.xml b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/lights.xml index e8809e969260..1d4de9d3998d 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/lights.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/lights.xml @@ -16,7 +16,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -66,7 +66,7 @@ - + @@ -85,6 +85,8 @@ Control your light channels + + @@ -131,6 +133,8 @@ Switch channel and adjust settings + + diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/relay.xml index 8305b0d94013..bcc66b21eca9 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/relay.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/ESH-INF/thing/relay.xml @@ -9,6 +9,7 @@ Shelly1 device with single relay + @@ -21,6 +22,7 @@ + @@ -148,7 +150,7 @@ Shelly Plug device with relay and power meter - + @@ -179,7 +181,7 @@ - + @@ -195,7 +197,6 @@ - A Shelly relay channel @@ -207,6 +208,17 @@ + + + Temperatures from external sensors (if extension is installed and sensor connected) + + + + + + + + A Shelly dimmer channel