Browse Source

backend: Fix issue with to long log messages

ble
Andreas Berthoud 4 years ago
parent
commit
c35387f887
  1. 161
      backend/monsun_backend/command_execution.py

161
backend/monsun_backend/command_execution.py

@ -94,6 +94,9 @@ def enter_fsm(
responses_received: List[Response] = list() responses_received: List[Response] = list()
time_at_beginning_waiting_for_response: float = 0.0 time_at_beginning_waiting_for_response: float = 0.0
last_heart_beat_time: float = 0.0 last_heart_beat_time: float = 0.0
serial_receiver = SerialReceiver(
root_logger=root_logger,
)
while True: while True:
if state == State.heart_beat: if state == State.heart_beat:
@ -129,8 +132,7 @@ def enter_fsm(
) )
else: else:
request: Request = current_command request: Request = current_command
commands_, responses = receive( commands_, responses = serial_receiver.receive(
root_logger=root_logger,
serial=serial, serial=serial,
) )
responses_received.extend(responses) responses_received.extend(responses)
@ -165,8 +167,7 @@ def enter_fsm(
continue continue
elif state == State.receiving_command: elif state == State.receiving_command:
commands_, responses = receive( commands_, responses = serial_receiver.receive(
root_logger=root_logger,
serial=serial, serial=serial,
) )
responses_received.extend(responses) responses_received.extend(responses)
@ -201,70 +202,140 @@ def enqueue_command(
_command_queue[role].put(command) _command_queue[role].put(command)
def receive( class CommandInterpretationError(Exception):
root_logger: logging.Logger, """Raised in case the command could not be interpreted"""
serial: Serial,
) -> Tuple[Sequence[Command], Sequence[Response]]:
logger = root_logger.getChild("receive_and_log")
logger.setLevel(logging.INFO)
commands_received: List[Command] = list()
responses_received: List[Response] = list()
header_size = 4
bytes_read = serial.read(serial.in_waiting)
while bytes_read: class CommandBytesReadInsufficient(CommandInterpretationError):
"""Raised in case the command could not be interpreted"""
class CommandInterpreter:
header_size = 4
logger.debug(f"bytes: {bytes_read.hex()}") def __init__(
self,
root_logger: logging.Logger,
) -> None:
self._logger = root_logger.getChild(self.__class__.__name__)
self._logger.setLevel(logging.INFO)
self.command_id_int = 0
self.data_length = 0
self.payload = bytes()
def interpret(
self,
bytes_read: bytes,
) -> bytes:
"""Interpret the first command in a byte stream.
:param bytes_read: The bytes which are not yet parsed.
:returns: The byte which are not yet parsed.
:raises CommandInterpretationError: If the command could not be parsed.
:raises CommandBytesReadInsufficient: Not enough bytes to fully parse the
command.
"""
self._logger.debug(f"bytes: {bytes_read.hex()}")
try: try:
command_id_int, data_length, _ = unpack(">BHB", bytes_read[:header_size]) self.command_id_int, self.data_length, _ = unpack(
">BHB",
bytes_read[: self.header_size],
)
except error: except error:
logger.error("error while interpreting command header") self._logger.error("error while interpreting command header")
bytes_read = None raise CommandBytesReadInsufficient()
continue
try: try:
payload = bytes(bytes_read[header_size : header_size + data_length]) self.payload = bytes(
stop_byte = bytes_read[header_size + data_length] bytes_read[self.header_size : self.header_size + self.data_length],
)
except IndexError: except IndexError:
# okay, something went wrong. self._logger.error(
logger.error(
"There are less bytes than expected: " "There are less bytes than expected: "
f"Expected={header_size + data_length -1}, " f"Expected={self.header_size + self.data_length -1}, "
f"received={len(bytes_read)}", f"received={len(bytes_read)}",
) )
logger.debug(f"bytes: {bytes_read.hex()}") self._logger.debug(f"bytes: {bytes_read.hex()}")
bytes_read = None raise CommandBytesReadInsufficient()
continue
try: try:
command_id = CommandId(command_id_int) stop_byte = bytes_read[self.header_size + self.data_length]
except ValueError: except IndexError:
logger.error( self._logger.error("could not get stop byte")
f"invalid command {command_id_int} with payload {str(payload)}", raise CommandBytesReadInsufficient()
)
bytes_read = bytes_read[header_size + data_length + 1 :]
continue
logger.debug(f"stop_byte: {stop_byte}")
if stop_byte != 0xFF: if stop_byte != 0xFF:
logger.error("Invalid stop byte") self._logger.error("Invalid stop byte")
bytes_read = None raise CommandInterpretationError()
else:
bytes_read = bytes_read[header_size + data_length + 1 :] try:
return bytes_read[self.header_size + self.data_length + 1 :]
except IndexError:
return bytes()
class SerialReceiver:
def __init__(
self,
root_logger: logging.Logger,
) -> None:
self.root_logger = root_logger
self._logger = root_logger.getChild(self.__class__.__name__)
self._logger.setLevel(logging.INFO)
self._bytes_unread = bytearray()
def receive(
self,
serial: Serial,
) -> Tuple[Sequence[Command], Sequence[Response]]:
commands_received: List[Command] = list()
responses_received: List[Response] = list()
self._bytes_unread.extend(serial.read(serial.in_waiting))
while self._bytes_unread:
try:
command_interpreter = CommandInterpreter(
root_logger=self.root_logger,
)
self._bytes_unread = bytearray(
command_interpreter.interpret(
bytes_read=self._bytes_unread,
),
)
# except CommandBytesReadInsufficient:
# return commands_received, responses_received
except CommandInterpretationError:
return commands_received, responses_received
try:
command_id = CommandId(command_interpreter.command_id_int)
except ValueError:
self._logger.error(
f"invalid command {command_interpreter.command_id_int} with "
f"payload {str(command_interpreter.payload)}",
)
if command_id == CommandId.command_log: if command_id == CommandId.command_log:
command = commands.LogCommand( command = commands.LogCommand(
root_logger=root_logger, root_logger=self.root_logger,
data=payload, data=command_interpreter.payload,
) )
commands_received.append(command) commands_received.append(command)
elif command_id == CommandId.command_heartbeat_response: elif command_id == CommandId.command_heartbeat_response:
responses_received.append(commands.HeartbeatResponse(payload)) responses_received.append(
commands.HeartbeatResponse(command_interpreter.payload),
)
elif command_id == CommandId.command_led_response: elif command_id == CommandId.command_led_response:
responses_received.append(commands.LEDResponse(payload)) responses_received.append(
commands.LEDResponse(command_interpreter.payload),
)
elif command_id == CommandId.command_gp_response: elif command_id == CommandId.command_gp_response:
responses_received.append(commands.GPResponse(payload)) responses_received.append(
commands.GPResponse(command_interpreter.payload),
)
else: else:
raise RuntimeError raise RuntimeError

Loading…
Cancel
Save