Commit 4d5c269a authored by Dónal Murray's avatar Dónal Murray

Simplify hevclient internals

parent 42df77bf
Pipeline #1502 failed with stages
......@@ -31,7 +31,7 @@ import time
import json
import threading
from typing import List, Dict, Union
from CommsCommon import PayloadFormat, PAYLOAD_TYPE
from CommsCommon import PAYLOAD_TYPE
import logging
logging.basicConfig(
......@@ -45,80 +45,71 @@ class HEVPacketError(Exception):
class HEVClient(object):
def __init__(self, polling=True):
super(HEVClient, self).__init__()
self._alarms = [] # db for alarms
self._personal = None # db for personal data
self._fastdata = None # db for sensor values
self._readback = None # db for sensor values
self._cycle = None # db for sensor values
self._target = None # db for sensor values
self._logmsg = None # db for sensor values
self._thresholds = None # db for sensor values
self._thresholds = [] # db for threshold settings
self._polling = polling # keep reading data into db
self._lock = threading.Lock() # lock for the database
super().__init__()
# alarms latch
self._alarms = []
# Last packet of each type
self._last_packet = {
"PERSONAL": None,
"DATA": None,
"READBACK": None,
"CYCLE": None,
"TARGET": None,
"LOGMSG": None,
"THRESHOLDS": None,
}
# lock for the last packet storage
self._lock = threading.Lock()
# start polling in another thread unless told otherwise
self._polling = polling
if self._polling:
self.start_polling()
def start_polling(self):
"""start worker thread to update db in the background"""
"""start worker thread to get data in the background"""
worker = threading.Thread(target=self.start_client, daemon=True)
worker.start()
def start_client(self) -> None:
"""synchronous wrapper for polling()"""
asyncio.run(self.polling())
async def polling(self) -> None:
"""open persistent connection with server"""
writer = None
data = None
while True:
try:
reader, writer = await asyncio.open_connection("127.0.0.1", 54320)
# grab data from the socket as soon as it is available and dump it in the db
while self._polling:
try:
# grab data from the socket as soon as it is available
data = await reader.readuntil(separator=b"\0")
data = data[:-1] # snip off nullbyte
# snip off nullbyte and parse json
data = data[:-1]
payload = json.loads(data.decode("utf-8"))
if payload["type"] == "keepalive":
# Still alive
payload_type = payload["type"]
# check that it's valid
if payload_type == "keepalive":
# drop silently - without it the hevserver can go down unnoticed
continue
elif payload["type"] == "DATA":
with self._lock:
self._fastdata = payload["DATA"]
elif payload["type"] == "READBACK":
with self._lock:
self._readback = payload["READBACK"]
elif payload["type"] == "CYCLE":
with self._lock:
self._cycle = payload["CYCLE"]
elif payload["type"] == "TARGET":
with self._lock:
self._target = payload["TARGET"]
elif payload["type"] == "PERSONAL":
elif payload_type in self._last_packet:
# store it in the right place and pass it on
with self._lock:
self._personal = payload["PERSONAL"]
elif payload["type"] == "LOGMSG":
with self._lock:
self._logmsg = payload["LOGMSG"]
elif payload["type"] == "THRESHOLDS":
with self._lock:
self._thresholds = payload["THRESHOLDS"]
elif payload["type"] == "ALARM":
with self._lock:
self._alarms = payload["ALARM"]
elif payload["type"] in [pt.name for pt in PAYLOAD_TYPE]:
# payload type is a valid payload type
self._last_packet[payload_type] = payload[payload_type]
elif payload_type in [pt.name for pt in PAYLOAD_TYPE]:
# valid payload type but unimplemented in hevclient
# passing lets us still use alarm information vs continue
pass
else:
# invalid packet - something seriously wrong with the hevserver
raise HEVPacketError("Invalid broadcast type")
self._alarms = payload["alarms"]
# self._personal = payload["personal"]
self.get_updates(payload) # callback function to be overridden
except json.decoder.JSONDecodeError:
logging.warning(f"Could not decode packet: {data}")
......@@ -140,6 +131,7 @@ class HEVClient(object):
def get_updates(self, payload) -> None:
"""Overrideable function called after receiving data from the socket, with that data as an argument"""
logging.debug(payload)
pass
async def _send_request(
......@@ -213,39 +205,32 @@ class HEVClient(object):
# def send_personal(self, personal: Dict[str, str]=None ) -> bool:
def send_personal(self, personal: str) -> bool:
# acknowledge alarm to remove it from the hevserver list
# send personal information
return asyncio.run(self._send_request("PERSONAL", personal=personal))
# Getters to check last value of each datatype - debugging only
def get_values(self) -> Dict:
# get sensor values from db
return self._fastdata
return self._last_packet["DATA"]
def get_readback(self) -> Dict:
# get readback from db
return self._readback
return self._last_packet["READBACK"]
def get_cycle(self) -> Dict:
# get cycle data from db
return self._cycle
return self._last_packet["CYCLE"]
def get_personal(self) -> Dict:
# get personal data from db
return self._personal
return self._last_packet["PERSONAL"]
def get_logmsg(self) -> Dict:
# get logmsg data from db
return self._logmsg
return self._last_packet["LOGMSG"]
def get_target(self) -> Dict:
# get target data from db
return self._target
return self._last_packet["TARGET"]
def get_thresholds(self) -> Dict:
# get threshold data from db
return self._thresholds
return self._last_packet["THRESHOLDS"]
def get_alarms(self) -> List[str]:
# get alarms from db
return self._alarms
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment