Upload from Domoticz to Meteobridge

Moderator: leecollings

Post Reply
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Upload from Domoticz to Meteobridge

Post by Toulon7559 »

Meteobridge is a most flexibele device to act as a nodal point for collection of weatherdata and output/upload to various organisations.
Although plenty of options already included, sometimes connections missing, usually because the interface between Meteobridge and the other device not existing.

Having a collection of weathersensors not compatible with Meteobridge, but interfacing to Domoticz,
now looking for an online interface from Domoticz to Meteobridge, aiming for ‘best of 2 worlds’:
- data collection & preparation by Domoticz
- merger/integration & translation by Meteobridge for further upload.
Emulation in Domoticz of one of the 'real' weatherstations in the list seems a bit overdone.
Thinking about application of the available weatherstation-option in Meteobridge for either ‘Ecowitt protocol’ or ‘userdefined’.
'Ecowitt protocol' is popular for transfer of data for the FOSHK/Ecowitt sensors, already touching Domoticz, because RFLink Gateway is compatible for reading FOSHK/Ecowitt-sensors into Domoticz, but probably elaborate to implement for the other direction = interfacing from Domoticz, cloning/emulating FOSHK/Ecowitt-sensoroutput. [Furthermore such emulation might be conflicting if already 'real' FOSHK-sensors in the configuration]
Less elaborate or less risky, under the cover of 'userdefined', this CS-plugin is an interesting one, because it's data-package contains all elements for a weatherstation.
Interface for only one T&H-sensor in this DL-plugin with a completely different (but not easy) approach for getting the info inside Meteobridge.
The plugin to read the data from the local Luftdaten-setup is also interesting, because already reading a JSON-format and very compact.
For all 3 plugins also interesting to see the application of awk for shorthand-scripting.

The question is how to compatibly prepare&provide the required data at/from the Domoticz-side.
Any usable examples in Domoticz?
Last edited by Toulon7559 on Thursday 08 February 2024 15:48, edited 2 times in total.
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: Upload from Domoticz to Meteobridge

Post by Toulon7559 »

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?
DOM_PluginMB.zip
JSON_Files for/from Testing
(946 Bytes) Downloaded 50 times
Last edited by Toulon7559 on Thursday 15 February 2024 10:47, edited 9 times in total.
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: Upload from Domoticz to Meteobridge

Post by Toulon7559 »

Because it is not an obligation to stay with the Luftdaten-format for the JSON-file for the Meteobridge-Plugin,
the simpler solution probably might be the development of an adapted plugin for Meteobridge,
operating in conjunction with a JSON-file from Domoticz without those 'problematic' boundary-markers [ and ].
Perhaps even better to apply a dictionary which only has one key-layer,
not a level differentiation of segments with outer keys and inner keys.
With basic structure for all keys like the outer keys of the Luftdaten-dictionary.
To be continued in this thread.

Nevertheless, for other scripts and for general knowledge of Python-application the questions in the previous message are 'challenging':
who knows practical answers?
Especially resolution of the issue of global single-character replacement ‘ <> “ has value for file-manipulation.
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: Upload from Domoticz to Meteobridge

Post by Toulon7559 »

The application of Meteobridge's Luftdaten-plugin as basis for a new Domoticz_PWS-plugin stuck on aspects as mentioned in previous messages.
Their CampbellSci-plugin proved easier starting point.
The mixing of the 2 plugins resulted in even easier plugin-package.

The adapted plugin meanwhile under test in my Meteobridge, as reported in the Meteobridge-forum.

A related Python-script for the Domoticz-side is below,
- to extract required sensordata from Domoticz and
- to recompile & upload that data in a file compatible with the plugin in Meteobridge.
The script is programmed with small steps,
not combining repeating similar functions, and
with plenty of supporting lines for comments, line-numbers and printlines.
You need to tune the script to which sensors of your PWS-configuration you want to send to Meteobridge,
what webspace you want to apply for file-transfer, and to your taste.
In that perspective surely expert-users might siginificantly squeeze the size of this script without loss of functionality.

As stated in the script-header, this script is on purpose running under Python2.x, because then a proven FTP-uploadfunction could be included:
for Python3.x and/or SFTP another solution required for that section.
Spoiler: show
#!/usr/bin/python
# -*- coding = utf-8 to enable reading by simple editors -*-
# (c)2024 script compiled by Toulon7559 from various material from other scripts and forums, version 00_20240206
# On purpose running under Python 2.x, because for that environment a complete package available from reading till/incl. upload to webspace.
# ToDo = Upgrade this script for running under Python3.x
# Plenty of printlines for checking during test, which after test can be deleted, with related alignment or deletion of line numbers.
# --------------------------------------------------
# Line 008 = Description of setup
# --------------------------------------------------
# Required data for clone of Campbell Scientific data logger plugin for Meteobridge
# This script applies SI/Metric input data.
# Number indicates position in the output-string
# 1 average wind speed (m/s)
# 2 gust wind speed in last X minutes (m/s)
# 3 current wind direction (degrees north)
# 4 outdoor temperature (Celsius) # Sensor at standard height
# 5 relative outdoor humidity (%) # Sensor at standard height
# 6 windchill (Celsius) # Linked with choice for T&H-set
# 7 current rain rate (mm/h)
# 8 cumulated raintotal of today or year or since start (mm)
# 9 sealevel pressure (hPa)
# 10 uv index (uvi)
# 11 solar radiation (w/qm)
# 12 indoor temperature (Celsius)
# 13 relative indoor humidity (%)
# 14 outdoor temperature (Celsius) # Low/ grass sensor
# 15 relative outdoor humidity (%) # Low/ grass sensor
#
# example (for all-active sensors):
# 0.1,0.0,169.0,1.9,96.0,6.96,0.98,1.0,995.0,0.3,4.89,17.9,44.0,1.9,96.0
#
# This script is a 1st feasability test aimed to
# a. Read selected virtual devices as data sources in the Domoticz configuration
# Note that all Virtual Devices are assumed 'standard' devices as indicated, NOT Custom Sensors.
# b. Straightforward copy & recompile the extracted data into textstrings,
# b1. Set default values for missing sensors.
# c. Recompile the textstrings into another specific format, such as required for read-out by another system,
# in this testcase a Meteobridge-plugin.
# d. upload the compiled files to a selected webspace either on LAN or on internet, for pickup by other users.
#
# Line 041 = Usage at side of plugin
# DO NOT USE the original CampbellCsi-plugin in conjunction with the output from this script
# [because that plugin applies nc for file-transfer and expects imperial units for some inputs!]
# Usage: insert the location and name of the datafile into the Meteobridge-plugin in the 'read-section'.
# <folder>/<filename> with file <filename> accessible in webspace at location <folder>,
# compatible with info inserted in the FTP-upload-script at the end of this script.
# --------------------------------------------------
# Line 048 = PREPARATION & SETTING
# --------------------------------------------------
script_version = '00' # identifies (for test printing) your version of the script
# Imports for script-operation
import sys # required or system functions
import calendar # used for checking dates
import datetime # used for timestamps & timecheck
import time # used for timestamps & delays
from datetime import datetime, timedelta
now_cet = datetime.now()
now_utc = datetime.utcnow()
import json
import requests # requests installed as prep for Python3.x-compatibility

# Line 062 = Select the compatible urlopen-function [tbd placeholder]
try:
# For Python 3.0 and later
import urllib.request
from urllib.request import urlopen
except ImportError:
# Fall back to Python 2's urllib2
import urllib2
from urllib2 import urlopen

# Line 072 = Inventory of applicable RIDs for Virtual Devices as data sources in this configuration (examples)
# Raspberry1 RID=3891 = WS7000P1(150cm), RID=3892 = WS7000P2(010cm), RID=2745 = WS7000_Wind, RID=21 = WS7000_Rain, RID=3695 = WS7000P19
# Raspberry2 RID=18 = WS7000THB, RID=3350 = ML8511_UVI[~UVN800]
#
# Line 076 = Define configuration for the script [TUNE x and y and RID FOR YOUR CONFIGURATION!]
TH0_incl = 1; IP0 = '192.168.x.y:8080' ; RID0 = '18' # Indoor T&H-set
TH1_incl = 1; IP1 = '192.168.x.y:8080' ; RID1 = '3891' # Outdoor, Standard T&H-set, mandatory for calc of WindChill
TH2_incl = 1; IP2 = '192.168.x.y:8080' ; RID2 = '3892' # Outdoor, Grass T&H-set
Wind_incl = 1; IP3 = '192.168.x.y:8080' ; RID3 = '2745' # Mandatory for calc of WindChill
Rain_incl = 1; IP4 = '192.168.x.y:8080' ; RID4 = '21'
UVI_incl = 1; IP5 = '192.168.x.y:8080' ; RID5 = '3350'
SolarRad_incl = 1; IP6 = '192.168.x.y:8080' ; RID6 = '3695'
Baro_incl = 1; IP7 = '192.168.x.y:8080' ; RID7 = '18'; Baro_Rel = 1; Altitude = 15 # sensor altitude in meters AboveSeaLevel
Invalid = '' # result => no contents in output-string for this sensor
print
print ('Start of script for readout of RIDs & recompilation, version ',script_version)
# --------------------------------------------------
# Line 089 = SETUP of support functions
# --------------------------------------------------
# By default, not all required, and some duplicate
import sys # required or system functions
import calendar # used for checking dates
import datetime # used for timestamps & timecheck
import time # used for timestamps & delays
from datetime import datetime, timedelta
now_cet = datetime.now()
now_utc = datetime.utcnow()

# Line 100 = Definition of local support functions
# Line 101 = Translation of UTC to epoch, and UTC or Epoch to LocalTime

# Line 103 = utc_dt is a datetime object in UTC time # applied
def utc_to_epoch(utc_dt):
epoch = calendar.timegm(utc_dt.utctimetuple())
return epoch

# Line 108 = utc_dt is a datetime object in UTC time # spare
def utc_to_local(utc_dt):
# get integer timestamp to avoid precision lost
timestamp = calendar.timegm(utc_dt.timetuple())
local_dt = datetime.fromtimestamp(timestamp)
assert utc_dt.resolution >= timedelta(microseconds=1)
return local_dt.replace(microsecond=utc_dt.microsecond)

# Line 116 = utc_epoch is an epoch object in UTC time # spare
def epoch_to_local1(utc_epoch):
local_datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(utc_epoch))
return local_datetime

# Line 121 = utc_epoch is an epoch object in UTC time # spare
def epoch_to_local2(utc_epoch):
local_filedate = time.strftime('%d-%m-%Y', time.localtime(utc_epoch))
return local_filedate

# Line 126 = utc_epoch is an epoch object in UTC time # spare
def epoch_to_local3(utc_epoch):
local_filetime = time.strftime('%H:%M', time.localtime(utc_epoch))
return local_filetime

# --------------------------------------------------
# Line 132 = Read RID18 = Indoor T&H0 WTGR800
# Extract data
# --------------------------------------------------
url = ('http://' + IP0 + '/json.htm?type=devices&rid=' + RID0)
page = urlopen(url)
content_rid = page.read()
print
obj_test0 = json.loads(content_rid)
print('Layout obj_test0')
print
print(obj_test0)
print
HUM0 = float(obj_test0['result'][0]['Humidity']);print(HUM0) # %
TEMP0 = float(obj_test0['result'][0]['Temp']);print(TEMP0) # C
DEW0 = float(obj_test0['result'][0]['DewPoint']);print(DEW0) # C

# --------------------------------------------------
# Line 149 = Read T&H1 WTGR800 @ +1.5m
# Extract data
# --------------------------------------------------
url = ('http://'+ IP1 + '/json.htm?type=devices&rid='+ RID1)
page = urlopen(url)
content_rid = page.read()
print(content_rid)
print
obj_test1 = json.loads(content_rid)
print('Layout obj_test1')
print
print(obj_test1)
print
HUM1 = round(float(obj_test1['result'][0]['Humidity']), 2);print(HUM1)
TEMP1 = round(float(obj_test1['result'][0]['Temp']), 2);print(TEMP1)
DEW1 = round(float(obj_test1['result'][0]['DewPoint']), 2);print(DEW1) # spare
TIM1_epoch = obj_test1['ActTime'];print(TIM1_epoch) # timestamp expressed in epoch

# --------------------------------------------------
# Line 168 = Read T&H2 WTGR800 @ +0.1m
# Extract data
# --------------------------------------------------
url = ('http://' + IP2 + '/json.htm?type=devices&rid=' + RID2)
page = urlopen(url)
content_rid = page.read()
print
obj_test2 = json.loads(content_rid)
print('Layout obj_test2')
print
print(obj_test2)
print
HUM2 = round(float(obj_test2['result'][0]['Humidity']), 2);print(HUM2)
TEMP2 = round(float(obj_test2['result'][0]['Temp']), 2);print(TEMP2)
DEW2 = round(float(obj_test2['result'][0]['DewPoint']), 2);print(DEW2) # spare
TIM2_epoch = obj_test1['ActTime'];print(TIM2_epoch) # timestamp expressed in epoch

# --------------------------------------------------
# Line 186 = Read Wind
# Extract data and calculate windchill
# --------------------------------------------------
url = ('http://' + IP3 + '/json.htm?type=devices&rid=' + RID3)
page = urlopen(url)
content_rid = page.read()
print(content_rid)
print
obj_test3 = json.loads(content_rid)
print('Layout obj_test3')
print
print(obj_test3)
print
DIRDEG = round(float(obj_test3['result'][0]['Direction']), 2);print(DIRDEG) # Degrees rel. to North
GUST = round(float(obj_test3['result'][0]['Gust']), 2);print(GUST) # m/s
SPEED = round(float(obj_test3['result'][0]['Speed']), 2);print(SPEED) # m/s

# Line 203 = Calculate WindChill
print('Calculation of WindChill')
# Formula & script found at https://www.tutorialspoint.com/calculat ... on-program#
import math
# Linking to extracted data:
v = SPEED # => Wind-sensor must be included!
t = TEMP1 # => T&H1-sensor must be included!
# For manual testing of the calculation uncomment the next 2 lines:
# v = float(input("Input wind speed in kilometers/hour: "))
# t = float(input("Input air temperature in degrees Celsius: "))
wci = 13.12 + 0.6215*t - 11.37*math.pow(v, 0.16) + 0.3965*t*math.pow(v, 0.16)
# print("The wind chill index is", int(round(wci, 0)))
CHILL = round(wci, 2) # Celsius
print('WindChillC = ',CHILL)

# --------------------------------------------------
# Line 219 = Read Rain
# Extract data
# --------------------------------------------------
url = ('http://' + IP4 + '/json.htm?type=devices&rid=' + RID4)
page = urlopen(url)
content_rid = page.read()
print
obj_test4 = json.loads(content_rid)
print('Layout obj_test4')
print
print(obj_test4)
print
RAINTODAY = round(float(obj_test4['result'][0]['Rain']), 2);print(RAINTODAY) # mm, RainToday
RAINRATE = round(float(obj_test4['result'][0]['RainRate']), 2);print(RAINRATE) # mm/hr
RAINSUMS = (obj_test4['result'][0]['Data']);print(RAINSUMS) # mm, 2 values in string
# Extract values from string
end1 = RAINSUMS.find(';')
RAINYEAR = RAINSUMS[:(end1)]; print(RAINYEAR) # extract value1 from start till , / mm(RainYear?)
RAINTOTAL = RAINSUMS[(end1+1):]; print(RAINTOTAL) # extract value2 from , to end / mm(RainTotal?)

# --------------------------------------------------
# Line 240 = Read UVI
# Extract data
# --------------------------------------------------
url = ('http://' + IP5 + '/json.htm?type=devices&rid=' + RID5)
page = urlopen(url)
content_rid = page.read()
print
obj_test5 = json.loads(content_rid)
print('Layout obj_test5')
print
print(obj_test5)
print
UVI = round(float(obj_test5['result'][0]['UVI']), 2);print(UVI) # UVI

# --------------------------------------------------
# Line 255 = Read Light/SolarRad
# Extract data and recalculate Lux-value to W/m²
# --------------------------------------------------
url = ('http://' + IP6 + '/json.htm?type=devices&rid=' + RID6)
page = urlopen(url)
content_rid = page.read()
print(content_rid)
print
obj_test6 = json.loads(content_rid)
print('Layout obj_test6')
print
print(obj_test6)
print
LUX = (obj_test6['result'][0]['Data']);print(LUX) # Lux
# Extract value from string and convert to W/m^2, 1 Lux = 0,0079 W/m²
LUX = LUX.strip(" Lux"); LUX = float(LUX)
SOLRAD = round((LUX * 0.0079), 2);print(SOLRAD,' W/m²') # W/m²

# --------------------------------------------------
# Line 274 = Read Baro
# Extract data
# --------------------------------------------------
url = ('http://' + IP7 + '/json.htm?type=devices&rid=' + RID7)
page = urlopen(url)
content_rid = page.read()
print
obj_test7 = json.loads(content_rid)
print('Layout obj_test7')
print
print(obj_test7)
print
PRESS = round(float(obj_test7['result'][0]['Barometer']), 2);print(PRESS) # hPa
if Baro_Rel == 1: # Check on pressure relative or pressure absolute
PRESS_MSL = PRESS # assuming that Virtual Device reports rel. pressure as PRESS
else:
# Baro_Rel = Baro_Abs + (Altitude/8.5) # Absolute station-pressure, corrected for altitude_ASL of sensor
PRESS_MSL = PRESS + (Altitude/8.5)

# --------------------------------------------------
# Line 294 = Compile txt-file from the Read-outs
# --------------------------------------------------
# Line 296 = Determine staleness of data
System_epoch = utc_to_epoch(now_utc); print(System_epoch) # System_time expressed in epoch
AGE1 = round((System_epoch - TIM1_epoch), 1); print('Age = ',AGE1) # data staleness

# Line 300 = Conversion to valued input-strings

str00 = ','

if TH1_incl == 1: # Outdoor TH1
str04 = str(TEMP1)
str05 = str(HUM1)
else:
str04 = Invalid
str05 = Invalid

if TH2_incl == 1: # Outdoor TH2
str14 = str(TEMP2)
str15 = str(HUM2)
str16 = ','
else:
str14 = Invalid
str15 = Invalid
str16 = ''

if Wind_incl ==1:
str01 = str(SPEED)
str02 = str(GUST)
str03 = str(DIRDEG)
str06 = str(CHILL)
else:
str01 = Invalid
str02 = Invalid
str03 = Invalid
str06 = Invalid

if Baro_incl == 1:
str09 = str(PRESS_MSL)
else:
str09 = Invalid

if Rain_incl == 1:
str07 = str(RAINRATE)
str08 = str(RAINTODAY)
else:
str07 = Invalid
str08 = Invalid

if SolarRad_incl == 1:
str11 = str(SOLRAD)
else:
str11 = Invalid

if UVI_incl == 1:
str10 = str(UVI)
else:
str10 = Invalid

if TH0_incl ==1: # Indoor TH0
str12 = str(TEMP0)
str13 = str(HUM0)
else:
str12 = Invalid
str13 = Invalid

str20 = '\n' # Termination of string

# --------------------------------------------------
# Line 363 = Generate outputfile
# --------------------------------------------------
# Check staleness of data
if (AGE1 < 120) and (AGE1 > -120): # allowed offset is 2 minutes
# Open output-file for write&read
f = open("/home/pi/MB_WS7000PWS.txt", "w+")

# Complation of collection of strings for file
L = [str01, str00, str02, str00, str03, str00, str04, str00, str05, str00, str06, str00, str07, str00, str08, str00, str09, str00, str10, str00, str11, str00, str12, str00, str13, str16, str14, str16, str15, str20]

# Writing collected, multiple strings at 1 command
f.writelines(L)

# Closing file
f.close()

# Check the output file after the writing:
f = open("/home/pi/MB_WS7000PWS.txt", "r")
print(f.read())
f.close()

print ('End of Compilation')
# --------------------------------------------------
# End of making JSON & XML-file from WS7000Set Read-out
# --------------------------------------------------
# --------------------------------------------------
# Line 390 = Function for FTP_UPLOAD to Server
# --------------------------------------------------
# Imports for script-operation
import ftplib
import os
# Definition of Upload_function
def upload(ftp, file):
ext = os.path.splitext(file)[1]
# if ext in (".txt", ".htm", ".html"):
# ftp.storlines("STOR " + file, open(file))
# else:
ftp.storbinary("STOR " + file, open(file, "rb"), 1024)

# --------------------------------------------------
# Line 404 = Actual FTP-Login & -Upload
# --------------------------------------------------
ftp = ftplib.FTP("<your_FTP_provider>")
ftp.login("<your_FTP_username>", "<your_FTP_password>")
# set path to desired destination directory
ftp.cwd('<folder>')
# set path to source directory
os.chdir("/home/pi") # assuming running a standard setup of Domoticz
# upload of output-files
upload(ftp, "<file-name>")
# reset path for destination directory
ftp.cwd('/')
print
print ('End of MB_Upload')
print
print ('End of script, version ',script_version)
print
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 0 guests