| 
		
	
	
	
		
	Posts: 102 
	Threads: 16 
	Joined: Aug 2019
	
 Reputation: 
0 
	
	
		 (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!
	 
		
	 
	
	
	
		
	Posts: 102 
	Threads: 16 
	Joined: Aug 2019
	
 Reputation: 
0 
	
		
		
		13.10.2022, 14:26 
(This post was last modified: 13.10.2022, 14:28 by a455115.)
		
	 
		 (20.06.2022, 13:14)a455115 Wrote:  Code: if not broker thenbroker = '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?
	 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		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
 }
		
	 
	
	
	
		
	Posts: 102 
	Threads: 16 
	Joined: Aug 2019
	
 Reputation: 
0 
	
	
		 (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
 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		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
 }
		
	 
	
	
	
		
	Posts: 102 
	Threads: 16 
	Joined: Aug 2019
	
 Reputation: 
0 
	
	
		 (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!
	 
		
	 
	
	
	
		
	Posts: 102 
	Threads: 16 
	Joined: Aug 2019
	
 Reputation: 
0 
	
	
		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.
	 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		It should handle several hundred devices.
	 
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
	
		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',
 }
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		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.
	 
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
		
		
		03.01.2024, 10:26 
(This post was last modified: 03.01.2024, 11:05 by tomnord.)
		
	 
		 (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
 
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
	
		 (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/gen...us-example 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		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.
 
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
	
		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/gen...rmostats-0 
The http command is:
 Code: http://10.xxx.xxx.xxx/ext_t?temp=measured t°
 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		Try http://IP/settings/thermostats/0?temperature_offset=5 
If this does not work then contact Shelly support.
	
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
	
		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?
 
		
	 
	
	
	
		
	Posts: 8410 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
481 
	
	
		You can use multiple scripts but it makes more sense to handle everything in a single script.
	 
		
	 
	
	
	
		
	Posts: 238 
	Threads: 66 
	Joined: May 2018
	
 Reputation: 
4 
	
	
		YEah, I guess. just thought it would be easier to auto generate GA's in separate scrips.
	 
		
	 |