Re: Reading XML with LUA?
Posted: Sunday 23 December 2018 12:39
Another challenge.
Found a URL-string to directly read an XML-file from my SAJ-inverter:
When the inverter is operational, the resulting xml-file looks like
Obviously tried to tune the script version 04 from the previous message, but get a persistent error on line 29 for 'attempt to perform arithmetic on nil value': apparently a scriptline further down in the script (somewhere at/after line 60 etc.?) makes a function-call, but with a faulty inputvalue for the string-search.
Somebody seeing what's wrong in the script-version tuned to the example xml-file?
Found a URL-string to directly read an XML-file from my SAJ-inverter:
Code: Select all
http://<IP-address>/real_time_data.xml
Code: Select all
<real_time_data><state>Normal</state><v-grid>228.8</v-grid><i-grid>0.25</i-grid><f-grid>49.98</f-grid><p-ac>35</p-ac><temp>20.4</temp><e-today>0.0</e-today><t-today>1.5</t-today><e-total>4576.2</e-total><CO2>4562.47</CO2><t-total>14437.1</t-total><v-pv1>234.9</v-pv1><i-pv1>0.15</i-pv1><v-pv2>-</v-pv2><i-pv2>-</i-pv2><v-bus>361.2</v-bus></real_time_data>
Somebody seeing what's wrong in the script-version tuned to the example xml-file?
Code: Select all
------------------------------------------------------------------------------
-- Version SAJ/00 20181223
--
-- Domoticz lua script to convert XML output directly read from SAJ_inverter
-- Reads the status based on the unique IP of the Inverter and passes it
-- to virtual sensor(s) in Domoticz
--
------------------------------------------------------------------------------
-- Source-script from Domoticz-forum, adapted by Toulon7559 (c)2018
------------------------------------------------------------------------------
-- Line 11: Start of Script
commandArray = {}
-- Line 13: Definition of XML Capture
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
-- Line 25: Definition of XML dissect
function GetValueFromXML(XMLvalue)
-- Extract the start/end-positions of the values within the substrings
local XMLvalueLength=string.len(XMLvalue)+2
local XMLvalueStartPos=string.find(XML_string,"<" .. XMLvalue .. ">")+XMLvalueLength
local XMLvalueEndPos=string.find(XML_string,"</" .. XMLvalue .. ">")
-- Get the value substring and convert it to a number
local ReturnValue=tonumber(string.sub(XML_string,XMLvalueStartPos,XMLvalueEndPos-1))
print(XMLvalue .. "=" .. ReturnValue)
return ReturnValue
end
-- Line 37: Set debug to true to print to log file.
debug = true
-- Line 40: Define the idx of your virtual sensors - i.e. what you have called your sensors and their IDX numbers
PE_IDX = 446
-- VPV_IDX =
-- IAC_IDX =
-- Temp_IDX =
-- Hours_IDX =
-- Line 48: Define your SAJ Inverter device IP@
Device_IP = "192.168.0.109"
if debug == true then
print("Reading values from: 'http://"..Device_IP.."/real_time_data.xml'")
end
-- Line 56: Read the XML data from the device
XML_string=XML_Capture("curl -s 'http://"..Device_IP.."/real_time_data.xml'",1)
valid = string.find(XML_string, "<real_time_data>") -- check we are looking in the right place
if debug == true then
print(XML_string)
end
if valid == nil then
print ("Bad XML status read - info NOT updated")
else
-- Line 70: Choose in the XML_string the info-fields (substrings) based on their labels
-- Extract the values from the substrings and (if required) scale for upload to Domoticz
-- Line 73: read AC-power string
power_actual = GetValueFromXML("p-ac")
-- Line 76: read temperature string
temp = GetValueFromXML("temp")
-- Line 79: read PV-voltage string
vpv1 = GetValueFromXML("v-pv1")
-- Line 82: read PV-current string
ipv1 = GetValueFromXML("i-pv1")
-- Line 85: read day-energy string
energy_day= GetValueFromXML("e-today") * 1000 -- correction for energy in Wh as required in Domoticz
print("energy_day=" .. energy_day)
-- Line 89: read life-energy string
energy_life= GetValueFromXML("e-total") * 1000 -- correction for energy in Wh as required in Domoticz
print("energy_life=" .. energy_life)
-- Line 93: read hours_total string
hours_total = GetValueFromXML("t-total")
-- Line 96: Upload Power & Energy to Virtual Device at Domoticz
commandArray[1] = {['UpdateDevice'] = PE_IDX.."|0|"..power_actual..";"..energy_life} -- send updated values to Domoticz
if debug == true then
print("power/energy returned = ".."'"..power_actual.."/"..energy_life.."'")
end
end
return commandArray