Just one question please :-).  Suppose the read of the arduino could 
possibly take a relatively long time, and you want to have a timeout after 
which it gives up and saves None/NULL for the indoor data.  

What is the max timeout that would be reasonable relative to the archive 
interval ? What happens if the delay goes past the end of the main archive 
interval the event you are handling was in?

I think what is happening is I usually get very fast reads from the arduino 
but once in a while I get a really slow one.       Could be something 
independent like me reading the database while weewx is trying to write it?
On Wednesday, April 26, 2023 at 11:24:36 PM UTC-7 gjr80 wrote:

> Way more complex than I think is needed. I would see you using the SDR 
> driver as the your driver and nothing else. The example cited in the 
> Customisation Guide does augment archive records rather than loop packets, 
> in your case I would expect you are better served by augmenting loop 
> packets. You don't necessarily need to augment every loop packet (if your 
> loop packets are coming in every 7 seconds from SDR) but you need to make 
> sure you get a good few in each archive period. You should have no need to 
> deal with queues or accumulators in your service, the queue is a hangover 
> of the threaded SDR driver and the WeeWX engine should handle everything to 
> do with accumulators. At then end of the day you want to do two things (1) 
> feed WeeWX with a loop packet stream - the SDR driver does that and (2) 
> augment loop packets with Arduino data - your service does that. If you do 
> these two things WeeWX will take care of generating archive records, 
> reports etc.
>
> For the Arduino, can't you just read the Arduino data direct from the 
> serial port and decode/parse/process it in your service? (there seems to be 
> plenty of examples around the traps on this).
>
> The sort of service I had in mind is something like (untested of course):
>
> import weewx
> import weewx.units
>
> class ArduinoService(weewx.engine.StdService):
>     """Data service to augment loop packets with data from an Arduino.
>     
>     We will augment loop packets with obs obtained from the Arduino. The 
> WeeWX 
>     engine will take care of accumulating this data and generating archive 
>     records.
>     """
>
>     def __init__(self, engine, config_dict):
>
>         # initialisie my parent class
>         super(ArduinoService, self).__init__(engine, config_dict)
>
>         # include whatever initialisation you need to speak to the Arduino
>         < some python code to initialise any properties etc>
>         # we will augment loop packets so bind ourself to any new loop 
> packet 
>         # events
>         self.bind(weewx.NEW_LOOP_PACKET, self.new_loop_packet)
>
>     def new_loop_packet(self, event):
>         """Augment a loop packet with data obtained from the Arduino."""
>
>         # obtain a dict of data from the Arduino
>         _ard_data_dict = self.get_arduino_data()
>         
>         # do we have any data
>         if _ard_data_dict is not None:
>             # convert the Arduino data to the same unit system as used in 
> the 
>             # loop packet, first obtain a suitable Converter
>             converter = 
> weewx.units.StdUnitConverters[event.packet['usUnits']]
>             # now convert the Arduino data to the same unit system as used 
> in 
>             # the loop packet
>             _conv_data = converter.convertDict(_ard_data_dict)
>             # and finally update the loop packet with our converted data
>             event.packet.update(_conv_data)
>
>     def get_arduino_data():
>         """Get a data dict from the Arduino.
>         
>         Obtain any data from the Arduino, parse the data and return as a 
> dict 
>         using a known unit system. If no data could be obtained return 
> None.
>         """
>
>         # some code to obtain the data from the Arduino, this code needs 
> to be 
>         # carefully constructed to not block
>         < python code to read data from the Arduino>
>
>         if <we have Arduino data>:
>             # create an empty dict with a pre-populated field usUnits to 
> hold 
>             # our parsed Arduino data. The usUnits value is arbitrary, but 
> must 
>             # be one of weewx.US (1), weewx.METRIC (16) or weewx.METRICWX 
> (17). 
>             # Choose a conventient value, eg if the Arduino provides data 
> in 
>             # metric use weewx.METRIC (16), if US customary use weewx.US, 
> if a 
>             # mix of both then pick one and we will need to do some manual 
>             # conversion for the odd fields. In this case we will use
>             # weewx.METRIC
>             _data_dict = {'usunits': weewx.METRIC}
>
>             # populate the dict, assuming here the Arduino is providing 
> WeeWX 
>             # fields inTemp, inHumidity and barometer (could be 'pressure' 
> not 
>             # 'barometer')
>             _data_dict['inTemp'] = <some code to provide inside 
> temperature in degree C>
>             _data_dict['inHumidity'] = <some code to provide inside 
> humidity in percent>
>             _data_dict['barometer'] = <some code to provide barometer in 
> hPa>
>             # we have our data dict, now return it
>             return _data_dict
>         # we could not get any data from the Arduino so return None
>         return None
>
> This is fairly bare bones and you might want to put in a few pieces of 
> code to provide log output when debug = 1 (or 2 or 3) but hopefully you get 
> the idea
>
> Gary
> On Thursday, 27 April 2023 at 15:08:42 UTC+10 william...@att.net wrote:
>
>> here is my service.  In this version I took your advice and decided to 
>> use the weewx-sdr driver completely unmodified and put all my stuff in a 
>> service.  Sorry the weewx-sdr driver (the original, not my version) reads 
>> its input from AsyncReader (not my modification).  That uses a thread.  
>> That's what I was referring to.  But since I already had my (slightly 
>> modified) version of AsyncReader from before I spoke to you, I reused it in 
>> the service (see the attachment).  It has a queue.  It stores lines of 
>> input from the arduino over usb and discards any which are not json.  This 
>> is completely separate from the weewx-sdr and its AsyncReader.  Plus this 
>> AsyncReader can also be set up as a writer which enables me to have the 
>> option of a simple time server on the raspberry pi to set the RTC on the 
>> arduino if needed.  
>>
>> Anyway I could always get rid of the AsyncReader and just use 
>> serial.readline().
>>
>> Perhaps the example in the weewx customization guide is for a one-shot 
>> read of the indoors sensors.  Instead I made it loop over the lines of 
>> input in the queue and use an accumulator to average them.
>>
>> The callback for NEW_ARCHIVE_RECORD for my service would (I think) be 
>> called before StdArchive.new_archive_record().  My service only has access 
>> to the event and event.record.  Does it also have access to 
>> StdArchive.old_accumulator ?
>> In StdArchive.new_archive_record(event)   it gets the event which was 
>> modified by my service so the record includes my data.
>>
>> *So my question is* what about old_accumulator in 
>> StdArchive.new_archive_record() ?  Is it strictly optional ?  That 
>> accumulator only has the outside data not the data added by my 
>> new_archive_record() callback.
>> Of course my data is already averaged.  
>> In StdArchive.new_archive_record() the event.record has more observation 
>> types than the old_accumulator.  Does this pose a problem ?
>>
>> what do you mean by augmenting?    does this involve choosing 
>> self.record_generation = hardware ?
>> On Wednesday, April 26, 2023 at 6:12:50 PM UTC-7 gjr80 wrote:
>>
>>> Yes, that section covers it fairly well. The two main things to watch 
>>> are not delaying the main WeeWX engine loop and ensuring the data you add 
>>> to the loop packet follows the unit system used in the loop packet. 
>>> Delaying the main loop is often associated with accessing data via the 
>>> internet or some other network. A common approach is to develop the data 
>>> service without using its own thread, this makes debugging much easier. If 
>>> delay is an issue you can move the service to its own thread later. Unit 
>>> consistency is achieved by checking the usUnits field in the loop 
>>> packet and then converting your service' data to the correct units. This is 
>>> important for obs whose units that vary across unit systems (eg 
>>> temperature) but not an issue if the same unit is used across all unit 
>>> systems (eg wind direction). A robust, well written data service will not 
>>> assume the loop packet always uses the same unit system.
>>>
>>> Gary
>>>
>>> On Thursday, 27 April 2023 at 01:24:52 UTC+10 william...@att.net wrote:
>>>
>>>> Thank you I expect you are referring to the Customization guide 
>>>> "Customizing the WeeWX service engine; Adding a second data source"; I 
>>>> will 
>>>> try doing it that way; Thanks again;
>>>>
>>>> On Tuesday, April 25, 2023 at 10:16:18 PM UTC-7 gjr80 wrote:
>>>>
>>>>> I'm not sure if you are providing a running commentary or seeking 
>>>>> help. If the latter then I have no idea where to start. Personally, I 
>>>>> think 
>>>>> your architecture is way too complex; you appear to be running a highly 
>>>>> modified driver that seeks to amalgamate data from two sources. I imagine 
>>>>> you will strike all sorts of corner cases depending on what arrives when. 
>>>>> I 
>>>>> would also question the utility of reading indoor obs every seven 
>>>>> seconds, 
>>>>> seems way too frequent to me. All told I doubt you are going to find too 
>>>>> many folks here to help.
>>>>>
>>>>> Why not run a standard sdr driver to feed WeeWX with loop packets from 
>>>>> the Atlas with a simple, non-threaded data service bound to the new loop 
>>>>> packet arrival to read the 'indoor data' (I assume this is pressure, 
>>>>> temperature and humidity) and augment the loop packet. Far more modular 
>>>>> and 
>>>>> easier to test/develop (and get help), you will be running a standard sdr 
>>>>> driver, and since you are already getting your hands dirty modifying the 
>>>>> sdr driver, writing a small data service to handle the Arduino input 
>>>>> should 
>>>>> be a walk in the park. If the Arduino is serially connected to the RPi 
>>>>> you 
>>>>> should not have great latency in accessing data, so a suitably short 
>>>>> timeout on the serial reads should provide you with you indoor data 
>>>>> without 
>>>>> blocking the main WeeWX thread. Once proved, the serial read could be 
>>>>> moved 
>>>>> to a thread if you really had the need.
>>>>>
>>>>> Gary
>>>>>
>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to weewx-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-user/7e5a7de6-c535-458f-b81a-e927bd3a2572n%40googlegroups.com.

Reply via email to