Add support for multiple serial devices
This commit is contained in:
parent
f6c206e0b1
commit
87e337a69d
@ -24,7 +24,8 @@ barcode_server:
|
|||||||
# (optional) Serial push configuration
|
# (optional) Serial push configuration
|
||||||
serial:
|
serial:
|
||||||
# URL to send events to using a request
|
# URL to send events to using a request
|
||||||
path: "/dev/ttyUSB0"
|
pathA: "/dev/ttyUSB0"
|
||||||
|
pathB: "/dev/ttyUSB1"
|
||||||
|
|
||||||
# (optional) file push configuration
|
# (optional) file push configuration
|
||||||
file:
|
file:
|
||||||
@ -62,7 +63,7 @@ barcode_server:
|
|||||||
|
|
||||||
# A list of regex patterns to match USB device names against
|
# A list of regex patterns to match USB device names against
|
||||||
devices:
|
devices:
|
||||||
- ".*Barcode.*"
|
- ".*ode.*"
|
||||||
# A list of absolute file paths to devices
|
# A list of absolute file paths to devices
|
||||||
device_paths:
|
device_paths:
|
||||||
#- "/dev/input/barcode_scanner"
|
#- "/dev/input/barcode_scanner"
|
||||||
|
@ -50,7 +50,7 @@ def c_run():
|
|||||||
"""
|
"""
|
||||||
from barcode_server.barcode import BarcodeReader
|
from barcode_server.barcode import BarcodeReader
|
||||||
from barcode_server.config import AppConfig
|
from barcode_server.config import AppConfig
|
||||||
from barcode_server.webserver import Webserver
|
from barcode_server.webserver import WebServer
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ def c_run():
|
|||||||
LOGGER.info(f"Instance ID: {config.INSTANCE_ID.value}")
|
LOGGER.info(f"Instance ID: {config.INSTANCE_ID.value}")
|
||||||
|
|
||||||
barcode_reader = BarcodeReader(config)
|
barcode_reader = BarcodeReader(config)
|
||||||
webserver = Webserver(config, barcode_reader)
|
webserver = WebServer(config, barcode_reader)
|
||||||
|
|
||||||
# start prometheus server
|
# start prometheus server
|
||||||
if config.STATS_PORT.value is not None:
|
if config.STATS_PORT.value is not None:
|
||||||
|
@ -213,11 +213,20 @@ class AppConfig(ConfigBase):
|
|||||||
required=True
|
required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
SERIAL_PATH = StringConfigEntry(
|
SERIAL_PATH_A = StringConfigEntry(
|
||||||
key_path=[
|
key_path=[
|
||||||
CONFIG_NODE_ROOT,
|
CONFIG_NODE_ROOT,
|
||||||
CONFIG_NODE_SERIAL,
|
CONFIG_NODE_SERIAL,
|
||||||
"path"
|
"pathA"
|
||||||
|
],
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
SERIAL_PATH_B = StringConfigEntry(
|
||||||
|
key_path=[
|
||||||
|
CONFIG_NODE_ROOT,
|
||||||
|
CONFIG_NODE_SERIAL,
|
||||||
|
"pathB"
|
||||||
],
|
],
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
|
import os
|
||||||
import logging
|
import logging
|
||||||
# import time as sleep
|
from pathlib import Path
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from prometheus_async.aio import time
|
from prometheus_async.aio import time
|
||||||
|
|
||||||
from barcode_server.barcode import BarcodeEvent
|
from barcode_server.barcode import BarcodeEvent
|
||||||
from barcode_server.notifier import BarcodeNotifier
|
from barcode_server.notifier import BarcodeNotifier
|
||||||
from barcode_server.stats import FILE_NOTIFIER_TIME
|
from barcode_server.stats import FILE_NOTIFIER_TIME
|
||||||
|
from barcode_server.util import barcode_event_to_json
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -13,8 +16,45 @@ class FileNotifier(BarcodeNotifier):
|
|||||||
|
|
||||||
def __init__(self, path: str):
|
def __init__(self, path: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.inputDevicePathA = None
|
||||||
|
self.inputDevicePathB = None
|
||||||
self.path = path
|
self.path = path
|
||||||
|
pathObject = Path(path)
|
||||||
|
if not pathObject.exists():
|
||||||
|
pathObject.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# def ticks(dt):
|
||||||
|
# return (dt - datetime(1, 1, 1)).total_seconds() * 10000000
|
||||||
|
|
||||||
@time(FILE_NOTIFIER_TIME)
|
@time(FILE_NOTIFIER_TIME)
|
||||||
async def _send_event(self, event: BarcodeEvent):
|
async def _send_event(self, event: BarcodeEvent):
|
||||||
LOGGER.debug(f"Notified {self.path}: {event.barcode}")
|
now = datetime.now()
|
||||||
|
date_time = now.strftime("%Y-%m-%d")
|
||||||
|
weekNumberOfYear = now.strftime("%Y_Week_%U")
|
||||||
|
if self.inputDevicePathA is None:
|
||||||
|
self.inputDevicePathA = event.input_device.path
|
||||||
|
elif self.inputDevicePathB is None:
|
||||||
|
self.inputDevicePathB = event.input_device.path
|
||||||
|
weekPath = f"{self.path}/{weekNumberOfYear}"
|
||||||
|
dateTimePath = f"{weekPath}/{date_time}"
|
||||||
|
if event.input_device.path == self.inputDevicePathA:
|
||||||
|
fullPath = f"{dateTimePath}/A"
|
||||||
|
elif event.input_device.path == self.inputDevicePathB:
|
||||||
|
fullPath = f"{dateTimePath}/B"
|
||||||
|
else:
|
||||||
|
fullPath = f"{dateTimePath}/Z"
|
||||||
|
json = barcode_event_to_json(self.config.INSTANCE_ID.value, event)
|
||||||
|
ticks = int((datetime.utcnow() - datetime(1, 1, 1)).total_seconds() * 10000000)
|
||||||
|
pathObject = Path(weekPath)
|
||||||
|
if not pathObject.exists():
|
||||||
|
pathObject.mkdir(exist_ok=True)
|
||||||
|
pathObject = Path(dateTimePath)
|
||||||
|
if not pathObject.exists():
|
||||||
|
pathObject.mkdir(exist_ok=True)
|
||||||
|
pathObject = Path(fullPath)
|
||||||
|
if not pathObject.exists():
|
||||||
|
pathObject.mkdir(exist_ok=True)
|
||||||
|
f = open(f"{fullPath}/{str(ticks)}.json", 'wb')
|
||||||
|
f.write(json)
|
||||||
|
f.close()
|
||||||
|
LOGGER.debug(f"Notified {fullPath}: {event.barcode}")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import serial
|
import serial
|
||||||
import logging
|
import logging
|
||||||
# import time as sleep
|
|
||||||
|
|
||||||
from prometheus_async.aio import time
|
from prometheus_async.aio import time
|
||||||
|
|
||||||
@ -12,12 +11,25 @@ LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class SerialNotifier(BarcodeNotifier):
|
class SerialNotifier(BarcodeNotifier):
|
||||||
|
|
||||||
def __init__(self, path: str, usb: serial):
|
def __init__(self, pathA: str, pathB: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.path = path
|
self.pathA = pathA
|
||||||
self.usb = usb
|
self.pathB = pathB
|
||||||
|
self.inputDevicePathA = None
|
||||||
|
self.inputDevicePathB = None
|
||||||
|
self.usbA = serial.Serial(pathA, 9600, timeout=2)
|
||||||
|
if pathB is not None:
|
||||||
|
self.usbB = serial.Serial(pathB, 9600, timeout=2)
|
||||||
|
|
||||||
@time(SERIAL_NOTIFIER_TIME)
|
@time(SERIAL_NOTIFIER_TIME)
|
||||||
async def _send_event(self, event: BarcodeEvent):
|
async def _send_event(self, event: BarcodeEvent):
|
||||||
self.usb.write(event.barcode.encode())
|
if self.inputDevicePathA is None:
|
||||||
LOGGER.debug(f"Notified {self.path}: {event.barcode}")
|
self.inputDevicePathA = event.input_device.path
|
||||||
|
elif self.inputDevicePathB is None:
|
||||||
|
self.inputDevicePathB = event.input_device.path
|
||||||
|
if event.input_device.path == self.inputDevicePathA:
|
||||||
|
self.usbA.write(event.barcode.encode())
|
||||||
|
LOGGER.debug(f"Notified {self.pathA}: {self.inputDevicePathA}: {event.barcode}")
|
||||||
|
elif event.input_device.path == self.inputDevicePathB:
|
||||||
|
self.usbB.write(event.barcode.encode())
|
||||||
|
LOGGER.debug(f"Notified {self.pathB}: {self.inputDevicePathB}: {event.barcode}")
|
||||||
|
@ -27,3 +27,4 @@ WEBSOCKET_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='websocket')
|
|||||||
HTTP_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='http')
|
HTTP_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='http')
|
||||||
SERIAL_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='serial')
|
SERIAL_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='serial')
|
||||||
MQTT_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='mqtt')
|
MQTT_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='mqtt')
|
||||||
|
FILE_NOTIFIER_TIME = NOTIFIER_TIME.labels(type='file')
|
||||||
|
@ -15,6 +15,7 @@ from barcode_server.notifier import BarcodeNotifier
|
|||||||
from barcode_server.notifier.http import HttpNotifier
|
from barcode_server.notifier.http import HttpNotifier
|
||||||
from barcode_server.notifier.mqtt import MQTTNotifier
|
from barcode_server.notifier.mqtt import MQTTNotifier
|
||||||
from barcode_server.notifier.serial import SerialNotifier
|
from barcode_server.notifier.serial import SerialNotifier
|
||||||
|
from barcode_server.notifier.file import FileNotifier
|
||||||
from barcode_server.notifier.ws import WebsocketNotifier
|
from barcode_server.notifier.ws import WebsocketNotifier
|
||||||
from barcode_server.stats import REST_TIME_DEVICES, WEBSOCKET_CLIENT_COUNT
|
from barcode_server.stats import REST_TIME_DEVICES, WEBSOCKET_CLIENT_COUNT
|
||||||
from barcode_server.util import input_device_to_dict
|
from barcode_server.util import input_device_to_dict
|
||||||
@ -23,7 +24,7 @@ LOGGER = logging.getLogger(__name__)
|
|||||||
routes = web.RouteTableDef()
|
routes = web.RouteTableDef()
|
||||||
|
|
||||||
|
|
||||||
class Webserver:
|
class WebServer:
|
||||||
|
|
||||||
def __init__(self, config: AppConfig, barcode_reader: BarcodeReader):
|
def __init__(self, config: AppConfig, barcode_reader: BarcodeReader):
|
||||||
self.config = config
|
self.config = config
|
||||||
@ -35,9 +36,8 @@ class Webserver:
|
|||||||
self.barcode_reader = barcode_reader
|
self.barcode_reader = barcode_reader
|
||||||
self.barcode_reader.add_listener(self.on_barcode)
|
self.barcode_reader.add_listener(self.on_barcode)
|
||||||
|
|
||||||
self.usb = {}
|
|
||||||
|
|
||||||
self.notifiers: Dict[str, BarcodeNotifier] = {}
|
self.notifiers: Dict[str, BarcodeNotifier] = {}
|
||||||
|
|
||||||
if config.HTTP_URL.value is not None:
|
if config.HTTP_URL.value is not None:
|
||||||
http_notifier = HttpNotifier(
|
http_notifier = HttpNotifier(
|
||||||
config.HTTP_METHOD.value,
|
config.HTTP_METHOD.value,
|
||||||
@ -58,13 +58,12 @@ class Webserver:
|
|||||||
)
|
)
|
||||||
self.notifiers["mqtt"] = mqtt_notifier
|
self.notifiers["mqtt"] = mqtt_notifier
|
||||||
|
|
||||||
if config.SERIAL_PATH.value is not None:
|
if config.SERIAL_PATH_A.value is not None:
|
||||||
self.usb = serial.Serial(config.SERIAL_PATH.value, 9600, timeout=2)
|
serial_notifier = SerialNotifier(config.SERIAL_PATH_A.value, config.SERIAL_PATH_B.value)
|
||||||
serial_notifier = SerialNotifier(config.SERIAL_PATH.value, self.usb)
|
|
||||||
self.notifiers["serial"] = serial_notifier
|
self.notifiers["serial"] = serial_notifier
|
||||||
|
|
||||||
if config.FILE_PATH.value is not None:
|
if config.FILE_PATH.value is not None:
|
||||||
file_notifier = SerialNotifier(config.FILE_PATH.value)
|
file_notifier = FileNotifier(config.FILE_PATH.value)
|
||||||
self.notifiers["file"] = file_notifier
|
self.notifiers["file"] = file_notifier
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
|
@ -8,7 +8,7 @@ from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
|||||||
from barcode_server import const
|
from barcode_server import const
|
||||||
from barcode_server.barcode import BarcodeEvent
|
from barcode_server.barcode import BarcodeEvent
|
||||||
from barcode_server.util import barcode_event_to_json
|
from barcode_server.util import barcode_event_to_json
|
||||||
from barcode_server.webserver import Webserver
|
from barcode_server.webserver import WebServer
|
||||||
|
|
||||||
|
|
||||||
def create_barcode_event_mock(barcode: str = None):
|
def create_barcode_event_mock(barcode: str = None):
|
||||||
@ -46,7 +46,7 @@ class WebsocketNotifierTest(AioHTTPTestCase):
|
|||||||
Override the get_app method to return your application.
|
Override the get_app method to return your application.
|
||||||
"""
|
"""
|
||||||
barcode_reader = MagicMock()
|
barcode_reader = MagicMock()
|
||||||
self.webserver = Webserver(self.config, barcode_reader)
|
self.webserver = WebServer(self.config, barcode_reader)
|
||||||
app = self.webserver.create_app()
|
app = self.webserver.create_app()
|
||||||
runner = aiohttp.web.AppRunner(app)
|
runner = aiohttp.web.AppRunner(app)
|
||||||
await runner.setup()
|
await runner.setup()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user