The modification to AsyncReader is to add a write mode so weewx acts as a timeserver. Triggered by sentinel "request_datetime".
The timeserver was not called during the gap at 9:15pm in the previous post attachment and log. Search the log for "AsyncReader"
def run_read_mode(self):
# fixme I think this should be longer than the loop time for the arduino
timeout = 12
# select(rlist,wlist,xlist,timeout); wait until ready for reading (rlist);
ready,_,_ = select.select([self._fd], [], [], timeout)
if not ready:
return
line = self._fd.readline()
# fixme verbose
logdbg("read line = '%s'" % (line))
line = line.rstrip()
# all our files are binary
line = line.decode()
if not line:
return
if self._write_mode and (line == "request_datetime"):
self._read_mode = False
self._write_attempt = 0
return
# garberw begin -----------------------
# we are not processing any lines other than json so just keep only json;
# this saves a little work until we get to PacketFactory.create;
# to see the debugging info comment this line out;
# PacketFactory.parse_json handles this line;
# PacketFactory.parse_text handles the other lines; we never use that;
#if not line.startswith("{"):
# return
# garberw end -----------------------
# line = fudge_time()
self._queue.put(line)
def run_write_mode(self):
# fixme check this
timeout = 12
# select(rlist,wlist,xlist,timeout); wait until ready for writing (wlist);
_,ready,_ = select.select([], [self._fd], [], timeout)
if not ready:
self._write_attempt += 1
if self._write_attempt >= self.WRITE_ATTEMPT_MAX:
logdbg("AsyncReader write timeout")
self._read_mode = True
return
# int(1677178029.12345) seconds since epoch
time_now_epoch = int(time.time())
# '1677178029\n'
time_str_epoch = '{}\n'.format(time_now_epoch)
# b'1677178029\n'
buf = bytes(time_str_epoch, 'ascii')
self._fd.write(buf)
self._fd.flush()
loginf("AsyncReader wrote timestamp={} buf={}".format(time_now_epoch, buf))
self._read_mode = True
Maybe the problem is that the queue in AsyncReader gets too full before ProcessManager.get_stdout()
yields all the lines to PacketFactory.create() which parses the json in them and
pops each line off the list "lines". Sort of like flushing the input buffer.
ProcessManager.get_stdout() yields the lines immediately if they contain a timestamp matching
TS = re.compile('^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d[\s]+')
maybe this would "flush the input buffer sooner" but this doesn't work for me since I am using unix epoch time as an integer
not formatted like TS.