feat(itho-wpu): cache results for getnodeid, getserial, getdatatype in a json file

The results for these calls are static. If we cache them we don't have
to retrieve it from the WPU every time we need it.

To ignore the cache (for reading), provide the --no-cache argument.
This commit is contained in:
Pim van den Berg 2021-01-14 15:11:51 +01:00
parent 0b4b9a3d79
commit ff149eba6a
2 changed files with 62 additions and 3 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
itho-wpu-cache.json

View File

@ -9,6 +9,7 @@ import sys
import time import time
import os import os
import datetime import datetime
import json
from collections import namedtuple from collections import namedtuple
consolelogformatter = logging.Formatter("%(asctime)-15s %(levelname)s: %(message)s") consolelogformatter = logging.Formatter("%(asctime)-15s %(levelname)s: %(message)s")
@ -62,6 +63,8 @@ def parse_args():
parser.add_argument('--slave-only', action='store_true', help="Only run I2C slave") parser.add_argument('--slave-only', action='store_true', help="Only run I2C slave")
parser.add_argument('--slave-timeout', nargs='?', type=int, default=60, parser.add_argument('--slave-timeout', nargs='?', type=int, default=60,
help="Slave timeout in seconds when --slave-only") help="Slave timeout in seconds when --slave-only")
parser.add_argument('--no-cache', action='store_true',
help="Don't use local cache")
parser.add_argument('--export-to-influxdb', action='store_true', parser.add_argument('--export-to-influxdb', action='store_true',
help="Export results to InfluxDB") help="Export results to InfluxDB")
@ -163,14 +166,22 @@ class I2CMaster:
class IthoWPU(): class IthoWPU():
def __init__(self, master_only, slave_only, slave_timeout): def __init__(self, master_only, slave_only, slave_timeout, no_cache):
self.master_only = master_only self.master_only = master_only
self.slave_only = slave_only self.slave_only = slave_only
self.slave_timeout = slave_timeout self.slave_timeout = slave_timeout
self._q = queue.Queue() self._q = queue.Queue()
self.no_cache = no_cache
self.cache = IthoWPUCache()
def get(self, action): def get(self, action):
reponse = None if not self.no_cache:
response = self.cache.get(action.replace('get', ''))
if response is not None:
logger.debug(f"Response (from cache): {response}")
return response
response = None
if not self.master_only: if not self.master_only:
slave = I2CSlave(address=0x40, queue=self._q) slave = I2CSlave(address=0x40, queue=self._q)
@ -188,9 +199,56 @@ class IthoWPU():
if not self.master_only: if not self.master_only:
slave.close() slave.close()
self.cache.set(action.replace('get', ''), response)
return response return response
class IthoWPUCache:
def __init__(self):
self._cache_file = "itho-wpu-cache.json"
self._cache_data = {
'nodeid': None,
'serial': None,
'datatype': None,
'schema_version': '1',
}
self._read_cache()
def _read_cache(self):
if not os.path.exists(self._cache_file):
logger.debug(f"Not loading cache file: {self._cache_file} does not exist")
return
with open(self._cache_file) as cache_file:
cache_data = json.load(cache_file)
logger.debug(f"Loading local cache: {json.dumps(cache_data)}")
for key in ['nodeid', 'serial', 'datatype']:
if key in cache_data:
self._cache_data[key] = cache_data[key]
def _write_cache(self):
with open(self._cache_file, 'w') as cache_file:
logger.debug(f"Writing to local cache: {json.dumps(self._cache_data)}")
json.dump(self._cache_data, cache_file)
def get(self, action):
if action not in ['nodeid', 'serial', 'datatype']:
logger.debug(f"Cache for '{action}' is not supported")
return None
logger.debug(f"Reading '{action}' from local cache")
if self._cache_data[action] is None:
logger.debug(f"Action '{action}' is not present in local cache")
return self._cache_data[action]
def set(self, action, value):
if action not in ['nodeid', 'serial', 'datatype']:
logger.debug(f"Cache for '{action}' is not supported")
return None
logger.debug(f"Writing '{action}' to local cache: {value}")
self._cache_data[action] = value
self._write_cache()
def is_messageclass_valid(action, response): def is_messageclass_valid(action, response):
if int(response[1], 0) != actions[action][0] and int(response[2], 0) != actions[action][1]: if int(response[1], 0) != actions[action][0] and int(response[2], 0) != actions[action][1]:
logger.error(f"Response MessageClass != {actions[action][0]} {actions[action][1]} " logger.error(f"Response MessageClass != {actions[action][0]} {actions[action][1]} "
@ -304,7 +362,7 @@ if __name__ == "__main__":
if args.loglevel: if args.loglevel:
logger.setLevel(args.loglevel.upper()) logger.setLevel(args.loglevel.upper())
wpu = IthoWPU(args.master_only, args.slave_only, args.slave_timeout) wpu = IthoWPU(args.master_only, args.slave_only, args.slave_timeout, args.no_cache)
response = wpu.get(args.action) response = wpu.get(args.action)
if response is not None: if response is not None:
process_response(args.action, response, args) process_response(args.action, response, args)