moving to python logging infrastructure
This commit is contained in:
Родитель
6b8cbbf0cb
Коммит
1eeb00cf16
|
@ -4,6 +4,8 @@ from time import sleep
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
def main():
|
def main():
|
||||||
|
from logging import basicConfig, INFO
|
||||||
|
basicConfig(level=INFO)
|
||||||
bus = Bus()
|
bus = Bus()
|
||||||
led = LedClient(bus, "led")
|
led = LedClient(bus, "led")
|
||||||
led.brightness = 0.5
|
led.brightness = 0.5
|
||||||
|
@ -13,7 +15,7 @@ if __name__ == '__main__':
|
||||||
led.set_all((255, 0, 0))
|
led.set_all((255, 0, 0))
|
||||||
sleep(1)
|
sleep(1)
|
||||||
# off
|
# off
|
||||||
led.set_all((0,0,0))
|
led.set_all((0, 0, 0))
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from asyncio.tasks import Task
|
from asyncio.tasks import Task
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
from logging import getLogger, DEBUG, INFO, WARNING, ERROR, NOTSET
|
||||||
import threading
|
import threading
|
||||||
import asyncio
|
import asyncio
|
||||||
import queue
|
import queue
|
||||||
|
@ -24,7 +25,7 @@ from .unique_brain.constants import *
|
||||||
from .packet import *
|
from .packet import *
|
||||||
from .transport import Transport
|
from .transport import Transport
|
||||||
|
|
||||||
from .util import now, log, logv
|
from .util import now, info, debug
|
||||||
from .pack import PackTuple, PackType, jdpack, jdunpack
|
from .pack import PackTuple, PackType, jdpack, jdunpack
|
||||||
|
|
||||||
EV_CHANGE = "change"
|
EV_CHANGE = "change"
|
||||||
|
@ -158,7 +159,7 @@ class EventEmitter:
|
||||||
if logger:
|
if logger:
|
||||||
logger.report(priority, msg, *args)
|
logger.report(priority, msg, *args)
|
||||||
|
|
||||||
def log(self, text: str, *args: object):
|
def info(self, text: str, *args: object):
|
||||||
self._add_log_report(LoggerPriority.LOG, text, *args)
|
self._add_log_report(LoggerPriority.LOG, text, *args)
|
||||||
|
|
||||||
def warn(self, text: str, *args: object):
|
def warn(self, text: str, *args: object):
|
||||||
|
@ -180,18 +181,23 @@ def _service_matches(dev: 'Device', serv: bytearray):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def rand_u64():
|
def rand_u64():
|
||||||
return bytearray([getrandbits(8) for _ in range(8)])
|
return bytearray([getrandbits(8) for _ in range(8)])
|
||||||
|
|
||||||
|
|
||||||
def is_raspberrypi():
|
def is_raspberrypi():
|
||||||
# https://raspberrypi.stackexchange.com/questions/5100/detect-that-a-python-program-is-running-on-the-pi
|
# https://raspberrypi.stackexchange.com/questions/5100/detect-that-a-python-program-is-running-on-the-pi
|
||||||
try:
|
try:
|
||||||
from io import open
|
from io import open
|
||||||
with open('/sys/firmware/devicetree/base/model', 'r') as m:
|
with open('/sys/firmware/devicetree/base/model', 'r') as m:
|
||||||
if 'raspberry pi' in m.read().lower(): return True
|
if 'raspberry pi' in m.read().lower():
|
||||||
except Exception: pass
|
return True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Bus(EventEmitter):
|
class Bus(EventEmitter):
|
||||||
"""A Jacdac bus that managed devices, service client, registers."""
|
"""A Jacdac bus that managed devices, service client, registers."""
|
||||||
|
|
||||||
|
@ -245,7 +251,8 @@ class Bus(EventEmitter):
|
||||||
|
|
||||||
# merge .ctor configuration with files
|
# merge .ctor configuration with files
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
config.read(["./jacdac.ini", os.path.expanduser("~") + "/.jacdac/config.ini", "./setup.cfg"])
|
config.read(["./jacdac.ini", os.path.expanduser("~") +
|
||||||
|
"/.jacdac/config.ini", "./setup.cfg"])
|
||||||
if not config.has_section("jacdac"):
|
if not config.has_section("jacdac"):
|
||||||
cfg = config.add_section("jacdac")
|
cfg = config.add_section("jacdac")
|
||||||
cfg = config["jacdac"]
|
cfg = config["jacdac"]
|
||||||
|
@ -288,7 +295,7 @@ class Bus(EventEmitter):
|
||||||
self.transports.append(ExecTransport(self.transport_cmd))
|
self.transports.append(ExecTransport(self.transport_cmd))
|
||||||
if self.hf2_portname:
|
if self.hf2_portname:
|
||||||
from .transports.hf2 import HF2Transport
|
from .transports.hf2 import HF2Transport
|
||||||
self.transports.append(HF2Transport(self.hf2_portname))
|
self.transports.append(HF2Transport(self.hf2_portname))
|
||||||
if self.spi:
|
if self.spi:
|
||||||
from .transports.spi import SpiTransport
|
from .transports.spi import SpiTransport
|
||||||
self.transports.append(SpiTransport())
|
self.transports.append(SpiTransport())
|
||||||
|
@ -311,7 +318,7 @@ class Bus(EventEmitter):
|
||||||
|
|
||||||
self.process_thread.start()
|
self.process_thread.start()
|
||||||
|
|
||||||
print("starting jacdac, self device {}".format(self.self_device))
|
info("starting jacdac, self device {}".format(self.self_device))
|
||||||
|
|
||||||
def run(self, cb: Callable[..., None], *args: Any):
|
def run(self, cb: Callable[..., None], *args: Any):
|
||||||
if self.process_thread is threading.current_thread():
|
if self.process_thread is threading.current_thread():
|
||||||
|
@ -390,10 +397,10 @@ class Bus(EventEmitter):
|
||||||
while ptr < 12 + frame[2]:
|
while ptr < 12 + frame[2]:
|
||||||
sz = frame[ptr] + 4
|
sz = frame[ptr] + 4
|
||||||
pktbytes = frame[0:12] + frame[ptr:ptr+sz]
|
pktbytes = frame[0:12] + frame[ptr:ptr+sz]
|
||||||
# log("PKT: {}-{} / {}", ptr, len(frame), pktbytes.hex())
|
# info("PKT: {}-{} / {}", ptr, len(frame), pktbytes.hex())
|
||||||
pkt = JDPacket(frombytes=pktbytes, sender=sender)
|
pkt = JDPacket(frombytes=pktbytes, sender=sender)
|
||||||
if ptr > 12:
|
if ptr > 12:
|
||||||
pkt.requires_ack = False # only ack once
|
pkt.requires_ack = False # only ack once
|
||||||
self.process_packet(pkt)
|
self.process_packet(pkt)
|
||||||
# dispatch to other transports
|
# dispatch to other transports
|
||||||
self._queue_core(pkt)
|
self._queue_core(pkt)
|
||||||
|
@ -504,7 +511,7 @@ class Bus(EventEmitter):
|
||||||
break
|
break
|
||||||
|
|
||||||
def process_packet(self, pkt: JDPacket):
|
def process_packet(self, pkt: JDPacket):
|
||||||
logv("route: {}", pkt)
|
debug("route: {}", pkt)
|
||||||
dev_id = pkt.device_id
|
dev_id = pkt.device_id
|
||||||
multi_command_class = pkt.multicommand_class
|
multi_command_class = pkt.multicommand_class
|
||||||
service_index = pkt.service_index
|
service_index = pkt.service_index
|
||||||
|
@ -540,7 +547,7 @@ class Bus(EventEmitter):
|
||||||
elif dev_id == self.self_device.device_id and pkt.is_command:
|
elif dev_id == self.self_device.device_id and pkt.is_command:
|
||||||
h = self.servers[pkt.service_index]
|
h = self.servers[pkt.service_index]
|
||||||
if h:
|
if h:
|
||||||
# log(`handle pkt at ${h.name} cmd=${pkt.service_command}`)
|
# info(`handle pkt at ${h.name} cmd=${pkt.service_command}`)
|
||||||
h.handle_packet_outer(pkt)
|
h.handle_packet_outer(pkt)
|
||||||
else:
|
else:
|
||||||
if pkt.is_command:
|
if pkt.is_command:
|
||||||
|
@ -1011,7 +1018,7 @@ class ControlServer(Server):
|
||||||
self.auto_bind_cnt = 0
|
self.auto_bind_cnt = 0
|
||||||
|
|
||||||
def queue_announce(self):
|
def queue_announce(self):
|
||||||
logv("announce: %d " % self.restart_counter)
|
debug("announce: %d " % self.restart_counter)
|
||||||
self.restart_counter += 1
|
self.restart_counter += 1
|
||||||
ids = [s.service_class for s in self.bus. servers]
|
ids = [s.service_class for s in self.bus. servers]
|
||||||
rest = self.restart_counter
|
rest = self.restart_counter
|
||||||
|
@ -1109,7 +1116,8 @@ class LoggerServer(Server):
|
||||||
|
|
||||||
def report(self, priority: int, msg: str, *args: object):
|
def report(self, priority: int, msg: str, *args: object):
|
||||||
if priority >= self.min_priority:
|
if priority >= self.min_priority:
|
||||||
log(msg, *args)
|
info(msg, *args)
|
||||||
|
|
||||||
cmd: int = -1
|
cmd: int = -1
|
||||||
if priority == LoggerPriority.DEBUG:
|
if priority == LoggerPriority.DEBUG:
|
||||||
cmd = JD_LOGGER_CMD_DEBUG
|
cmd = JD_LOGGER_CMD_DEBUG
|
||||||
|
@ -1117,7 +1125,7 @@ class LoggerServer(Server):
|
||||||
cmd = JD_LOGGER_CMD_LOG
|
cmd = JD_LOGGER_CMD_LOG
|
||||||
elif priority == LoggerPriority.WARNING:
|
elif priority == LoggerPriority.WARNING:
|
||||||
cmd = JD_LOGGER_CMD_WARN
|
cmd = JD_LOGGER_CMD_WARN
|
||||||
elif priority == JD_LOGGER_CMD_ERROR:
|
elif priority == JD_LOGGER_CMD_ERROR:
|
||||||
cmd = JD_LOGGER_CMD_ERROR
|
cmd = JD_LOGGER_CMD_ERROR
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
@ -1781,10 +1789,11 @@ class Device(EventEmitter):
|
||||||
for c in self.clients:
|
for c in self.clients:
|
||||||
if (c.broadcast and c.service_class == service_class) or \
|
if (c.broadcast and c.service_class == service_class) or \
|
||||||
(not c.broadcast and c.service_index == pkt.service_index):
|
(not c.broadcast and c.service_index == pkt.service_index):
|
||||||
# log(`handle pkt at ${client.role} rep=${pkt.serviceCommand}`)
|
# info(`handle pkt at ${client.role} rep=${pkt.serviceCommand}`)
|
||||||
c.device = self
|
c.device = self
|
||||||
c.handle_packet_outer(pkt)
|
c.handle_packet_outer(pkt)
|
||||||
|
|
||||||
|
|
||||||
class BufferClient(Client):
|
class BufferClient(Client):
|
||||||
_value: bytearray
|
_value: bytearray
|
||||||
_dirty: bool
|
_dirty: bool
|
||||||
|
@ -1792,12 +1801,13 @@ class BufferClient(Client):
|
||||||
"""
|
"""
|
||||||
A client that handles a double-buffer bytes buffer
|
A client that handles a double-buffer bytes buffer
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, bus: Bus, service_class: int, pack_formats: Dict[int, str], role: str) -> None:
|
def __init__(self, bus: Bus, service_class: int, pack_formats: Dict[int, str], role: str) -> None:
|
||||||
super().__init__(bus, service_class, pack_formats, role)
|
super().__init__(bus, service_class, pack_formats, role)
|
||||||
|
|
||||||
self._value = bytearray(0)
|
self._value = bytearray(0)
|
||||||
self._dirty = False
|
self._dirty = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> bytearray:
|
def value(self) -> bytearray:
|
||||||
"""
|
"""
|
||||||
|
@ -1816,10 +1826,10 @@ class BufferClient(Client):
|
||||||
@property
|
@property
|
||||||
def dirty(self) -> bool:
|
def dirty(self) -> bool:
|
||||||
return self._dirty
|
return self._dirty
|
||||||
|
|
||||||
def set_dirty(self) -> None:
|
def set_dirty(self) -> None:
|
||||||
self._dirty = True
|
self._dirty = True
|
||||||
|
|
||||||
def refresh_value(self) -> None:
|
def refresh_value(self) -> None:
|
||||||
if self._dirty:
|
if self._dirty:
|
||||||
self.register(JD_REG_VALUE).set_values(self._value)
|
self.register(JD_REG_VALUE).set_values(self._value)
|
||||||
|
@ -1833,7 +1843,5 @@ class BufferClient(Client):
|
||||||
self._value = self._value + bytearray(length - l)
|
self._value = self._value + bytearray(length - l)
|
||||||
self._dirty = True
|
self._dirty = True
|
||||||
else:
|
else:
|
||||||
self._value = self._value[0:length -1]
|
self._value = self._value[0:length - 1]
|
||||||
self._dirty = True
|
self._dirty = True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from typing import List, Optional
|
||||||
from time import sleep, monotonic
|
from time import sleep, monotonic
|
||||||
from tokenize import Number
|
from tokenize import Number
|
||||||
from jacdac.transport import Transport
|
from jacdac.transport import Transport
|
||||||
from jacdac.util import buf2hex, hex2buf, now
|
from jacdac.util import buf2hex, hex2buf, debug, now
|
||||||
from gpiod import Chip, Line, LineBulk, LINE_REQ_EV_RISING_EDGE, LINE_REQ_FLAG_ACTIVE_LOW, LINE_REQ_DIR_OUT # type: ignore
|
from gpiod import Chip, Line, LineBulk, LINE_REQ_EV_RISING_EDGE, LINE_REQ_FLAG_ACTIVE_LOW, LINE_REQ_DIR_OUT # type: ignore
|
||||||
from spidev import SpiDev # type: ignore
|
from spidev import SpiDev # type: ignore
|
||||||
from weakref import finalize
|
from weakref import finalize
|
||||||
|
@ -45,7 +45,7 @@ class SpiTransport(Transport):
|
||||||
self.logger.debug("spi: select chip")
|
self.logger.debug("spi: select chip")
|
||||||
self.chip = Chip(RPI_CHIP)
|
self.chip = Chip(RPI_CHIP)
|
||||||
# monitor rx,tx in bulk
|
# monitor rx,tx in bulk
|
||||||
print("spi: request rx,tx")
|
debug("spi: request rx,tx")
|
||||||
self.rxtx = self.chip.get_lines([RPI_PIN_RX_READY, RPI_PIN_TX_READY])
|
self.rxtx = self.chip.get_lines([RPI_PIN_RX_READY, RPI_PIN_TX_READY])
|
||||||
self.rxtx.request(consumer = CONSUMER, type = LINE_REQ_EV_RISING_EDGE)
|
self.rxtx.request(consumer = CONSUMER, type = LINE_REQ_EV_RISING_EDGE)
|
||||||
self._flip_reset()
|
self._flip_reset()
|
||||||
|
@ -67,14 +67,14 @@ class SpiTransport(Transport):
|
||||||
chip.close()
|
chip.close()
|
||||||
#print("spi: chip closed")
|
#print("spi: chip closed")
|
||||||
except:
|
except:
|
||||||
print("error: chip failed to close")
|
debug("error: chip failed to close")
|
||||||
|
|
||||||
if not spi is None:
|
if not spi is None:
|
||||||
try:
|
try:
|
||||||
spi.close()
|
spi.close()
|
||||||
print("spi: device closed")
|
debug("spi: device closed")
|
||||||
except:
|
except:
|
||||||
print("error: device failed to close")
|
debug("error: device failed to close")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.logger.debug("spi: close")
|
self.logger.debug("spi: close")
|
||||||
|
@ -101,7 +101,7 @@ class SpiTransport(Transport):
|
||||||
rst.release()
|
rst.release()
|
||||||
|
|
||||||
def send(self, pkt: bytes) -> None:
|
def send(self, pkt: bytes) -> None:
|
||||||
#print("JD %d %s TX" % (millis(), buf2hex(pkt)))
|
#debug("JD %d %s TX" % (millis(), buf2hex(pkt)))
|
||||||
self.sendQueue.append(pkt)
|
self.sendQueue.append(pkt)
|
||||||
self._poke()
|
self._poke()
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class SpiTransport(Transport):
|
||||||
if not sendtx and not rxReady:
|
if not sendtx and not rxReady:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# print("spi: transfer rx:" + str(rx) + ", tx: " + str(tx) + ", queue: " + str(len(self.sendQueue)))
|
# debug("spi: transfer rx:" + str(rx) + ", tx: " + str(tx) + ", queue: " + str(len(self.sendQueue)))
|
||||||
|
|
||||||
# allocate transfer buffers
|
# allocate transfer buffers
|
||||||
txqueue = bytearray(XFER_SIZE)
|
txqueue = bytearray(XFER_SIZE)
|
||||||
|
@ -179,18 +179,18 @@ class SpiTransport(Transport):
|
||||||
rxqueue = bytearray(self.spi.xfer2(txqueue))
|
rxqueue = bytearray(self.spi.xfer2(txqueue))
|
||||||
|
|
||||||
if rxqueue is None:
|
if rxqueue is None:
|
||||||
print("spi: recv failed")
|
debug("spi: recv failed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
framep = 0
|
framep = 0
|
||||||
while framep + 4 < len(rxqueue):
|
while framep + 4 < len(rxqueue):
|
||||||
frame2 = rxqueue[framep + 2]
|
frame2 = rxqueue[framep + 2]
|
||||||
if frame2 == 0:
|
if frame2 == 0:
|
||||||
# print("spi: empty frame")
|
# debug("spi: empty frame")
|
||||||
break
|
break
|
||||||
sz = frame2 + 12
|
sz = frame2 + 12
|
||||||
if framep + sz > len(rxqueue):
|
if framep + sz > len(rxqueue):
|
||||||
self.logger.debug("spi: frame size out of range")
|
debug("spi: frame size out of range")
|
||||||
break
|
break
|
||||||
frame0 = rxqueue[framep]
|
frame0 = rxqueue[framep]
|
||||||
frame1 = rxqueue[framep + 1]
|
frame1 = rxqueue[framep + 1]
|
||||||
|
@ -200,7 +200,7 @@ class SpiTransport(Transport):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
buf = bytearray(rxqueue[framep:framep+sz])
|
buf = bytearray(rxqueue[framep:framep+sz])
|
||||||
#print("JD %d %s RX" % (millis(), buf2hex(buf)))
|
#debug("JD %d %s RX" % (millis(), buf2hex(buf)))
|
||||||
if buf and self.on_receive:
|
if buf and self.on_receive:
|
||||||
self.on_receive(buf)
|
self.on_receive(buf)
|
||||||
sz = (sz + 3) & ~3
|
sz = (sz + 3) & ~3
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import binascii
|
import binascii
|
||||||
|
from logging import getLogger
|
||||||
import time
|
import time
|
||||||
from typing import List, Tuple, Union, cast
|
from typing import List, Tuple, Union, cast
|
||||||
|
|
||||||
logging = True
|
|
||||||
loggingv = False
|
|
||||||
_hex = "0123456789abcdef"
|
_hex = "0123456789abcdef"
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,18 +10,19 @@ def now():
|
||||||
return int(time.monotonic() * 1000)
|
return int(time.monotonic() * 1000)
|
||||||
|
|
||||||
|
|
||||||
def log(msg: str, *args: object):
|
logger = getLogger(__name__)
|
||||||
if logging:
|
|
||||||
if len(args):
|
|
||||||
msg = msg.format(*args)
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def logv(msg: str, *args: object):
|
def info(msg: str, *args: object):
|
||||||
if loggingv:
|
if len(args):
|
||||||
if len(args):
|
msg = msg.format(*args)
|
||||||
msg = msg.format(*args)
|
logger.info(msg)
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
def debug(msg: str, *args: object):
|
||||||
|
if len(args):
|
||||||
|
msg = msg.format(*args)
|
||||||
|
logger.debug(msg)
|
||||||
|
|
||||||
|
|
||||||
def hex_num(n: int, len: int = 8):
|
def hex_num(n: int, len: int = 8):
|
||||||
|
@ -106,7 +106,7 @@ def crc16(buf: bytes, start: int = 0, end: int = None):
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
|
|
||||||
def color_to_rgb(rgb: Union[int, Tuple[int, int, int], List[int]], default = (0,0,0)) -> Tuple[int, int, int]:
|
def color_to_rgb(rgb: Union[int, Tuple[int, int, int], List[int]], default=(0, 0, 0)) -> Tuple[int, int, int]:
|
||||||
"""
|
"""
|
||||||
Maps various format to a r,g,b tuple
|
Maps various format to a r,g,b tuple
|
||||||
"""
|
"""
|
||||||
|
@ -127,4 +127,4 @@ def color_to_rgb(rgb: Union[int, Tuple[int, int, int], List[int]], default = (0,
|
||||||
r = (lrgb[0]) & 0xff
|
r = (lrgb[0]) & 0xff
|
||||||
g = (lrgb[1]) & 0xff
|
g = (lrgb[1]) & 0xff
|
||||||
b = (lrgb[2]) & 0xff
|
b = (lrgb[2]) & 0xff
|
||||||
return (r,g,b)
|
return (r, g, b)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче