LogicMachine Forum
Shelly - WiFi IoT-Devices - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Gateway (https://forum.logicmachine.net/forumdisplay.php?fid=10)
+--- Thread: Shelly - WiFi IoT-Devices (/showthread.php?tid=3010)

Pages: 1 2


RE: Shelly - WiFi IoT-Devices - a455115 - 05.07.2022

(05.07.2022, 06:36)admin Wrote: Add before multiply function:
Code:
function onofftobool(payload)   return tostring(payload):lower() == 'on' end

Then modify mqtt_to_object_conv table:
Code:
mqtt_to_object_conv = {   ['shellies/shellyplug-s-D9AA39/relay/0'] = onofftobool, }
Thanks!


RE: Shelly - WiFi IoT-Devices - a455115 - 13.10.2022

(20.06.2022, 13:14)a455115 Wrote:
Code:
if not broker then   broker = '127.0.0.1'   function multiply(mult)     return function(value)       local num = tonumber(value)       if num then         return num * mult       else         return value       end     end   end   -- topic to object map   mqtt_to_object = {     ['shellies/shellyplug-s-D9AA39/relay/0'] = '32/1/1',     ['shellies/shellyplug-s-D9AA39/temperature'] = '32/1/2',   } -- optional topic value conversion function mqtt_to_object_conv = {   ['shellies/shellyplug-s-D9AA39/relay/0'] = multiply(1),    ['shellies/shellyplug-s-D9AA39/temperature'] = multiply(1), }   -- object to topic map object_to_mqtt = {    -- ['1/1/1'] = 'out/topic1',    -- ['1/1/2'] = 'out/topic2',   }   datatypes = {}   grp.sender = 'mq'   require('socket')   for addr, _ in pairs(object_to_mqtt) do     local obj = grp.find(addr)     if obj then       datatypes[ addr ] = obj.datatype     end   end   mclient = require('mosquitto').new()   mclient.ON_CONNECT = function(res, ...)     log('mqtt connect status', res, ...)     if res then       for topic, _ in pairs(mqtt_to_object) do         mclient:subscribe(topic)       end     else       mclient:disconnect()     end   end   mclient.ON_MESSAGE = function(mid, topic, payload)     local addr = mqtt_to_object[ topic ]     if addr then       local fn = mqtt_to_object_conv[ topic ]       if fn then         payload = fn(payload)       end       grp.write(addr, payload)     end   end   mclient.ON_DISCONNECT = function(...)     log('mqtt disconnect', ...)     mclientfd = nil   end   function mconnect()     local fd     mclient:connect(broker)     fd = mclient:socket()     -- fd ref is valid     if fd then       mclientfd = fd     end   end   mconnect()   function publishvalue(event)     -- message from us or client is not connected     if event.sender == 'mq' or not mclientfd then       return     end     local addr = event.dst     local dpt = datatypes[ addr ]     local topic = object_to_mqtt[ addr ]     -- unknown object     if not dpt or not topic then       return     end     local value = busdatatype.decode(event.datahex, dpt)     if value ~= nil then       if type(value) == 'boolean' then         value = value and 1 or 0       end       mclient:publish(topic, tostring(value))     end   end   lbclient = require('localbus').new(1)   lbclient:sethandler('groupwrite', publishvalue)   lbclientfd = socket.fdmaskset(lbclient:getfd(), 'r')   -- run timer every 5 seconds   timer = require('timerfd').new(5)   timerfd = socket.fdmaskset(timer:getfd(), 'r') end -- mqtt connected if mclientfd then   mclientfdset = socket.fdmaskset(mclientfd, mclient:want_write() and 'rw' or 'r')   res, lbclientstat, timerstat, mclientstat =       socket.selectfds(10, lbclientfd, timerfd, mclientfdset) -- mqtt not connected else   res, lbclientstat, timerstat =     socket.selectfds(10, lbclientfd, timerfd) end if mclientfd and mclientstat then   if socket.fdmaskread(mclientstat) then     mclient:loop_read()   end   if socket.fdmaskwrite(mclientstat) then     mclient:loop_write()   end end if lbclientstat then   lbclient:step() end if timerstat then   -- clear armed timer   timer:read()   if mclientfd then     mclient:loop_misc()   else     mconnect()   end end
Hi admin,
How do I convert directly from the code to get a specific parameter from the Json it returns? For an example of a specific topic it returns json to me 

shellies/shellytrv-14B457E5C2C8/info
return
{"tmp": {"value":24.5,"units": "C","is_valid": true},"target_t":{"enabled":false,"value":22.0,"units":"C "},"temperature_offset":0.0,"bat":99}

I only want to extract from it:
target_t - value - 1/1/1
bat - 1/1/2
How can I extract only this with the above code?


RE: Shelly - WiFi IoT-Devices - admin - 14.10.2022

Use this (1/1/1 is battery object, 1/1/2 is target temperature value object):
Code:
mqtt_to_object = {   ['shellies/shellytrv-14B457E5C2C8/info'] = '1/1/1', } mqtt_to_object_conv = {   ['shellies/shellytrv-14B457E5C2C8/info'] = function(payload)     local data = require('json').pdecode(payload)     if type(data) == 'table' then       grp.write('1/1/2', data.target_t.value)       return data.bat     end   end }



RE: Shelly - WiFi IoT-Devices - a455115 - 17.10.2022

(14.10.2022, 06:17)admin Wrote: Use this (1/1/1 is battery object, 1/1/2 is target temperature value object):
Code:
mqtt_to_object = {   ['shellies/shellytrv-14B457E5C2C8/info'] = '1/1/1', } mqtt_to_object_conv = {   ['shellies/shellytrv-14B457E5C2C8/info'] = function(payload)     local data = require('json').pdecode(payload)     if type(data) == 'table' then       grp.write('1/1/2', data.target_t.value)       return data.bat     end   end }
Hi admin,

Data.target_t.value does not work. This is a log from data, and from data.thermostats, how should I get the target_t ? If I have many shelits for each, should I add it this way?
Code:
log (data) ["ps_mode"]   * number: 0 ["thermostats"]   * table:    [1]     * table:      ["tmp"]       * table:        ["is_valid"]         * bool: true        ["units"]         * string: C        ["value"]         * number: 24.7      ["pos"]       * number: 50      ["target_t"]       * table:        ["value_op"]         * number: 8        ["enabled"]         * bool: false        ["units"]         * string: C        ["value"]         * number: 22      ["window_open"]       * bool: false      ["boost_minutes"]       * number: 0      ["schedule"]       * bool: false      ["schedule_profile"]       * number: 1 ["fs_free"]   * number: 59376 ["wifi_sta"]   * table:    ["connected"]     * bool: true    ["rssi"]     * number: -59    ["ssid"]     * string: Project Solutions    ["ip"]     * string: 10.0.5.105 ["dbg_flags"]   * number: 0 ["mac"]   * string: 14B457E5C2C8 ["cloud"]   * table:    ["connected"]     * bool: false    ["enabled"]     * bool: false ["time"]   * string: 12:47 ["update"]   * table:    ["new_version"]     * string: 20220811-152343/v2.1.8@5afc928c    ["old_version"]     * string: 20220811-152343/v2.1.8@5afc928c    ["status"]     * string: unknown    ["beta_version"]     * userdata: NULL    ["has_update"]     * bool: false ["bat"]   * table:    ["voltage"]     * number: 4.077    ["value"]     * number: 99 ["unixtime"]   * number: 1666000030 ["ram_total"]   * number: 97280 ["fw_info"]   * table:    ["fw"]     * string: 20220811-152343/v2.1.8@5afc928c    ["device"]     * string: shellytrv-14B457E5C2C8 ["calibrated"]   * bool: true ["uptime"]   * number: 5326 ["charger"]   * bool: false ["ram_free"]   * number: 22568 ["actions_stats"]   * table:    ["skipped"]     * number: 0 ["serial"]   * number: 0 ["mqtt"]   * table:    ["connected"]     * bool: true ["has_update"]   * bool: false ["cfg_changed_cnt"]   * number: 0 ["fs_size"]   * number: 65536 log(data.thermostats) [1]   * table:    ["tmp"]     * table:      ["is_valid"]       * bool: true      ["units"]       * string: C      ["value"]       * number: 24.7    ["pos"]     * number: 50    ["target_t"]     * table:      ["value_op"]       * number: 8      ["enabled"]       * bool: false      ["units"]       * string: C      ["value"]       * number: 22    ["window_open"]     * bool: false    ["boost_minutes"]     * number: 0    ["schedule"]     * bool: false    ["schedule_profile"]     * number: 1



RE: Shelly - WiFi IoT-Devices - admin - 17.10.2022

Try this:
Code:
mqtt_to_object = {   ['shellies/shellytrv-14B457E5C2C8/info'] = '1/1/1', -- battery level   ['shellies/shellytrv-ABC/info'] = '2/1/1', -- battery level   ['shellies/shellytrv-DEF/info'] = '3/1/1', -- battery level } function conv_therm(payload, target_t_addr)   local data = require('json').pdecode(payload)   if type(data) == 'table' then     grp.write(target_t_addr, data.thermostats[1].target_t.value)     return data.bat.value   end end mqtt_to_object_conv = {   ['shellies/shellytrv-14B457E5C2C8/info'] = function(payload)     return conv_therm(payload, '1/1/2') -- target temp   end,   ['shellies/shellytrv-ABC/info'] = function(payload)     return conv_therm(payload, '2/1/2') -- target temp   end,   ['shellies/shellytrv-DEF/info'] = function(payload)     return conv_therm(payload, '3/1/2') -- target temp   end }



RE: Shelly - WiFi IoT-Devices - a455115 - 17.10.2022

(17.10.2022, 10:00)admin Wrote: Try this:
Code:
mqtt_to_object = {   ['shellies/shellytrv-14B457E5C2C8/info'] = '1/1/1', -- battery level   ['shellies/shellytrv-ABC/info'] = '2/1/1', -- battery level   ['shellies/shellytrv-DEF/info'] = '3/1/1', -- battery level } function conv_therm(payload, target_t_addr)   local data = require('json').pdecode(payload)   if type(data) == 'table' then     grp.write(target_t_addr, data.thermostats[1].target_t.value)     return data.bat.value   end end mqtt_to_object_conv = {   ['shellies/shellytrv-14B457E5C2C8/info'] = function(payload)     return conv_therm(payload, '1/1/2') -- target temp   end,   ['shellies/shellytrv-ABC/info'] = function(payload)     return conv_therm(payload, '2/1/2') -- target temp   end,   ['shellies/shellytrv-DEF/info'] = function(payload)     return conv_therm(payload, '3/1/2') -- target temp   end }

It works, thanks a lot!


RE: Shelly - WiFi IoT-Devices - a455115 - 20.10.2022

What is the maximum number of objects/devices Logic Machine can work with without problems? I want to hook up an apartment complex with shelly.


RE: Shelly - WiFi IoT-Devices - admin - 20.10.2022

It should handle several hundred devices.


RE: Shelly - WiFi IoT-Devices - tomnord - 03.01.2024

Hi, with the above code, you use broadcast topic "shellies". If I use a topic set in a device, eg a ShellyPluss1 (relay) eith add-on module, how can i sort the different values on the same topic?
I made this based on the above, but it only works on th ebinary status object, not temperature:

Code:
function conv_shellyRelay(payload, numberRel, target_s_addr)   local data = require('json').pdecode(payload)     if type(data) == 'table' then       grp.write(target_s_addr, data["params"][numberRel]["output"])       log(data.bat.value)       return data.bat.value   end end         function conv_shellyTemp(payload, numberTemp, target_t_addr)   local data = require('json').pdecode(payload)     if type(data) == 'table' then       log(data["params"][numberTemp]["tC"])         grp.write(target_t_addr, data["params"][numberTemp]["tC"])     return data.bat.value   end end     -- topic to object map   mqtt_to_object = {     ['Shelly/events/rpc']         = '33/1/8', -- Temperature 1     ['Shelly/events/rpc']         = '33/1/9',    -- Status relay       ['Shelly/events/rpc']         = '33/1/10',-- Temperature 2   }       mqtt_to_object_conv = {       ['Shelly/events/rpc'] = function(payload)    return conv_shellyTemp(payload,"temperature:100", '33/1/8')   end,            ['Shelly/events/rpc'] = function(payload)    return conv_shellyTemp(payload,"temperature:101", '33/1/10')   end,          ['Shelly/events/rpc'] = function(payload)    return conv_shellyRelay(payload,"switch:0", '33/1/9')   end,          }   -- object to topic map   object_to_mqtt = {        ['33/1/7']     = 'Shelly/command/switch:0', }



RE: Shelly - WiFi IoT-Devices - admin - 03.01.2024

You have duplicate keys in mqtt_to_object and mqtt_to_object_conv - this won't work. If multiple devices share the same topic then you need to manually implement logic for distinguishing what kind of data is received and which object must be updated.


RE: Shelly - WiFi IoT-Devices - tomnord - 03.01.2024

(03.01.2024, 10:19)admin Wrote: You have duplicate keys in mqtt_to_object and mqtt_to_object_conv - this won't work. If multiple devices share the same topic then you need to manually implement logic for distinguishing what kind of data is received and which object must be updated.

Ok, I was afraid of that. So i need to make logic that only reads topic once, and then sorts out the different values I'm looking for.

So I made a function to look up certain names in the table, is there any way to have the mqtt_to_object run without a GA attached? It will only run the first grp.write:
Code:
function conv_shellyTemp(payload)   local data = require('json').pdecode(payload)        if type(data) == 'table' then                function tableHasKey(table, prefix)                         for key, _ in pairs(table) do                       --log(key)                         if string.match(key, prefix) then                         return true                         end                         end                         return false                         end          if tableHasKey(data["params"],"temperature") then                    grp.write('33/1/8', data["params"]["temperature:100"]["tC"])                 grp.write('33/1/10', data["params"]["temperature:101"]["tC"])        elseif             tableHasKey(data["params"],"switch") then                    grp.write('33/1/9', data["params"]["switch:0"]["output"])           else         log("no data")         end     end   end



RE: Shelly - WiFi IoT-Devices - tomnord - 03.01.2024

(03.01.2024, 10:26)tomnord Wrote:
(03.01.2024, 10:19)admin Wrote: You have duplicate keys in mqtt_to_object and mqtt_to_object_conv - this won't work. If multiple devices share the same topic then you need to manually implement logic for distinguishing what kind of data is received and which object must be updated.

Ok, I was afraid of that. So i need to make logic that only reads topic once, and then sorts out the different values I'm looking for.

So I made a function to look up certain names in the table, is there any way to have the mqtt_to_object run without a GA attached? It will only run the first grp.write:
Code:
function conv_shellyTemp(payload)   local data = require('json').pdecode(payload)        if type(data) == 'table' then                function tableHasKey(table, prefix)                         for key, _ in pairs(table) do                       --log(key)                         if string.match(key, prefix) then                         return true                         end                         end                         return false                         end          if tableHasKey(data["params"],"temperature") then                    grp.write('33/1/8', data["params"]["temperature:100"]["tC"])                 grp.write('33/1/10', data["params"]["temperature:101"]["tC"])        elseif             tableHasKey(data["params"],"switch") then                    grp.write('33/1/9', data["params"]["switch:0"]["output"])           else         log("no data")         end     end   end

Figured it out, needed to activate status sending.
But I would lik eto be able to use the GetStatus function from, it seems to be a request that does not need a input.
https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Sys#sysgetstatus-example


RE: Shelly - WiFi IoT-Devices - admin - 03.01.2024

You can attach topic to a dummy object. If the conversion function does not return anything the grp.write won't happen anyway.

For HTTP requests search the forum, there are many examples that can be adapted.


RE: Shelly - WiFi IoT-Devices - tomnord - 16.01.2024

Code:
["thermostats"]   * table:    [1]     * table:      ["valve_min_percent"]       * number: 0      ["t_auto"]       * table:        ["enabled"]         * bool: true      ["target_t"]       * table:        ["units"]         * string: C        ["value_op"]         * number: 8        ["enabled"]         * bool: true        ["accelerated_heating"]         * bool: true        ["value"]         * number: 7      ["extra_pressure"]       * bool: false      ["calibration_correction"]       * bool: true      ["schedule_profile_names"]       * table:        [1]         * string: Livingroom        [2]         * string: Livingroom 1        [3]         * string: Bedroom        [4]         * string: Bedroom 1        [5]         * string: Holiday      ["schedule_profile"]       * number: 1      ["open_window_report"]       * bool: false      ["boost_minutes"]       * number: 30      ["valve_min_report"]       * number: 1      ["force_close"]       * bool: false      ["schedule_rules"]       * table:        [1]         * string: 0600-0123456-23        [2]         * string: 2300-0123456-18      ["ext_t"]       * table:        ["floor_heating"]         * bool: false        ["enabled"]         * bool: true      ["schedule"]       * bool: false      ["temperature_offset"]       * number: 0

I am trying to write to the object "temperature_offset" but i can not get the syntax right. 
"'shellies/TRV_ROM1/settings/thermostats  . .. " 
It is stated as a parameter in the documentation for mqtt. 
https://shelly-api-docs.shelly.cloud/gen1/#shelly-trv-settings-thermostats-0

The http command is:

Code:
http://10.xxx.xxx.xxx/ext_t?temp=measured t°



RE: Shelly - WiFi IoT-Devices - admin - 16.01.2024

Try http://IP/settings/thermostats/0?temperature_offset=5
If this does not work then contact Shelly support.


RE: Shelly - WiFi IoT-Devices - tomnord - 16.01.2024

shellies/TRV_ROM1/thermostat/0/command/ext_t

This worked over MQTT. had to dig in the docu, TRV needed to be set as Floor_heating to use external value.


Quick question, can I have several MQTT scripts running, e.g one for each component? Or should I run all in one script?


RE: Shelly - WiFi IoT-Devices - admin - 16.01.2024

You can use multiple scripts but it makes more sense to handle everything in a single script.


RE: Shelly - WiFi IoT-Devices - tomnord - 16.01.2024

YEah, I guess. just thought it would be easier to auto generate GA's in separate scrips.