Page 1 of 1
Reading XML from IPX800
Posted: Wednesday 05 June 2019 20:01
by laco
Hello.
I am reading xml from IPX800 http://192.168.1.125/status.xml
Code: Select all
<response>
<led0>0</led0>
<led1>0</led1>
<led2>0</led2>
<led3>0</led3>
<led4>0</led4>
<led5>0</led5>
<led6>0</led6>
<led7>0</led7>
<btn0>up</btn0>
<btn1>up</btn1>
<btn2>up</btn2>
<btn3>dn</btn3>
<an1>0</an1>
<an2>0</an2>
<time0>19:16:16</time0>
</response>
I created LUA script to read:
Code: Select all
commandArray = {}
function XML_Capture(cmd,flatten)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if flatten then
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
end
return s
end
debug = true
-- DOMOTICZ IDX
IDX1=117 --motion sensor 1
IDX2=118 --motion sensor 2
Device_IPX800 = "192.168.1.125"
if debug == true then
print("Reading values from: 'http://"..Device_IPX800.."/status.xml'")
end
-- Read the XML data from the device IPX800
XML_string=XML_Capture("curl -s 'http://"..Device_IPX800.."/status.xml'",1)
valid = string.find(XML_string, "<response>") -- check we are looking in the right place
if debug == true then
print(XML_string)
end
return commandArray
I see in the log that it writes it right.
LOG:
Code: Select all
2019-06-05 19:59:26.808 Status: LUA: Reading values from: 'http://192.168.1.125/status.xml'
2019-06-05 19:59:26.858 Status: LUA: <response> <led0>0</led0> <led1>0</led1> <led2>0</led2> <led3>0</led3> <led4>0</led4> <led5>0</led5> <led6>0</led6> <led7>0</led7> <btn0>up</btn0> <btn1>up</btn1> <btn2>up</btn2> <btn3>dn</btn3> <an1>0</an1> <an2>0</an2> <time0>19:26:51</time0> </response>
I need to write the motion sensor value to IDX1:
<btn3> dn </btn3> switch open
<btn3> up </btn3> switch closed
Can anyone help me? Well thank you.
Re: Reading XML from IPX800
Posted: Thursday 06 June 2019 9:33
by waaren
laco wrote: ↑Wednesday 05 June 2019 20:01
I am reading xml
I need to write the motion sensor value to IDX1:
<btn3> dn </btn3> switch open
<btn3> up </btn3> switch closed
Can anyone help me?
This should do it. Please feel free to ask clarification when not clear.
Code: Select all
commandArray = {}
local Device_IPX800 = '192.168.1.125'
local motionSensor1 = 'motion sensor 1' -- change to name of your motion sensor 1
local debug = false
local function XML_Capture(cmd, flatten) -- cmd required, flatten optional
local f = assert(io.popen(cmd, 'r')) -- open file for reading
local s = assert(f:read('*a')) -- read complete file into string
f:close() -- close file
if flatten then -- when flatten is not equal to false or nil then the file will be 'flattened'
s = string.gsub(s, '[\n\r]+', ' ') -- replace all (multiple) CR/LF from string s with a space
else -- action not set so defaults to converting xml to table
lines = {}
local validXML = false
for row in s:gmatch('[^\r\n]+') do -- read one line from string s into row
debug = ( debug and print(row) ) or debug -- print line when debug is set
validXML = validXML or ( row == '<response>' ) -- did we find the string that makes this xml valid ?
lines[row:match('<(%w+)>') or 'nil'] = row:match('<.->(.-)<') -- xml tag will be the key and content will be value
end
debug = ( debug and print('XML Valid? : ' .. tostring(validXML))) or debug -- print line when debug is set
lines = ( validXML and lines ) or {} -- nullify lines when no valid response
end
return lines or s -- return table or flattened string
end
debug = ( debug and print("Reading values from: 'http://" .. Device_IPX800 .. "/status.xml'") ) or debug -- print line when debug is set
-- Read the XML data from the device IPX800 into a table
-- Please note that a curl command can potentially blocks the entire domoticz event system
-- So advise is to add maxTime parm (-m 5 ) for n seconds. (or use dzVents where aSync method domoticz.openURL can be used)
local xmlTable = XML_Capture("curl -m 5 -s 'http://" .. Device_IPX800 .. "/status.xml'")
-- local xmlTable = XML_Capture('cat /usr/local/domotica/xml.in') -- test file
local action = 'On' -- default value; will also be used when xml was not valid !
if xmlTable.btn3 == 'up' then action = 'Off' end
commandArray[motionSensor1] = action
return commandArray
Re: Reading XML from IPX800
Posted: Thursday 19 September 2019 12:52
by laco
Thank you very much, it works perfectly.
Please, you can do a script to read the temperature of an1 and an2
and write it into a virtual thermometer in domoticz?
Temperature reading every 5 minutes
Rounding to 1 decimal
The formula for calculating the temperature is an1 * 0.323
Virtual temp1 = IDX59
Virtual temp2 = IDX60
The script can be lua or dzvents
well thank you
Re: Reading XML from IPX800
Posted: Thursday 19 September 2019 15:15
by laco
Everything works, but still sending off status. Creates a large log file.
- Spoiler: show
-
2019-09-19 15:14:53 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:52 Off
2019-09-19 15:14:51 Off
2019-09-19 15:14:51 Off
2019-09-19 15:14:51 Off
2019-09-19 15:14:51 Off
2019-09-19 15:14:51 Off
2019-09-19 15:14:51 Off
You will need to modify the script.
After sending the command on to send only 1x off
Re: Reading XML from IPX800
Posted: Thursday 19 September 2019 15:20
by waaren
laco wrote: ↑Thursday 19 September 2019 15:15
Everything works, but still sending off status. Creates a large log file.
It looks like you saved it as device or all type triggered event. You should save it as a time triggered event.
When I find the time I will look into this and your earlier question and convert it into a dzVents script.
Re: Reading XML from IPX800
Posted: Thursday 19 September 2019 19:58
by waaren
laco wrote: ↑Thursday 19 September 2019 12:52
Please, you can do a script to read the temperature of an1 and an2
and write it into a virtual thermometer in domoticz?
Can you try this dzVents script ?
Handles both the temperatures and the motion detector.
Code: Select all
local scriptVersion = '0.201909191600'
local scriptVar = 'IPX800_' .. scriptVersion
--[[
this dzVents script is used to collect data from IPX800
It uses a openURL call and interprets the returned XML code.
Before activating the script:
please read the GETTING STARTED section of the dzVents wiki.
]]--
return
{
on =
{
timer = { 'every 5 minutes' }, -- is this frequent enough for the motion detection part?
httpResponses = { scriptVar },
},
logging =
{
level = domoticz.LOG_DEBUG,
marker = scriptVar,
},
execute = function(dz, item)
local IPX800IP = '192.168.1.125'
local an1Temperature = dz.devices(59)
local an2Temperature = dz.devices(60)
local motionDetector = dz.devices('Pohyb fitness')
local temperatureFactor = 0.323
local function getIPX800XML()
local url = 'http://' .. IPX800IP .. '/status.xml'
dz.openURL({ url = url, callback = scriptVar })
end
local function processXML(xmlData)
local validator = '<response>'
if not(xmlData:find(validator)) then return end
local usedFields = { "btn3", "an1", "an2" }
local tupels = {}
for _, key in ipairs(usedFields) do
for tag in xmlData:gmatch('<' .. key .. '%s?[^>]->') do
local _, beginValueString = xmlData:find(tag)
local _, endValueString = xmlData:find('<', beginValueString)
local value = xmlData:sub(beginValueString + 1, endValueString - 1)
tag = tag:gsub('[<>]','')
dz.log("Value of " .. tag .. ' ==> '.. value ,dz.LOG_FORCE)
tupels[tag] = value
end
end
return tupels
end
local function updateTemperatureSensor(device, value)
if device and value then device.updateTemperature(dz.utils.round((value * temperatureFactor),1 )) end
end
local function updateMotionDetector(device, activate)
if device and activate then device.switchOn().checkFirst()
elseif device then device.switchOff().checkFirst()
end
end
local function errorReport(message)
dz.log(message, dz.LOG_ERROR)
dz.log('Received: ' .. tostring(item.data),dz.LOG_FORCE)
end
-- main
if item.isTimer or item.isDevice then
getIPX800XML()
elseif item.ok then -- statusCode == 2xx
local result = processXML(item.data)
if result then
updateMotionDetector(motionDetector, result.btn3 == 'dn' )
updateTemperatureSensor(an1Temperature, result.an1)
updateTemperatureSensor(an2Temperature, result.an2)
else
errorReport('Could not get valid XML from ' .. IPX800IP)
end
else
errorReport('Could not get (good) data from ' .. IPX800IP)
end
end
}
Re: Reading XML from IPX800
Posted: Friday 20 September 2019 13:10
by laco
Analog temperature sensors work great.
You can easily set the shooting time.
Only digital readers may need to be separately scripted to send the status only if there is an intrusion of the object.
Thank you great job.