diff --git a/components/actor/heater_hendi.py b/components/actor/heater_hendi.py index efdfdad..fd8b206 100755 --- a/components/actor/heater_hendi.py +++ b/components/actor/heater_hendi.py @@ -45,7 +45,7 @@ class HeaterHendi(AHeater): # tick loop (with self.device.open(): activate(True)/(False)) and # from a client's Connect/Disconnect command, neither of which # expect activate() itself to ever raise. - print(f"HeaterHendi: comm error in activate({enable}): {e}") + self.log.error(f"comm error in activate({enable}): {e}") self.disconnect() def is_activated(self): @@ -55,7 +55,7 @@ class HeaterHendi(AHeater): s = self.hendi.isRemoteEnable() return '1' in s except Exception as e: - print(f"HeaterHendi: comm error in is_activated: {e}") + self.log.error(f"comm error in is_activated: {e}") self.disconnect() return False @@ -72,7 +72,7 @@ class HeaterHendi(AHeater): self.hendi.setPowerWatts(power) self.power_eff = self.hendi.getPowerWatts() if power > 0 else 0 except Exception as e: - print(f"HeaterHendi: comm error in process: {e}") + self.log.error(f"comm error in process: {e}") self.disconnect() self.power_eff = 0 diff --git a/components/actor/hendiCtrl.py b/components/actor/hendiCtrl.py index afec45a..1b46ac8 100755 --- a/components/actor/hendiCtrl.py +++ b/components/actor/hendiCtrl.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 +import logging import time import serial import sys @@ -11,6 +12,7 @@ class HendiException(Exception): class HendiCtrl: def __init__(self, port, speed, debug=False): + self.log = logging.getLogger(type(self).__name__) self.debug = debug self.prompt = b':' self.sw_id = None @@ -48,7 +50,7 @@ class HendiCtrl: try: self.ser.open() except serial.SerialException as e: - print(f"HendiCtrl: connect failed: {e}") + self.log.error(f"connect failed: {e}") return False # The port itself is what "connected" means - a failed version query # (e.g. the device sitting in its ungraceful-disconnect lockout, see @@ -57,9 +59,9 @@ class HendiCtrl: try: self.sw_id = self.getSoftwareIdentifier() self.sw_ver = self.getSoftwareVersion() - print(f"{self.sw_id}, F/W-Version: {self.sw_ver}") + self.log.info(f"{self.sw_id}, F/W-Version: {self.sw_ver}") except HendiException: - print("HendiCtrl: Hendi not found") + self.log.warning("Hendi not found") return True @contextmanager @@ -91,7 +93,7 @@ class HendiCtrl: self.ser.rts = True def firmware_update(self, filename): - print("Start firmware update") + self.log.info("Start firmware update") self.enter_bootloader() self.ser.readline() @@ -122,7 +124,7 @@ class HendiCtrl: self.ser.flushInput() data = s.encode() if self.debug: - print(f"HendiCtrl: -> {data!r}") + self.log.debug(f"-> {data!r}") self.ser.write(data + b'\r') def __read(self): @@ -132,7 +134,7 @@ class HendiCtrl: # Read answer line answer_raw = self.ser.readline() if self.debug: - print(f"HendiCtrl: <- echo={echo!r} answer={answer_raw!r}") + self.log.debug(f"<- echo={echo!r} answer={answer_raw!r}") answer = answer_raw.decode('utf-8').replace('\r', '').replace('\n', '') if ':' in answer: result = answer.split(':') diff --git a/components/actor/pololu1376.py b/components/actor/pololu1376.py index 8d0669a..925119b 100644 --- a/components/actor/pololu1376.py +++ b/components/actor/pololu1376.py @@ -1,3 +1,4 @@ +import logging import time import serial import enum @@ -68,6 +69,7 @@ class StatusError(enum.IntFlag): class Pololu1376: def __init__(self, serial_port): + self.log = logging.getLogger(type(self).__name__) # Deferred-open pyserial idiom: serial_port is constructed with no # port set (see components/actor/stirrerpololu1376.py), so it isn't # actually opened until connect() is called - a missing/unplugged @@ -88,7 +90,7 @@ class Pololu1376: self.ser.close() self.ser.open() except serial.SerialException as e: - print(f"Pololu1376: connect failed: {e}") + self.log.error(f"connect failed: {e}") return False # set_output_flow_control() requires the port to already be open - # can only happen here, after open() above, not at construction time. @@ -96,10 +98,10 @@ class Pololu1376: try: self.stop() self.firmware_version = self.get_firmware_version() - print("Pololu1376 F/W-Version:", self.firmware_version) + self.log.info("F/W-Version: {}".format(self.firmware_version)) return True except Exception as e: - print(f"Pololu1376: connect failed: {e}") + self.log.error(f"connect failed: {e}") self.ser.close() self.firmware_version = None return False @@ -142,7 +144,7 @@ class Pololu1376: rsp = self.cmd("GO") errors = self.get_status_errors() if errors: - print(f"Pololu1376: ERROR - still in fail-safe after GO, active errors: {errors!r}") + self.log.error(f"still in fail-safe after GO, active errors: {errors!r}") return rsp def stop(self): diff --git a/components/actor/stirrerpololu1376.py b/components/actor/stirrerpololu1376.py index 39e5d9b..e4f16fe 100644 --- a/components/actor/stirrerpololu1376.py +++ b/components/actor/stirrerpololu1376.py @@ -46,7 +46,7 @@ class StirrerPololu1376(AStirrer): if not self.connected: return try: - print("activate {}".format(enable)) + self.log.debug("activate {}".format(enable)) if enable: self.drv.go() else: @@ -58,7 +58,7 @@ class StirrerPololu1376(AStirrer): # loop (with self.device.open(): activate(True)/(False)) and # from a client's Connect/Disconnect command, neither of which # expect activate() itself to ever raise. - print(f"StirrerPololu1376: comm error in activate({enable}): {e}") + self.log.error(f"comm error in activate({enable}): {e}") self.disconnect() def _on_set_speed(self, speed): @@ -66,9 +66,9 @@ class StirrerPololu1376(AStirrer): return try: self.drv.motor_forward(speed) - print("Set speed to {} %".format(speed)) + self.log.debug("Set speed to {} %".format(speed)) except Exception as e: - print(f"StirrerPololu1376: comm error in _on_set_speed: {e}") + self.log.error(f"comm error in _on_set_speed: {e}") self.disconnect() def _on_process(self): @@ -77,12 +77,12 @@ class StirrerPololu1376(AStirrer): try: errors = self.drv.get_status_errors() if errors: - print(f"StirrerPololu1376: motor controller reports errors: {errors!r}") + self.log.warning(f"motor controller reports errors: {errors!r}") if StatusError.SAFE_START_VIOLATION in errors: - print("Recover after safe start violation!") + self.log.warning("Recover after safe start violation!") self.drv.go() except Exception as e: - print(f"StirrerPololu1376: comm error in _on_process: {e}") + self.log.error(f"comm error in _on_process: {e}") self.disconnect() diff --git a/components/sensor/tempSensor_max31865.py b/components/sensor/tempSensor_max31865.py index eecf98b..1c3ba03 100755 --- a/components/sensor/tempSensor_max31865.py +++ b/components/sensor/tempSensor_max31865.py @@ -25,7 +25,7 @@ class TempSensor_max31865(ATemperatureSensor): # temperature()'s own except handler already retries via # reopen() on the next tick, same recovery path as a later # runtime failure. - print(f"TempSensor_max31865: could not open SPI at startup: {e}") + self.log.error(f"could not open SPI at startup: {e}") def _open_spi(self): self.spi.open(0, 0) @@ -56,7 +56,7 @@ class TempSensor_max31865(ATemperatureSensor): try: self._open_spi() except Exception as e: - print(f"TempSensor_max31865: reopen failed: {e}") + self.log.error(f"reopen failed: {e}") def read_reg(self, addr): reg = self.spi.xfer([addr, 0xFF]) @@ -98,7 +98,7 @@ class TempSensor_max31865(ATemperatureSensor): # nothing restarts a dead ATask). reopen() gives the SPI bus a # chance to recover from a wedged state without a full process/ # Pi reboot - see docs/pi_deployment_notes.md. - print(f"TempSensor_max31865: comm error reading sensor, reopening SPI: {e}") + self.log.error(f"comm error reading sensor, reopening SPI: {e}") self.reopen() return self.temp diff --git a/server/brewpi.py b/server/brewpi.py index 6bb79a2..e7d1066 100755 --- a/server/brewpi.py +++ b/server/brewpi.py @@ -2,6 +2,7 @@ import asyncio import functools import json +import logging import os import signal import sys @@ -20,20 +21,23 @@ from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, Stir import argparse as ap +log = logging.getLogger('brewpi') + class Tee: """Duplicates writes to multiple streams - used to mirror stdout/stderr - (everything the rest of the codebase already reaches via print()) into - a log file under logs/ as well as the console, without having to touch - every print() call site. + into a log file under logs/ as well as the console, without every + writer needing to know about either. - Also stamps every line with a "T