Код: Выделить всё
async def send_packet(
self, packet: bytearray | list[tuple[bytearray, float | None]]
) -> None:
"""Send a packet to the device."""
if isinstance(packet, list):
for p, delay in packet:
if delay is not None:
await asyncio.sleep(delay)
p[:0] = PREFIX_HEADER
if (crc := calculate_crc(p)) is None:
continue
p.extend(crc)
p.extend(SUFFIX_HEADER)
if not verify_crc(p):
continue
queue = PacketQueue(packet=DoorPhonePacket(p))
self.packet_queue.put(queue)
else:
packet[:0] = PREFIX_HEADER
if (sum := calculate_checksum(packet)) is None:
return
packet.append(sum)
packet.extend(SUFFIX_HEADER)
if not verify_checksum(packet):
return
queue = PacketQueue(packet=KocomPacket(packet))
self.packet_queue.put(queue)
Код: Выделить всё
async def _handle_retry(self, queue: PacketQueue) -> None:
"""Handle command retry."""
if queue.retry >= self.max_retry:
_LOGGER.error(f"Command failed after {self.max_retry} retries: {queue.packet.packet.hex()}")
return
delay = self.retry_delays[queue.retry]
queue.packet.packet[3] = (queue.packet.packet[3] + 1) % 256
queue.retry += 1
_LOGGER.debug(f"Retrying command (attempt {queue.retry}): {queue.packet.packet.hex()}")
await asyncio.sleep(delay)
self.packet_queue.put(queue)
Код: Выделить всё
async def _process_queue(self) -> None:
"""Process packets in the queue."""
while True:
try:
if self.packet_queue.empty():
await asyncio.sleep(0.1)
continue
packet = self.packet_queue.get()
await asyncio.sleep(0.03)
await self.connection.send(packet.packet.packet)
if packet.ack:
self.packet_queue.task_done()
_LOGGER.debug(
f"Command successful: {packet.packet.packet.hex()} -> {packet.ack.packet.hex()}"
)
continue
else:
await self._handle_retry(packet)
except asyncio.CancelledError:
break
except Exception as e:
_LOGGER.error(f"Error processing queue: {e}", exc_info=True)
await asyncio.sleep(1)
Код: Выделить всё
async def _listen(self) -> None:
"""Listen for incoming packets."""
while True:
try:
if not self.connection.is_connected:
await asyncio.sleep(1)
continue
receive_data = await self.connection.receive()
if not receive_data:
continue
for packet in self.extract_packets(receive_data):
await self._process_packet(packet)
except asyncio.CancelledError:
break
except ValueError as ve:
invalid_value, enum_class_name = map(str.strip, ve.args[0].rsplit(' ', 1))
hex_value = f"0x{int(invalid_value):02X}"
_LOGGER.error(
"Invalid value '%s' (hex=%s) for Enum '%s'", invalid_value, hex_value, enum_class_name
)
await asyncio.sleep(1)
except Exception as e:
_LOGGER.error(f"Error receiving data: {e}", exc_info=True)
await asyncio.sleep(1)
async def _process_packet(self, packet: bytes) -> None:
"""Process a single packet."""
parser, log_message = None, None
if verify_checksum(packet):
parser, log_message = PacketParser, "Received packet"
elif verify_crc(packet):
parser, log_message = DoorPhoneParser, "Received door phone"
if parser:
parsed_packets = parser.parse_state(packet)
for parsed_packet in parsed_packets:
_LOGGER.debug(
f"{log_message}: {parsed_packet}, {parsed_packet._device}, {parsed_packet._last_data}"
)
if parsed_packet._device is None:
continue
for callback in self.device_callbacks:
try:
await callback(parsed_packet)
except Exception as e:
_LOGGER.error(f"Error in callback: {e}", exc_info=True)
if not self.packet_queue.empty():
_LOGGER.debug(f"Packet queue is available")
queue = self.packet_queue.get()
_LOGGER.debug(f"_process_packet - queue: {queue}")
if parsed_packet.value == queue.packet.value:
_LOGGER.debug(f"_process_packet - packet value match")
queue.ack = parsed_packet
_LOGGER.debug(f"_process_packet - queue: {queue}")
self.packet_queue.task_done()
2025-01-10 18:08:15.748 ОТЛАДКА (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Полученный пакет: KocomPacket(packet_type=RECV, последовательность=0xc, dest=0100, src=3b04, команда=0x0, значение= 0000000000000000, контрольная сумма=0x4c), Device(device_type=outlet, device_id=outlet_4, room_id=4, state={'power': False}, sub_id=0), {'outlet_1': {'ids': []}, 'outlet_2 ': {'ids': []}, 'outlet_4': {'ids': [0]}, 'outlet_0': {'ids': [0]}}
2025-01-10 18:08:15.834 DEBUG (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Повторная попытка команды (попытка 2): aa5530be003b0401000000000000000000002c0d0d
2025-01-10 18:08:15.878 ОТЛАДКА (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Полученный пакет: KocomPacket(packet_type=SEND, последовательность=0xc, dest=0100, src=3b04, команда=0x0, значение= 0000000000000000, контрольная сумма=0x2c), Device(device_type=outlet, device_id=outlet_4, room_id=4, state={'power': False}, sub_id=0), {'outlet_1': {'ids': []}, 'outlet_2 ': {'ids': []}, 'outlet_4': {'ids': [0]}, 'outlet_0': {'ids': [0]}}
2025-01-10 18:08:15.878 ОТЛАДКА (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Получен пакет: KocomPacket(packet_type=RECV, последовательность=0xc, dest=3b04, src=0100 , команда=0x0, значение = 0000000000000000, контрольная сумма = 0x4c), Устройство (device_type = розетка, device_id = outlet_4, room_id = 4, состояние = {'power': False}, sub_id = 0), {'outlet_1': {'ids': [] }, 'outlet_2': {'ids': []}, 'outlet_4': {'ids': [0]}, 'outlet_0': {'ids': [0]}}
2025-01-10 18:08:16.119 DEBUG (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Повторная попытка команды (попытка 3) : aa5530bf003b0401000000000000000000002c0d0d
2025-01-10 18:08:16.300 ОШИБКА (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Команда не выполнена после 3 попыток: aa5530bf003b0401000000000000000000002c0d0d
2025-01-10 18:08:17.341 DEBUG (MainThread) [custom_comComponents.kocom_wallpad.pywallpad] Полученный пакет: KocomPacket(packet_type=RECV, последовательность = 0xc, dest = 0100, src = 3b01, команда = 0x3a, значение = 0000000000000000, контрольная сумма = 0x83), нет, {'outlet_1': {'ids': []}, 'outlet_2': {'ids': []}, 'outlet_4': {'ids': [0]}, 'outlet_0': {'ids': [0]}}
..........
Как видно из журнала выше, PacketQueue уже настроен. и команды отправляются, поэтому оператор if в приведенном ниже коде должен быть выполнен и журнал должен отображаться нормально, но оператор if не выполняется.
Сначала я попробовал с помощью asyncio.queue, но это могло быть связано с проблемами времени, поэтому я изменил его на общую очередь, но симптомы все те же.
Код: Выделить всё
if not self.packet_queue.empty():
_LOGGER.debug(f"Packet queue is available")
queue = self.packet_queue.get()
_LOGGER.debug(f"_process_packet - queue: {queue}")
if parsed_packet.value == queue.packet.value:
_LOGGER.debug(f"_process_packet - packet value match")
queue.ack = parsed_packet
_LOGGER.debug(f"_process_packet - queue: {queue}")
self.packet_queue.task_done()
Подробнее здесь: https://stackoverflow.com/questions/793 ... te-to-true
Мобильная версия