From ff149eba6aeaaa2ee1f4a2d48fc6f5ba6c2a27d6 Mon Sep 17 00:00:00 2001 From: Pim van den Berg Date: Thu, 14 Jan 2021 15:11:51 +0100 Subject: [PATCH] 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. --- .gitignore | 1 + itho-wpu.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..021178c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +itho-wpu-cache.json diff --git a/itho-wpu.py b/itho-wpu.py index 27bcdd7..29c365c 100755 --- a/itho-wpu.py +++ b/itho-wpu.py @@ -9,6 +9,7 @@ import sys import time import os import datetime +import json from collections import namedtuple 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-timeout', nargs='?', type=int, default=60, 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', help="Export results to InfluxDB") @@ -163,14 +166,22 @@ class I2CMaster: 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.slave_only = slave_only self.slave_timeout = slave_timeout self._q = queue.Queue() + self.no_cache = no_cache + self.cache = IthoWPUCache() 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: slave = I2CSlave(address=0x40, queue=self._q) @@ -188,9 +199,56 @@ class IthoWPU(): if not self.master_only: slave.close() + self.cache.set(action.replace('get', ''), 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): 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]} " @@ -304,7 +362,7 @@ if __name__ == "__main__": if args.loglevel: 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) if response is not None: process_response(args.action, response, args)