(SOLVED) Convert LUA script into dzVents

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Post Reply
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

(SOLVED) Convert LUA script into dzVents

Post by costo »

New to dzVents, made a LUA script a few years ago to extract cpm, temperatue and uptime
this script works fine but I'm trying to convert this script into dzVents.

The uRadmonitor sensor on '192.168.178.26/j' generates this json format line
{"data":{ "id":"12000059","type":"1","detector":"SI29BG","cpm":9,"temperature":29.31,"uptime": 1407157}}

My first try is to extract the cpm value , the sensorname is cpmCount
apparently the json decoding is not right becouse cpmCount is always zero

Code: Select all

local IP = '192.168.178.26' -- uRadmonitor sensor IP

return {
	active = true,
	on = {
		timer = { 'every minute' },
		httpResponses = { 'cpmRetrieved' } -- matches callback string below
	},
	execute = function(domoticz, item)

		if (item.isTimer) then
			domoticz.openURL({
				url = 'http://' .. IP .. '/j',
				method = 'GET',
				callback = 'cpmRetrieved',
			})


    elseif (item.isHTTPResponse) then
			if (item.ok) then -- and item.isJSON) then -- statusCode == 2xx
            -- if (item.statusCode==0) then 
			    local Count = item.data.cpm
			    domoticz.log('status = ',tonumber(Count))
			    domoticz.devices('cpmCount').updateCustomSensor(Count)
		        
            end
        end
end
}
any suggestion can help me.

log output:
2025-05-11 21:57:00.216 dzVents: Handling httpResponse-events for: "cpmRetrieved"
2025-05-11 21:57:00.216 dzVents: ------ Start internal script: cpm_dzvents: HTTPResponse: "cpmRetrieved"
2025-05-11 21:57:00.216 dzVents: status =
2025-05-11 21:57:00.217 dzVents: ------ Finished cpm_dzvents
Last edited by costo on Tuesday 13 May 2025 21:28, edited 1 time in total.
User avatar
waltervl
Posts: 5770
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Convert LUA script into dzVents

Post by waltervl »

You can log the table item.data to see what is in it.
Also the log statement you are using is not correct, it should be

Code: Select all

domoticz.log('status = ' .. Count) 
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

If I write 'domoticz.log('status = ' .. Count) ' then i see this error

2025-05-11 23:29:00.346 Error: dzVents: An error occurred when calling event handler cpm_dzvents
2025-05-11 23:29:00.346 Error: dzVents: ...moticz/scripts/dzVents/generated_scripts/cpm_dzvents.lua:26: attempt to concatenate a nil value

I tried to log the table but i was not succesfull
User avatar
waltervl
Posts: 5770
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Convert LUA script into dzVents

Post by waltervl »

You should be able to see the complete data with log statement.

Code: Select all

domoticz.log(item.data,dz.LOG_FORCE)
It could be that you have to use data twice to get the count eg

Code: Select all

local Count = item.data.data.cpm
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

negative, both lines give an Error : attempt to index a nil value (global 'dz') or (field 'data')

print (item.data) prints the line as seen in the browser,
{"data":{ "id":"12000059","type":"1","detector":"SI29BG","cpm":9,"temperature":29.31,"uptime": 1407157}}

print (item.data.id),
print (item.data.cpm),
print (item.data.temperature),
print (item.data.uptime),

all are nil values.
User avatar
habahabahaba
Posts: 232
Joined: Saturday 18 March 2023 14:44
Target OS: Windows
Domoticz version: 2024.4
Contact:

Re: Convert LUA script into dzVents

Post by habahabahaba »

costo wrote: Monday 12 May 2025 0:22 negative, both lines give an Error : attempt to index a nil value (global 'dz') or (field 'data')

print (item.data) prints the line as seen in the browser,
{"data":{ "id":"12000059","type":"1","detector":"SI29BG","cpm":9,"temperature":29.31,"uptime": 1407157}}

print (item.data.id),
print (item.data.cpm),
print (item.data.temperature),
print (item.data.uptime),

all are nil values.
According to https://jsonparser.org/ you have some incorrect values. It should be
{"data":{ "id":"12000059","type":"1","detector":"SI29BG","cpm":"9","temperature":"29.31","uptime": "1407157"}}

Try to put to Dzvents script this:

Code: Select all

if (item.isJSON) then...
to check if Dz understandig incoming Json or not.
User avatar
waltervl
Posts: 5770
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Convert LUA script into dzVents

Post by waltervl »

The error in the log line is my fault
It should be

Code: Select all

domoticz.log(item.data,domoticz.LOG_FORCE)
And if item.data shows data entry in the JSON I believe you should use data twice like

Code: Select all

print (item.data.data.cpm)
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

Using this:

Code: Select all

	if (item.ok  and item.isJSON) then -- statusCode == 2xx

			    domoticz.log(item.data,domoticz.LOG_FORCE)
			    print ('cpm = '..item.data.data.cpm)
            end

which gives an error in the print() line so apparently the data is recognized as json .

In the link jparser.org I can put the data line and the parser makes this of it

data {6}
id : 12000059
type : 1
detector : SI29BG
cpm : 9
temperature : 29.31
uptime : 1407157

that looks very usefull but upto now I only get nil value errors

in the log this line:
!Info: {"data":{ "id":"12000059","type":"1","detector":"SI29BG","cpm":9,"temperature":34.31,"uptime": 1462644}}
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

For completeness this is the LUA script that works fine for many years

Code: Select all

-- Script to calculate average CPM
local idxUptime = 14                -- idx of Uptime 
local idxCpm    = 15                -- idx of simpel cpm1
local idxWA     = 16                -- idx of wAverage30
local idxTemp   = 13                -- idx of Tempsensor
local cpm = " "				        -- counts in last minute
local uptime = " "			        -- in seconds
local temperature = " "
local cpmWalkAv = 'WAcpm'           -- WAcpm user variable
local IPcpm =   '192.168.178.26'    -- change IP here

-- NOTE: Fetch data from external servers without locking the event system!
-- see https://www.domoticz.com/forum/viewtopic.php?t=19327

commandArray={}
	json = (loadfile "/home/co/domoticz/scripts/lua/JSON.lua")()			-- JSON library on user 'co'
	  local jsondata    = assert(io.popen('curl http://' .. IPcpm .. '/j'))	-- open URADmonitor
	  local jsondevices = jsondata:read('*all')								-- read 'data'
	jsondata:close()	                                                    -- close URADmonitor
      -- print ('devices =' .. jsondevices)
    local jsonCPM = json:decode(jsondevices)								-- decode json string
    if (jsonCPM ~= nil) then                                                -- jsonCPM is a table                  --
        cpm = jsonCPM.data.cpm													-- cpm
 	    uptime = jsonCPM.data.uptime
        temperature = math.floor(10*(jsonCPM.data.temperature + .05))/10        -- temp in tenth degrees
        wAverage30 = tonumber(uservariables[cpmWalkAv])							-- load old WAcpm_uservar
        wAverage30 = (29 * wAverage30 + cpm)/30									-- calculate new WAcpm_uservar
        wAverage30 = tonumber(string.format("%." .. 2 .. "f", wAverage30))		-- format 2 digits after dot
        commandArray['Variable:' .. cpmWalkAv] = tostring(wAverage30)			-- update new WAcpm_uservar every minute
	
        time = os.date("*t")	
        if  (((time.min+1) % 1)==0)  then         -- update devices every 5 minutes. 1,6,11,16,21,26	
            uptime = math.floor(uptime/60)
            commandArray[1] = {['UpdateDevice'] = idxUptime .. '|0|' .. uptime}		-- in minutes
            commandArray[2] = {['UpdateDevice'] = idxTemp .. '|0|' .. temperature}	-- T
            commandArray[4] = {['UpdateDevice'] = idxCpm .. '|0|' .. cpm}			-- send cpm cnt/min
            commandArray[5] = {['UpdateDevice'] = idxWA .. '|0|' .. wAverage30}		-- send wAverage30
        end
    end  

return commandArray
User avatar
habahabahaba
Posts: 232
Joined: Saturday 18 March 2023 14:44
Target OS: Windows
Domoticz version: 2024.4
Contact:

Re: Convert LUA script into dzVents

Post by habahabahaba »

Fully working example with JSON:

Code: Select all

-- TEST

return {
	on = {
		timer = {
			'every minute' -- just an example set as often as you need
		},
		httpResponses = {
			'USGovWeathertrigger' -- must match with the callback passed to the openURL command
		}
	},
	logging = {
		level = domoticz.LOG_INFO,
		marker = 'USGovWeathertrigger',
	},
	execute = function(domoticz, item)
	    
	    local APIURL = 'https://api.weather.gov/points/39.7456,-97.0892'

		if (item.isTimer) then
			domoticz.openURL({
				url = APIURL,  
				method = 'GET',
				callback = 'USGovWeathertrigger', -- see httpResponses above.
			}).afterSec(5)
		end

		if (item.isHTTPResponse) then

			if (item.ok) then
				if (item.isJSON) then
				    
                    --domoticz.utils.dumpTable(item.json)
                    
                    local city = item.json.properties.relativeLocation.properties.city

                    local state = item.json.properties.relativeLocation.properties.state
                    
                    local coord1 = item.json.properties.relativeLocation.geometry.coordinates[1] -- 1 because in JSON elements start from 0 and in table it starts from 1
                    local coord2 = item.json.properties.relativeLocation.geometry.coordinates[2]
                        

                    domoticz.log('City='.. city.. '  State='.. state .. ';  Coordinates: '.. coord1..'; '.. coord2, domoticz.LOG_ERROR) -- los as ERROR just to mark it for easy find
                        

				end
			else
				domoticz.log('LOG_ERROR', domoticz.LOG_ERROR)
			end

		end

	end
}
Try

Code: Select all

local Count = item.json.data.cpm
domoticz.log('status = ' .. Count, LOG_INFO)
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

YES !!!
That does the trick

thank you thank you thank you
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

So I got a basic working dzVents script

Code: Select all

local IP = '192.168.178.26' -- uRadmonitor sensor IP

return {
	active = true,

	on = {
		timer = { 'every minute' },
		httpResponses = { 'cpmRetrieved' } -- matches callback string below
	},

	execute = function(domoticz, item)

		if (item.isTimer) then
			domoticz.openURL({
				url = 'http://' .. IP .. '/j',
				method = 'GET',
				callback = 'cpmRetrieved',
			})

    elseif (item.isHTTPResponse) then
			if (item.ok  and item.isJSON) then -- statusCode == 2xx
			    local Count = (item.json.data.cpm)
                local Up = (item.json.data.uptime/60)
                local Temp = (item.json.data.temperature)
			    print (item.data)
			    domoticz.devices('cpmCount').updateCustomSensor(Count)
			    domoticz.devices('cpmUp').updateCustomSensor(Up)
			    domoticz.devices('cpmT').updateTemperature(Temp)

            end
        end
end
}
Now I need to do some math, dzVents documentation for math functions seems non-existent.

The Temperature is displayed with 2 decimals, I need only 1
The Uptime in minutes needs to be rounded , no decimals.
Then I need to engineer some way to make a Cumulative Average of the last 30 readings
in LUA that needed one uservariable. and a few lines of code

Code: Select all

        cpm = jsonCPM.data.cpm													-- cpm
 	uptime = jsonCPM.data.uptime
        temperature = math.floor(10*(jsonCPM.data.temperature + .05))/10        -- temp in tenth degrees
        wAverage30 = tonumber(uservariables[cpmWalkAv])							-- load old WAcpm_uservar
        wAverage30 = (29 * wAverage30 + cpm)/30									-- calculate new WAcpm_uservar
        wAverage30 = tonumber(string.format("%." .. 2 .. "f", wAverage30))		-- format 2 digits after dot
        commandArray['Variable:' .. cpmWalkAv] = tostring(wAverage30)			-- update new WAcpm_uservar every minute
whatever I try in dzVents it ends in errors.
User avatar
habahabahaba
Posts: 232
Joined: Saturday 18 March 2023 14:44
Target OS: Windows
Domoticz version: 2024.4
Contact:

Re: Convert LUA script into dzVents

Post by habahabahaba »

local temp = domoticz.utils.round(temperature , 1)
local Uptime = domoticz.utils.round(Uptime, 0)

local wAverage30 = domoticz.variables('cpmWalkAv').value
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

thanks habahabahaba, your input is very helpfull.

Most of the things work.
I still use a uservariable, just as in the LUA script, maybe in dzVents there is a better way but for now the uservariable is ok.

reading from the uservariable is like this:
local wAverage30 = domoticz.variables('CAcpm').value -- uservariable

but writing a new value in the uservariables table is erronous.

I tried -- domoticz.variables.CAcpm.value = tostring(wAverage30)
and get this error 'attempt to index a function value (field 'variables')

this is part of my code:

Code: Select all

	if (item.ok and item.isJSON) then -- statusCode == 2xx
	    print (item.data)
	    local Count  = item.json.data.cpm
             local Uptime = math.floor((item.json.data.uptime+0.5)/60)
             local Temp   = domoticz.utils.round(item.json.data.temperature,1)

             local wAverage30 = domoticz.variables('CAcpm').value        -- uservariable
             wAverage30 = (29*wAverage30 + Count)/30 
             wAverage30 = tonumber(string.format("%." .. 2 .. "f", wAverage30))
                 
              domoticz.variables.CAcpm.value = tostring(wAverage30)  -- this line gives the error
                
              print (wAverage30)

	    domoticz.devices('cpmCount').updateCustomSensor(Count)
	    domoticz.devices('cpmUp').updateCustomSensor(Uptime)
	    domoticz.devices('cpmT').updateTemperature(Temp)
            domoticz.devices('cpmCount30').updateCustomSensor(wAverage30)
       end
       
User avatar
habahabahaba
Posts: 232
Joined: Saturday 18 March 2023 14:44
Target OS: Windows
Domoticz version: 2024.4
Contact:

Re: Convert LUA script into dzVents

Post by habahabahaba »

costo wrote: Monday 12 May 2025 22:43
but writing a new value in the uservariables table is erronous.

I tried -- domoticz.variables.CAcpm.value = tostring(wAverage30)
and get this error 'attempt to index a function value (field 'variables')
domoticz.variables('Heating_123_floors').set('On') - example

I think you have to learn this - https://wiki.domoticz.com/DzVents:_next ... _scripting
costo
Posts: 71
Joined: Tuesday 11 August 2015 17:35
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Convert LUA script into dzVents

Post by costo »

Hi habahabahaba,
your example brought me to the solution

yes you are right, I have to learn dzVents, but its not easy to teach an old horse a new trick.

More than 50 years ago I learned coding using punchcards.
each card was a line and had max 80 characters, so variables needed short names.
in the evening a batch of cards was sent by a modem to a mainframe and the next day I got the result or error warning.
from algol>pascal>basic to C++ and then I stopped, never had interest in java or script language.
Now I have to if i want to do nice things in domoticz

I still feel the need to keep variable names short and get dizzy if I see a script with names like ('broodroosterventilator') or (response.data.value) , than I don't see the code anymore :lol:
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest