Hello,

Thank you for looking into this.

The LOOP information are coming from the console when runnning "sudo vi 
weewx.conf".

After some researchs, I found that the maxSolarRad comes from the pyephem 
package.
For the Rainrate value, in [StdWXCalculate] / [[Calculations]] I changed 
from prefer_hardware to hardware, and now I don't have it anymore in the 
LOOP record.

For the configuration, I don't have a label_map paragraph, I use the same 
labels in mqtt topic and in weewx.

So sorry, it seems your module is working fine, and it was a wrong 
installation on my part.

However, I reproduced the problem concerning the information from a device 
splitted in different LOOP records:
$ sudo ./bin/weewxd weewx.conf
LOOP:   2019-12-13 17:55:36 CET (1576256136) dateTime: 1576256136, 
maxSolarRad: 0.0, usUnits: 1, windDir: 247.5, windGust: 5.59235462985, 
windGustDir: 247.5, windSpeed: 4.47388370388
LOOP:   2019-12-13 17:55:41 CET (1576256141) dateTime: 1576256141, 
maxSolarRad: 0.0, usUnits: 1, windBatteryStatus: 0.0
LOOP:   2019-12-13 17:55:51 CET (1576256151) dateTime: 1576256151, 
maxSolarRad: 0.0, usUnits: 1, windBatteryStatus: 0.0, windDir: 292.5, 
windGust: 2.68433022233, windGustDir: 292.5, windSpeed: 4.25018951868

The record from 17:55:41 should not be here, the information about the 
battery should have been received with the 17:55:36 information.

I have tried to add the cumulative rain management. I succeeded at least at 
breaking the debug logs. Running test for the functionality.
I hope this is only a problem of indent, could someone look at it?

-- 
You received this message because you are subscribed to the Google Groups 
"weewx-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-development/972caae5-95a2-4824-9972-20b017861a10%40googlegroups.com.
#!/usr/bin/python
#
# weewx driver that reads data from MQTT subscription
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
#
# See http://www.gnu.org/licenses/

#
# The units must be weewx.US:   (this comment need to be updated)
#   degree_F, inHg, inch, inch_per_hour, mile_per_hour
#
# To use this driver, put this file in the weewx user directory, then make
# the following changes to weewx.conf:
#
# [Station]
#     station_type = wxMesh
# [wxMesh]
#     host = localhost           # MQTT broker hostname
#     topic = weather            # topic, mqtt topics should have format "topic/label_map", ex: weather/humi
#     driver = user.wxMesh
#
# If the variables in the file have names different from those in weewx, then
# create a mapping such as this:
#
# [wxMesh]
#     ...
#     [[label_map]]
#         temp = outTemp
#         humi = outHumidity
#         in_temp = inTemp
#         in_humid = inHumidity
#
# If a rain field is provided in the file it can be interpreted as an
# incremental or cumulative value by setting the cumulative_rain config option. 
# Setting cumulative_rain = True will result in the rain field being
# interpreted as a cumulative value, omitting the cumulative_rain config option
# or setting it to True will result in the rain field being interpreted as an
# incremental value. For example:
#
# [wxMesh]
#     ...
#     cumulative_rain = True  # interpret rain as a cumulative value
#
from __future__ import with_statement
import syslog
import time
import paho.mqtt.client as mqtt
import weewx.drivers
from weeutil.weeutil import to_bool

DRIVER_NAME = 'wxMesh'
DRIVER_VERSION = "0.2"

def logmsg(dst, msg):
    syslog.syslog(dst, 'wxMesh: %s' % msg)

def logdbg(msg):
    logmsg(syslog.LOG_DEBUG, msg)

def loginf(msg):
    logmsg(syslog.LOG_INFO, msg)

def logerr(msg):
    logmsg(syslog.LOG_ERR, msg)

def _get_as_float(d, s):
    v = None
    if s in d:
        try:
            v = float(d[s])
        except ValueError, e:
            logerr("cannot read value for '%s': %s" % (s, e))
    return v

def loader(config_dict, engine):
    return wxMesh(**config_dict[DRIVER_NAME])

class wxMesh(weewx.drivers.AbstractDevice):
    """weewx driver that reads data from a file"""

    def __init__(self, **stn_dict):
        # where to find the data file
        self.host = stn_dict.get('host', 'localhost')
        # subscribe to all sub-topic of the topic define in weewx.conf 
        self.topic = stn_dict.get('topic', 'weather') + "/#"
	self.username = stn_dict.get('username', 'default_usernameXXX')
        self.password = stn_dict.get('password', 'password')
	self.clientid = stn_dict.get('client', 'weewx_mqttc')
        # how often to poll the weather data file, seconds
        self.poll_interval = float(stn_dict.get('poll_interval', 5.0))
        # mapping from variable names to weewx names
        self.label_map = stn_dict.get('label_map', {})
        # is the mapped 'rain' field to be interpreted as incremental(default)
        # or cumulative
        self.cumulative_rain = to_bool(stn_dict.get('cumulative_rain', False))
        if self.cumulative_rain:
            # initialise last_rain
            self.last_rain = None
            _msg = "rain will be interpreted as cumulative"

        loginf("host is %s" % self.host)
        loginf("topic is %s" % self.topic)
        loginf("polling interval is %s" % self.poll_interval)
        loginf(_msg)
        loginf('rain label map is %s' % self.label_map)

        self.payload = "Empty"
	self.receive_buffer = {}
        #self.payloadList = [payload]
        self.client = mqtt.Client(client_id=self.clientid, protocol=mqtt.MQTTv31)

	#self.client.on_connect = self.on_connect
	self.client.on_message = self.on_message

        self.client.username_pw_set(self.username, self.password)
	self.client.connect(self.host, 1883, 60)
	self.client.subscribe(self.topic, qos=0)

    # The callback for when a PUBLISH message is received from the server.
    def on_message(self, client, userdata, msg):
	self.payload = str(msg.payload)
	string_topic = str(msg.topic)
	key =  string_topic.split('/')[-1] 
        self.receive_buffer[key] = str(msg.payload)
### LOGDB
#        logdbg("mqtt message received %s" %string_topic)
#        logdbg("mqtt message payload %s" %self.payload)


    def closePort(self):
	self.client.loop_stop()
        self.client.disconnect()

    def genLoopPackets(self):
        self.client.loop_start()   # enable to receive ('on_message') in background
        while True:
            time.sleep(self.poll_interval) # wait for some MQTT data to be published
            data = self.receive_buffer.copy() # copy receive_buffer in data for packet building
            self.receive_buffer.clear() # clear receive_buffer to make it ready for any next incoming mqtt data
            if data:       # if data is not empty then prepare loop packet
                _packet = {'dateTime': int(time.time() + 0.5),'usUnits': weewx.METRICWX}
                logdbg("dateTime %s" % _packet["dateTime"])
                for vname in data:
                    _packet[self.label_map.get(vname, vname)] = _get_as_float(data, vname)
   	        # if there is a rain field in the packet and rain is being
        	# interpreted as cumulative then the incremental value must be
	        # calculated and substituted in the packet
        	if 'rain' in _packet and self.cumulative_rain:
                    _packet['rain'] = self.calculate_rain(_packet['rain'])


                    logdbg("packet content: %s =  %s" %(self.label_map.get(vname, vname), data[vname]))
                yield _packet
                data.clear()
#	self.client.loop_stop()

    def calculate_rain(self, newtotal):
        """Calculate the rain difference given two cumulative measurements."""

        if newtotal is not None and self.last_rain is not None:
            if newtotal >= self.last_rain:
                delta = newtotal - self.last_rain
            else:
                loginf("rain counter decrement detected: new=%s old=%s" %
                       (newtotal, self.last_rain))
                delta = None
        else:
            loginf("possible missed rain event: new=%s old=%s" %
                   (newtotal, self.last_rain))
            delta = None
        self.last_rain = newtotal
        return delta

    @property
    def hardware_name(self):
        return "wxMesh"

Reply via email to