Skip to content

Commit a0f799d

Browse files
authored
Merge pull request #15 from juergenpabel/feature-logging
[feature] implements #14, various logging capabilities (console, sysl…
2 parents 25d3d72 + 1d68465 commit a0f799d

19 files changed

Lines changed: 872 additions & 149 deletions

File tree

src/app/__init__.py

Lines changed: 86 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,132 @@
11
import os
22
import time
33
import wifi
4+
45
import toml
6+
import adafruit_logging as logging
7+
from .printers import Printer, NullPrinter
8+
from .services import Service
9+
from .util.log import Log
510

611

7-
class Server:
8-
debug: bool = False
12+
class Server(object):
913
runtime: dict
10-
config: toml.Dotty
14+
settings: toml.Dotty
15+
logger: logging.Logger
16+
17+
def __new__(cls):
18+
if hasattr(cls, 'singleton') is False:
19+
cls.singleton = super(Server, cls).__new__(cls)
20+
cls.singleton.logger = Log().getLogger("root")
21+
cls.singleton.settings = None
22+
cls.singleton.runtime = { 'printers': {}, 'services': {} }
23+
return cls.singleton
1124

12-
def __init__(self, debug):
13-
self.debug = debug
14-
self.runtime = { 'printers': {}, 'services': {} }
15-
self.config = toml.load('settings.toml')
16-
self.config.setdefault('SYSTEM', {})
17-
self.config.setdefault('ESCPOS', {'PRINTERS': {}, 'SERVICES': {}})
18-
self.config.setdefault('PRINTER:DEBUG', {'DRIVER': 'DEBUG'})
25+
def getLogger(self) -> logging.Logger:
26+
return self.logger
27+
28+
def getPrinter(self, name: str) -> Printer:
29+
if len(self.runtime['printers']) == 0:
30+
return None
31+
if name not in self.runtime['printers']:
32+
return NullPrinter()
33+
return self.runtime['printers'][name]
1934

35+
def getService(self, name: str) -> Service:
36+
if name in self.runtime['services']:
37+
return self.runtime['services'][name]
38+
return None
2039

2140
def setup(self):
22-
print(f"Configuring printers...")
23-
for printer_name in self.config['ESCPOS']['PRINTERS']:
24-
print(f" Configuring printer '{printer_name}'...")
41+
self.settings = toml.load('settings.toml')
42+
self.settings.setdefault('SYSTEM', {})
43+
self.settings.setdefault('ESCPOS', {'PRINTERS': {}, 'SERVICES': {}})
44+
self.settings.setdefault('PRINTER:DEBUG', {'DRIVER': 'DEBUG'})
45+
Log().setup(self, self.settings)
46+
self.logger.info(f"Configuring printers...")
47+
printers = dict()
48+
for printer_name in self.settings['ESCPOS']['PRINTERS']:
49+
self.logger.info(f" Configuring printer '{printer_name}'...")
2550
printer_section = f"PRINTER:{printer_name}"
26-
if printer_section in self.config and 'DRIVER' in self.config[printer_section]:
51+
if printer_section in self.settings and 'DRIVER' in self.settings[printer_section]:
2752
printer = None
28-
printer_driver = self.config[printer_section]['DRIVER'].upper()
53+
printer_driver = self.settings[printer_section]['DRIVER'].upper()
2954
if printer_driver == 'DEBUG':
3055
from .printers.debug import PrinterDEBUG
3156
printer = PrinterDEBUG()
3257
elif printer_driver == 'SERIAL':
3358
from .printers.serial import PrinterSerial
34-
printer = PrinterSerial(self.debug)
59+
printer = PrinterSerial()
3560
elif printer_driver == 'USB':
3661
from .printers.usb import PrinterUSB
37-
usb_host_pin_dp = self.config['SYSTEM'].get('USB_HOST_PIN_DP')
38-
usb_host_pin_dm = self.config['SYSTEM'].get('USB_HOST_PIN_DM')
62+
usb_host_pin_dp = self.settings['SYSTEM'].get('USB_HOST_PIN_DP')
63+
usb_host_pin_dm = self.settings['SYSTEM'].get('USB_HOST_PIN_DM')
3964
if usb_host_pin_dp is not None and usb_host_pin_dm is not None:
40-
printer = PrinterUSB(usb_host_pin_dp, usb_host_pin_dm, self.debug)
65+
printer = PrinterUSB(printer_name, usb_host_pin_dp, usb_host_pin_dm)
4166
else:
42-
print(f" ERROR: in configuration for printer '{printer_name}': missing pin definition in table/section SYSTEM (USB_HOST_PIN_DP & USB_HOST_PIN_DM), skipping printer")
67+
self.logger.error(f" Missing USB pin definition in table/section SYSTEM (USB_HOST_PIN_DP & USB_HOST_PIN_DM), skipping printer '{printer_name}'")
4368
else:
44-
print(f" ERROR: in configuration for printer '{printer_name}': unknown driver type '{printer_driver}', skipping printer")
69+
self.logger.error(f" DRIVER='{printer_driver}' is invalid in configuration table/section 'PRINTER:{printer_name}' (in settings.toml), skipping printer")
4570
if printer is not None:
46-
if printer.setup(self.config[printer_section]) is True:
47-
self.runtime['printers'][printer_name] = printer
71+
if printer.setup(self.settings[printer_section]) is True:
72+
printers[printer_name] = printer
4873
else:
49-
print(f" WARNING: Printer{printer_driver}.setup() failed for printer '{printer_name}', skipping printer")
50-
print(f" ...configuration for printer '{printer_name}' finished")
51-
print(f"...printers configured ({len(self.runtime['printers'])} active printers)")
74+
self.logger.warning(f" Printer{printer_driver}.setup() failed for printer '{printer_name}', skipping printer")
75+
self.logger.info(f" ...configuration for printer '{printer_name}' finished")
76+
self.runtime['printers'] = printers
77+
self.logger.info(f"...printers configured ({len(self.runtime['printers'])} active printers)")
5278

53-
print(f"Configuring services...")
79+
self.logger.info(f"Configuring services...")
80+
services = dict()
5481
if len(self.runtime['printers']) == 0:
55-
print(f" ERROR: no active printers, not activating any services")
56-
self.config['ESCPOS']['SERVICES'] = []
57-
for service_name in self.config['ESCPOS']['SERVICES']:
58-
print(f" Configuring service '{service_name}'...")
82+
self.logger.critical(f" No (active) printers, not activating any services")
83+
self.settings['ESCPOS']['SERVICES'] = []
84+
for service_name in self.settings['ESCPOS']['SERVICES']:
85+
self.logger.info(f" Configuring service '{service_name}'...")
5986
service_section = f"SERVICE:{service_name}"
60-
if service_section not in self.config:
61-
print(f" ERROR: configuration table/section 'SERVICE:{service_name}' not found, skipping service")
62-
if 'DRIVER' not in self.config[service_section]:
63-
print(f" ERROR: missing 'DRIVER' config in table/section 'SERVICE:{service_name}', skipping service")
64-
if service_section in self.config and 'DRIVER' in self.config[service_section]:
87+
if service_section not in self.settings:
88+
self.logger.error(f" Configuration table/section 'SERVICE:{service_name}' (in settings.toml) not found, skipping service")
89+
if 'DRIVER' not in self.settings[service_section]:
90+
self.logger.error(f" Missing 'DRIVER' config in table/section 'SERVICE:{service_name}' (in settings.toml), skipping service")
91+
if service_section in self.settings and 'DRIVER' in self.settings[service_section]:
6592
service = None
66-
service_driver = self.config[service_section]['DRIVER'].upper()
93+
service_driver = self.settings[service_section]['DRIVER'].upper()
6794
if service_driver == 'HTTP':
68-
self.config[service_section].setdefault('SERVER_IPV4', str(wifi.radio.ipv4_address))
69-
self.config[service_section].setdefault('SERVER_PORT', 8080)
70-
self.config[service_section].setdefault('SERVER_PATH', '/')
95+
self.settings[service_section].setdefault('SERVER_IPV4', str(wifi.radio.ipv4_address))
96+
self.settings[service_section].setdefault('SERVER_PORT', 8080)
97+
self.settings[service_section].setdefault('SERVER_PATH', '/')
7198
from .services.http import ServiceHTTP
72-
service = ServiceHTTP(self.debug)
99+
service = ServiceHTTP(service_name)
73100
elif service_driver == 'MQTT':
74-
self.config[service_section].setdefault('BROKER_USER', None)
75-
self.config[service_section].setdefault('BROKER_PASS', None)
101+
self.settings[service_section].setdefault('BROKER_USER', None)
102+
self.settings[service_section].setdefault('BROKER_PASS', None)
76103
from .services.mqtt import ServiceMQTT
77-
service = ServiceMQTT(self.debug)
104+
service = ServiceMQTT(service_name)
78105
elif service_driver == 'TCP':
79-
self.config[service_section].setdefault('SERVER_IPV4', str(wifi.radio.ipv4_address))
80-
self.config[service_section].setdefault('SERVER_PORT', 9100)
81-
self.config[service_section].setdefault('CLIENT_TIMEOUT', 1)
106+
self.settings[service_section].setdefault('SERVER_IPV4', str(wifi.radio.ipv4_address))
107+
self.settings[service_section].setdefault('SERVER_PORT', 9100)
108+
self.settings[service_section].setdefault('CLIENT_TIMEOUT', 1)
82109
from .services.tcp import ServiceTCP
83-
service = ServiceTCP(self.debug)
110+
service = ServiceTCP(service_name)
84111
else:
85-
print(f" ERROR: unknown driver type '{service_driver}' in configuration table/section 'SERVICE:{service_name}', skipping service")
112+
self.logger.error(f" DRIVER='{service_driver}' is invalid in configuration table/section 'SERVICE:{service_name}' (in settings.toml), skipping service")
86113
if service is not None:
87-
self.config[service_section].setdefault('PRINTERS', self.runtime['printers'].keys())
114+
self.settings[service_section].setdefault('PRINTERS', self.runtime['printers'].keys())
88115
service2printers = {}
89-
for printer_name in self.config[service_section]['PRINTERS']:
116+
for printer_name in self.settings[service_section]['PRINTERS']:
90117
if printer_name in self.runtime['printers']:
91118
service2printers[printer_name] = self.runtime['printers'][printer_name]
92119
if len(service2printers) == 0:
93-
print(f" WARNING: No printers assigned to service, skipping service")
120+
self.logger.warning(f" No printers assigned to service, skipping service")
94121
else:
95-
if service.setup(self.config[service_section], service2printers) is True:
96-
self.runtime['services'][service_name] = service
97-
print(f" INFO: Assigned printers = ['{'\',\''.join(service2printers.keys())}']")
122+
if service.setup(self.settings[service_section], service2printers) is True:
123+
services[service_name] = service
124+
self.logger.info(f" Assigned printers = ['{'\',\''.join(service2printers.keys())}']")
98125
else:
99-
print(f" WARNING: Service{service_driver}.setup() failed for service '{service_name}', skipping service")
100-
print(f" ...configuration for service '{service_name}' finished")
101-
print(f"...services configured ({len(self.runtime['services'])} active services)")
126+
self.logger.warning(f" Service{service_driver}.setup() failed for service '{service_name}', skipping service")
127+
self.logger.info(f" ...configuration for service '{service_name}' finished")
128+
self.runtime['services'] = services
129+
self.logger.info(f"...services configured ({len(self.runtime['services'])} active services)")
102130

103131

104132
def loop(self) -> bool:

src/app/printers/__init__.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import binascii
22
import toml
33

4+
45
class Printer:
56
debug: bool = False
67
escpos_init: bytearray = bytearray()
78
escpos_fini: bytearray = bytearray()
89

910

10-
def __init__(self, debug: bool):
11-
self.debug = debug
12-
11+
def __init__(self, name: str):
12+
self.name = name
1313

14-
def setup(self, config: toml.Dotty) -> bool:
14+
def setup(self, config: dict) -> bool:
1515
if 'ESCPOS-INIT' not in config:
1616
config['ESCPOS-INIT'] = "1b401b6404" # reset & feed 4 lines
1717
if 'ESCPOS-FINI' not in config:
@@ -20,19 +20,20 @@ def setup(self, config: toml.Dotty) -> bool:
2020
self.escpos_fini = binascii.unhexlify(config['ESCPOS-FINI'])
2121
return True
2222

23-
2423
def loop(self) -> bool:
2524
return True
2625

27-
2826
def write_init(self) -> None:
2927
self.write(self.escpos_init)
3028

31-
3229
def write(self, data: bytearray) -> None:
3330
pass
3431

35-
3632
def write_fini(self) -> None:
3733
self.write(self.escpos_fini)
3834

35+
36+
class NullPrinter(Printer):
37+
def __init__(self):
38+
Printer.__init__(self, '<NullPrinter>')
39+

src/app/printers/debug.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
from . import Printer
22

3+
34
class PrinterDEBUG(Printer):
45

56
def __init__(self):
6-
Printer.__init__(self, True)
7+
Printer.__init__(self, "DEBUG")
78

8-
def setup(self, config: toml.Dotty) -> bool:
9+
def setup(self, config: dict) -> bool:
910
return Printer.setup(self, config)
1011

1112
def loop(self) -> bool:
1213
return True
1314

1415
def write(self, data: bytearray) -> None:
15-
print(data)
16+
print(data.decode())
1617

src/app/printers/serial.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ class PrinterSerial(Printer):
1414
stopbits: int = 1
1515

1616

17-
def __init__(self, debug: bool):
18-
Printer.__init__(self, debug)
17+
def __init__(self, name: str):
18+
Printer.__init__(self, name)
1919

20-
21-
def setup(self, config: toml.Dotty) -> bool:
20+
def setup(self, config: dict) -> bool:
2221
Printer.setup(self, config)
2322
self.pin_tx = config.get('PIN_TX')
2423
if self.pin_tx not in board.__dict__:
@@ -49,17 +48,14 @@ def setup(self, config: toml.Dotty) -> bool:
4948
parity = busio.Parity.EVEN
5049
if self.parity == 'odd':
5150
parity = busio.Parity.ODD
52-
if self.debug is True:
53-
print(f" DEBUG: instantiating busio.UART(tx=board.{self.pin_tx}, rx=board.{self.pin_rx}, baudrate={self.baud}, bits={self.bits}, parity=busio.Parity.{self.parity.upper()}, stop={self.stopbits})")
51+
print(f" DEBUG: instantiating busio.UART(tx=board.{self.pin_tx}, rx=board.{self.pin_rx}, baudrate={self.baud}, bits={self.bits}, parity=busio.Parity.{self.parity.upper()}, stop={self.stopbits})")
5452
self.uart = busio.UART(board.__dict__.get(self.pin_tx), board.__dict__.get(self.pin_rx),
5553
baudrate=self.baud, bits=self.bits, parity=parity, stop=self.stopbits)
5654
return True
5755

58-
5956
def loop(self) -> bool:
6057
return True
6158

62-
6359
def write(self, data: bytearray) -> None:
6460
if self.uart is not None:
6561
self.uart.write(data)

src/app/printers/usb.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import usb_host
55

66
from . import Printer
7+
from app.util.log import Log
78

89

910
class PrinterUSB(Printer):
@@ -13,9 +14,8 @@ class PrinterUSB(Printer):
1314
device_usb_pid: str = None
1415
device = None
1516

16-
17-
def __init__(self, usb_dp: str, usb_dm: str, debug: bool):
18-
Printer.__init__(self, debug)
17+
def __init__(self, name: str, usb_dp: str, usb_dm: str):
18+
Printer.__init__(self, name)
1919
self.host_usb_dp = usb_dp
2020
self.host_usb_dm = usb_dm
2121
klass = self.__class__
@@ -25,32 +25,29 @@ def __init__(self, usb_dp: str, usb_dm: str, debug: bool):
2525
if isinstance(pin_usb_dp, Pin) is True and isinstance(pin_usb_dm, Pin) is True:
2626
klass.usb_host_port = usb_host.Port(pin_usb_dp, pin_usb_dm)
2727

28-
29-
def setup(self, config: toml.Dotty) -> bool:
28+
def setup(self, config: dict) -> bool:
3029
if hasattr(self.__class__, 'usb_host_port') is False:
31-
print(f" ERROR: failed to instantiate usb_host.Port({self.host_usb_dp}, {self.host_usb_dm})")
30+
Log().getLogger(f"PRINTER:{self.name}").error(f" failed to instantiate usb_host.Port({self.host_usb_dp}, {self.host_usb_dm})")
3231
return False
3332
Printer.setup(self, config)
3433
self.device_usb_vid = config.get('USB_VID')
3534
self.device_usb_pid = config.get('USB_PID')
3635
if self.device_usb_vid is None or self.device_usb_pid is None:
37-
print(f" ERROR: missing USB_VID and/or USB_PID definitions")
36+
Log().getLogger(f"PRINTER:{self.name}").error(f" missing USB_VID and/or USB_PID definitions")
3837
return False
39-
print(f" Connecting to USB printer '{self.device_usb_vid}:{self.device_usb_pid}'...")
38+
Log().getLogger(f"PRINTER:{self.name}").info(f" Connecting to USB printer '{self.device_usb_vid}:{self.device_usb_pid}'...")
4039
usb.core.find() # dummy enumeration because on RP2040 first enumeration always fails
4140
self.device = usb.core.find(idVendor=self.device_usb_vid, idProduct=self.device_usb_pid)
4241
if self.device is None:
43-
print(f" ...device '{self.device_usb_vid}:{self.device_usb_pid}' not found")
42+
Log().getLogger(f"PRINTER:{self.name}").warning(f" ...device '{self.device_usb_vid}:{self.device_usb_pid}' not found")
4443
return False
45-
print(f" ...connected to {self.device.idVendor:04x}:{self.device.idProduct:04x} {self.device.manufacturer} / {self.device.product} (#{self.device.serial_number})")
44+
Log().getLogger(f"PRINTER:{self.name}").info(f" ...connected to {self.device.idVendor:04x}:{self.device.idProduct:04x} {self.device.manufacturer} / {self.device.product} (#{self.device.serial_number})")
4645
self.device.set_configuration()
4746
return True
4847

49-
5048
def loop(self) -> bool:
5149
return True
5250

53-
5451
def write(self, data: bytearray) -> None:
5552
if self.device is not None:
5653
self.device.write(1, data)

src/app/services/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
21
class Service:
3-
debug: bool = False
42

5-
def __init__(self, debug: bool):
6-
self.debug = debug
3+
def __init__(self, name: str):
4+
self.name = name
75

8-
def setup(self, config: toml.Dotty, printers: dict) -> bool:
6+
def setup(self, config: dict, printers: dict) -> bool:
97
self.printers = printers
108
return True
119

0 commit comments

Comments
 (0)