Newer
Older
Dónal Murray
committed
#!/usr/bin/env python3
# Front end generator for HEV raspberry pi data server
# author Dónal Murray <donal.murray@cern.ch>
import time
import numpy as np
Dónal Murray
committed
import argparse
from collections import deque
import commsFormat
import threading
import commsConstants
Dónal Murray
committed
from commsConstants import alarm_codes
Dónal Murray
committed
from typing import List, Dict
Dónal Murray
committed
import logging
logging.basicConfig(level=logging.INFO,
Dónal Murray
committed
format='%(asctime)s - %(levelname)s - %(message)s')
Dónal Murray
committed
Dónal Murray
committed
class svpi():
def __init__(self, inputFile):
# use input file for testing
Dónal Murray
committed
self._input = open(inputFile, 'rb')
# dump file to variable
self._bytestore = bytearray(self._input.read())
self._pos = 0 # position inside bytestore
# received queue and observers to be notified on update
self._payloadrecv = deque(maxlen = 16)
self._observers = []
sendingWorker = threading.Thread(target=self.generate, daemon=True)
sendingWorker.start()
Dónal Murray
committed
def generate(self) -> None:
while True:
# check for an alarm
alarm = self.getAlarms()
if alarm is not None:
byteArray = alarm
payload = commsConstants.alarmFormat()
else:
# grab next array from filedump
fullArray = self._bytestore[0+self._pos*27:27+self._pos*27]
# current byte dump (20200411) has wrong format 27 bytes, new format expects 26. snip out second byte
byteArray = fullArray[:1] + fullArray[2:]
# go to next byte array. if at the end, loop
self._pos = self._pos + 1 if self._pos < 99 else 0
payload = commsConstants.dataFormat()
payload.fromByteArray(byteArray)
self.payloadrecv = payload
time.sleep(1)
Dónal Murray
committed
def getAlarms(self) -> List[str]:
Dónal Murray
committed
# give/cancel a random alarm a twentieth of the time
if np.random.randint(0, 20) == 0:
Dónal Murray
committed
# send alarm
alarm = 1 + np.random.randint(0, len(alarm_codes))
return bytearray((0xA0,alarm,0x00,0x00,0x00,0x00))
Dónal Murray
committed
return None
Dónal Murray
committed
Dónal Murray
committed
# callback to dependants to read the received payload
@property
def payloadrecv(self):
return self._payloadrecv
@payloadrecv.setter
def payloadrecv(self, payload):
self._payloadrecv.append(payload)
logging.debug(f"Pushed {payload} to FIFO")
for callback in self._observers:
# peek at the leftmost item, don't pop until receipt confirmed
callback(self._payloadrecv[0])
def writePayload(self, payload):
logging.info(payload)
Dónal Murray
committed
def bind_to(self, callback):
self._observers.append(callback)
def pop_payloadrecv(self):
# from callback. confirmed receipt, pop value
poppedval = self._payloadrecv.popleft()
logging.debug(f"Popped {poppedval} from FIFO")
if len(self._payloadrecv) > 0:
# purge full queue if Dependant goes down when it comes back up
for callback in self._observers:
callback(self._payloadrecv[0])
Dónal Murray
committed
if __name__ == "__main__":
Dónal Murray
committed
#parser to allow us to pass arguments to hevserver
parser = argparse.ArgumentParser(description='Arguments to run hevserver')
parser.add_argument('--inputFile', type=str, default = '', help='a test file to load data')
args = parser.parse_args()
generator = svpi(args.inputFile)
while True:
pass