robot0nfire/c0re
Archived
1
0
Fork 0
This repository has been archived on 2025-05-08. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
c0re/sensor_readout.py
2018-04-07 17:43:54 +02:00

158 lines
3.8 KiB
Python

from random import randint
from threading import Lock
from _thread import start_new_thread
from os.path import exists
from asyncio import sleep
from ctypes import cdll
from utils import is_wallaby
from highway import log as logging
ANALOG = 1
DIGITAL = 2
NAMED_MODES = {ANALOG : "analog", DIGITAL : "digital"}
REVERSE_NAMED_MODES = {v : k for k, v in NAMED_MODES.items()}
MODES = tuple(NAMED_MODES.keys())
CONFIG_PATH = "fl0w.cfg"
IS_WALLABY = is_wallaby()
LIB_WALLABY = "/usr/lib/libwallaby.so"
READOUT_TEMPLATE = {
ANALOG : [],
DIGITAL : []
}
def valid_port(port, mode):
if mode == ANALOG:
return port >= 0 and port <= 5
elif mode == DIGITAL:
return port >= 0 and port <= 9
return False
class SensorReadout:
def __init__(self, poll_rate=0.2):
self.poll_rate = poll_rate
self.handler_lock = Lock()
self.handlers = {}
self.running = True
self.readout_required = READOUT_TEMPLATE.copy()
# Wallaby library avaliable?
if not exists(LIB_WALLABY):
logging.warning("Wallaby library unavaliable.")
self.get_sensor_value = self.__get_random_value
else:
self.wallaby_library = cdll.LoadLibrary(LIB_WALLABY)
self.get_sensor_value = self.__get_sensor_value
async def run(self):
while self.running:
current_values = {
ANALOG : {},
DIGITAL : {}
}
for mode in MODES:
for port in self.readout_required[mode]:
current_values[mode][port] = self.get_sensor_value(port, mode)
self.handler_lock.acquire()
for handler in self.handlers:
readouts = 0
response = {ANALOG : {}, DIGITAL : {}}
for mode in MODES:
for port in self.handlers[handler][mode]:
response[mode][port] = current_values[mode][port]
readouts += 1
if readouts != 0:
await handler.send(response, "sensor_stream")
self.handler_lock.release()
await sleep(self.poll_rate)
def stop(self):
self.running = False
def subscribe(self, port, mode, handler):
if port not in self.readout_required[mode]:
self.readout_required[mode].append(port)
if not handler in self.handlers:
self.handler_lock.acquire()
self.handlers[handler] = READOUT_TEMPLATE.copy()
self.handler_lock.release()
self.handler_lock.acquire()
self.handlers[handler][mode].append(port)
self.handler_lock.release()
def unsubscribe(self, port, mode, handler):
if handler in self.handlers:
if port in self.handlers[handler][mode]:
self.handler_lock.acquire()
del self.handlers[handler][mode][ \
self.handlers[handler][mode].index(port)]
self.handler_lock.release()
self.determine_required_readouts()
def determine_required_readouts(self):
readout_required = READOUT_TEMPLATE.copy()
self.handler_lock.acquire()
for handler in self.handlers:
for mode in MODES:
for port in self.handlers[handler][mode]:
if not port in readout_required[mode]:
readout_required[mode].append(port)
self.handler_lock.release()
self.readout_required = readout_required
async def unsubscribe_all(self, handler):
successful = False
if handler in self.handlers:
self.handler_lock.acquire()
del self.handlers[handler]
self.handler_lock.release()
successful = True
self.determine_required_readouts()
await handler.send(successful, "sensor_unsubscribe")
def handler_disconnected(self, handler):
if handler in self.handlers:
self.handler_lock.acquire()
del self.handlers[handler]
self.handler_lock.release()
self.determine_required_readouts()
def __get_sensor_value(self, port, mode):
if mode == SensorReadout.ANALOG:
return self.wallaby_library.analog(port)
elif mode == SensorReadout.DIGITAL:
return self.wallaby_library.digital(port)
def __get_random_value(self, port, mode):
if mode == ANALOG:
return randint(0, 4095)
elif mode == DIGITAL:
return randint(0, 1)