The simplest way to get hold of data from a Virtual Device in Domoticz is to call JSON-output per device by
Code: Select all
http://<ip-adress-of-raspberry>:8080/json.htm?type=devices&rid=<device-number>
and then (for each desired device) have the MB-plugin extracting required info from the presented, big JSON-file per Virtual Device.
However, easier for an MB_plugin if Domoticz collects the info and generates a compact JSON-file in a layout (nearly) compatible with an adapted, existing MB_plugin.
Have been 'fiddling' with the MB_plugin for reading a local Luftdaten-setup with SDS011.
Made a static JSON-file mimicking such local Luftdaten_JSON-file, but then with contents as from 2 Virtual Devices for Temp&Humidity:
see file MB_WS7000P12_2TH.json in the zip-file.
Tested with success, means that static basis is OK.
Making a dynamic version of that JSON-file is different story.
Use Python-scripting for that exercise.
Reading the Vitual Devices is not a big deal, as well as extraction of selected values.
Next step is re-compilation towards a JSON-file for the MB-plugin with dynamically updated values.
The script-segment below shows the scriptlines being tested.
2 Approaches included for the re-compilation:
-
Approach1 in lines 292 till 302 applies a dictionary as starting-point to generate a 'Luftdaten-like' JSON-file,
and at same time also an equivalent XML-file (for any other application)
-
Approach2 in lines 302 till 308 is simpler, more brute force, string-generation towards file-generation
- Spoiler: show
- # --------------------------------------------------
# Line 269 = Compile specific datafile as data source for Meteobridge-Plugin
# --------------------------------------------------
# This datafile in structure mimicks a datafile as coming from a Luftdaten-setup:
# tuned layout is implemented by means of the layout of the dictionary.
import json
import dicttoxml
dattim = datetime.now().strftime('%Y%m%d %H:%M')
time = datetime.now().strftime('%H:%M:%S')
utcdate = datetime.utcnow().strftime('%d%m%Y')
utctime = datetime.utcnow().strftime('%H:%M:%S')
System_epoch = utc_to_epoch(now_utc); print(System_epoch) # System epoch
AGE3 = round((System_epoch - (TIM1_epoch + TIM2_epoch)/2), 0); print (AGE3) # data staleness
# Line 281 = Setup of default dictionary [see remark in previous, equivalent section]
MB_WS7000P12_dict1 = {"utcdate":"30-01-2024","time":"22:12:51","age":"11","timestamp":"22:12:51","sensordatavalues":[{"value_type":"humid150","value":"91.00"},{"value_type":"temp150","value":"6.50"},{"value_type":"dew150","value":"6.50"},{"value_type":"humid010","value":"91.00"},{"value_type":"temp010","value":"6.50"},{"value_type":"dew010","value":"6.50"}]}
# Line 284 = Link values of dictionary to dynamic values in script
MB_WS7000P12_dict1["utcdate"] = utcdate
MB_WS7000P12_dict1["time"] = time
MB_WS7000P12_dict1["age"] = AGE3
MB_WS7000P12_dict1["timestamp"] = TIMSTMP2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"temp150","value"] = TEMP1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"humid150","value"] = HUM1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"dew150","value"] = DEW1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"temp010","value"] = TEMP2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"humid010","value"] = HUM2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"dew010","value"] = DEW2
# Line 292 = Make JSON-file
with open('MB_WS7000P12_test1.json', 'w') as outfile:
json.dump(MB_WS7000P12_dict1, outfile)
# Line 295 = Convert the updated dictionary to XML-file & print
# MB_WS7000P12_xml = dicttoxml.dicttoxml(MB_WS7000P12_dict1, attr_type=False)
# print(MB_WS7000P12_xml)
# xml_output = open("MB_WS7000P12_status.xml",'w')
# xml_output.write(str(MB_WS7000P12_xml))
# xml_output.close()
# Line 302 = Alternative method to make input-string and compilation
Compilation = open('MB_WS7000P12_test2.json','w') # output of selected values to file
Compilation.write("{'utcdate':'" + str(utcdate) + "','utctime':'" + str(utctime) + "','age':'" + str(AGE3) + "','timestamp':'" + str(TIMSTMP1) + "','sensordatavalues':[{'value_type':'humid150','value':'" + str(HUM1) + "'},{'value_type':'temp150','value':'" + str(TEMP1) + "'},{'value_type':'dew150','value':'" + str(DEW1) + "'},{'value_type':'humid010','value':'" + str(HUM2) + "'},{'value_type':'temp010','value':'" + str(TEMP2) + "'},{'value_type':'dew010','value':'" + str(DEW2) + "'}]}\n")
Compilation.close()
# Line 307 = Global replace character ' by character "
# global_replace (MB_WS7000P12_test2.json, MB_WS7000P12_output2.json,''','"')
Both approaches have a show-stopper.
Code: Select all
# --------------------------------------------------
# Line 269 = Compile specific datafile as data source for Meteobridge-Plugin
# --------------------------------------------------
# This datafile in structure mimicks a datafile as coming from a Luftdaten-setup:
# tuned layout is implemented by means of the layout of the dictionary.
import json
import dicttoxml
dattim = datetime.now().strftime('%Y%m%d %H:%M')
time = datetime.now().strftime('%H:%M:%S')
utcdate = datetime.utcnow().strftime('%d%m%Y')
utctime = datetime.utcnow().strftime('%H:%M:%S')
System_epoch = utc_to_epoch(now_utc); print(System_epoch) # System epoch
AGE3 = round((System_epoch - (TIM1_epoch + TIM2_epoch)/2), 0); print (AGE3) # data staleness
# Line 281 = Setup of default dictionary [see remark in previous, equivalent section]
MB_WS7000P12_dict1 = {"utcdate":"30-01-2024","time":"22:12:51","age":"11","timestamp":"22:12:51","sensordatavalues":[{"value_type":"humid150","value":"91.00"},{"value_type":"temp150","value":"6.50"},{"value_type":"dew150","value":"6.50"},{"value_type":"humid010","value":"91.00"},{"value_type":"temp010","value":"6.50"},{"value_type":"dew010","value":"6.50"}]}
# Line 284 = Link values of dictionary to values in script
MB_WS7000P12_dict1["utcdate"] = utcdate
MB_WS7000P12_dict1["time"] = time
MB_WS7000P12_dict1["age"] = AGE3
MB_WS7000P12_dict1["timestamp"] = TIMSTMP2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"temp150","value"] = TEMP1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"humid150","value"] = HUM1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"dew150","value"] = DEW1
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"temp010","value"] = TEMP2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"humid010","value"] = HUM2
# MB_WS7000P12_dict1["sensordatavalues"]["value_type":"dew010","value"] = DEW2
# Line 292 = Make JSON-file
with open('MB_WS7000P12_test1.json', 'w') as outfile:
json.dump(MB_WS7000P12_dict1, outfile)
# Line 295 = Convert the updated dictionary to XML-file & print
MB_WS7000P12_xml = dicttoxml.dicttoxml(MB_WS7000P12_dict1, attr_type=False)
print(MB_WS7000P12_xml)
xml_output = open("MB_WS7000P12_status.xml",'w')
xml_output.write(str(MB_WS7000P12_xml))
xml_output.close()
Approach1 is OK for dynamic update of values for the outer keys of the nested dictionary, but the script fails when the values must be updated for the inner keys.
If commented like shown, the script runs without error report for this segment: see file MB_WS7000P12_test1.json in the zip-file.
However useless, because no update of values for the inner keys, which unfortunately contain the sensor-data.
The 'problem' is handling of the boundary-markers [ and ] around the section with inner keys.
Tried several approaches as found by Googling for update of value-strings for inner keys,
but apparently yet missing the appropriate implementation in lines 289 ~291
Also tried 'split in 2 segments for outer keys and inner keys' & 'update of values'& 'rebuild' of the dictionary, for rebuild using mapping like this and comparable
description:
update of the split segments is OK, but subsequent rebuild is failing, again for handling of those boundary-markers [ and ].
Code: Select all
Line 302 = Alternative method to make input-string and compilation
Compilation = open('MB_WS7000P12_test2.json','w') # output of selected values to file
Compilation.write("{'utcdate':'" + str(utcdate) + "','utctime':'" + str(utctime) + "','age':'" + str(AGE3) + "','timestamp':'" + str(TIMSTMP1) + "','sensordatavalues':[{'value_type':'humid150','value':'" + str(HUM1) + "'},{'value_type':'temp150','value':'" + str(TEMP1) + "'},{'value_type':'dew150','value':'" + str(DEW1) + "'},{'value_type':'humid010','value':'" + str(HUM2) + "'},{'value_type':'temp010','value':'" + str(TEMP2) + "'},{'value_type':'dew010','value':'" + str(DEW2) + "'}]}\n")
Compilation.close()
# Line 307 = Global replace character ' by character "
# global_replace (MB_WS7000P12_test2.json, MB_WS7000P12_output2.json,''','"')
Approach2 is so far OK that it generates a JSON-file with correctly updated values in the whole file, but with ' as delimiters:
see file MB_WS7000P12_test2.json in the zip-file.
However, that is not compatible with the MB-plugin under test.
Changing the MB-plugin to deal with ' instead of " as delimiters not yet successful.
Neither success to modify the scripting for JSON-file generation in this script to get " as delimiters.
Tried various approaches for global replace in a file, but did not find a working function as solution in line 308.
Various functions OK for a replace of
string with letter(s) and/or number(s),
but
not working for replace of
only single character ' to be changed into single character ", due to problems with correct use of quotes in the definitions.
Because each character has an ASCII-number, have also looked for a replace-function applying that charateristic, but not yet with positive result.
Question:
somebody knowing a working solution for completion of one or for both approaches?