Files
templates/python/set_devices/qt_ports/ump_can_client.py

70 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Последовательный клиент CAN-логгера поверх уже подключённого Dima-адаптера."""
import secrets
from .qt_compat import QObject, QTimer, Signal
from set_devices.ump_logger_can import Response, build_request
class UmpCanClient(QObject):
completed = Signal(str, object)
failed = Signal(str)
def __init__(self, send, parent=None):
super().__init__(parent)
self._send = send
self._token = secrets.randbelow(255) + 1
self._pending = None
self._operation = ''
self._timer = QTimer(self)
self._timer.setSingleShot(True)
self._timer.timeout.connect(self._timeout)
@property
def busy(self):
return self._pending is not None
def cancel(self):
# Поздний ответ после переключения транспорта не должен продолжить
# старую цепочку и отправить команду в новое подключение.
self._timer.stop()
self._pending = None
self._operation = ''
def request(self, operation, mode, function, address, value, timeout_ms=2000):
if self.busy:
self.failed.emit('CAN-логгер занят предыдущим запросом')
return
self._token = self._token % 255 + 1
try:
can_id, data = build_request(mode, self._token, function, address, value)
self._pending = Response(mode, self._token, function, address, value)
self._operation = operation
self._timer.start(timeout_ms)
self._send(can_id, data)
except (ValueError, RuntimeError, OSError) as error:
self.cancel()
self.failed.emit(str(error))
def receive(self, can_id, data):
if self._pending is None:
return
try:
words = self._pending.feed(can_id, data)
except ValueError as error:
self.cancel()
self.failed.emit(str(error))
return
if words is None:
return
operation = self._operation
self.cancel()
self.completed.emit(operation, words)
def _timeout(self):
writing = self._pending is not None and self._pending.function == 6
self.cancel()
text = ('Таймаут CAN-логгера: проверьте адаптер, скорость, номер платы '
'и прошивку с поддержкой CAN-логгера.')
if writing:
text += ' Подтверждение записи потеряно; команда могла выполниться.'
self.failed.emit(text)