master and slave over sdg_io
Project description
Cодержит классы SdgDevMaster и SdgDevAsync для обмена командами, через СКБ-шный интерфейс ввода/вывода. https://pypi.org/project/sdg-io/
SdgDevMaster
умеет только передавать команды, т.е. выполняет работу Главного устройства
.
SdgDevAsync
предназначен как для передачи так и для приема команд, т.е позволяет
организовать работу как Главного
так и Подчиненного устройства
.
Для работы SdgDevAsync создается поток, в котором выполняется переодическое
чтение данных из интерфейса ввода/вывода и их обработка на предмет получения команд.
Входящие команды должны быть заранее добавлены методом add_incmd()
с указанием кода команды,
форматом ожидаемых данных и callback функции, которой будет передано управление при
поступлении команды с нужным кодом и форматом данных.
Внимание
callback функция вызывается из внутреннего потока SdgDevAsync и не должна его
блокировать! Для безопасного обмена данными должны быть приняты меры!
SdgDevMaster
и SdgDevAsync
могут автоматически определять порт к которому подключено
подчиненное устройство. Для этого нужно:
- Переопределить функцию
check_id()
, которая будет запрашиватьуникальный идентификатор
уподчиненного
и при получении адекватного ответа, возвращать True. - Использовать ф-ю
search_port()
для поискаподчиненного
по всем доступным портам системы, или search_port(portlist) для поиска по заранее подготовленному списоку портов.
При необходимости подключить какой-то другой интерфейс ввода/вывода нужно
использовать классы DevMaster и DevAsync.
Интерфейс ввода/вывода должен иметь методы read/write
и вызывать
исключение IOError
при ошибках чтения/записи.
Формат обмена:
АА СС D0 D1 .. DX
- команда
AA CA D0 D1 .. DX
- ответ
АА
: адрес устройства. Возможна работа без адреса (точка -точка).СС
: код команды, любой в диапазоне 0x00 - 0x7F, кроме 0x70CA
: код ответа = код команды с установленным старшим битом 0x80 - 0xFF, кроме 0xF0D0-DX
: данные команды/ответа опционально. На широковещательные команды с адресомАА=0х00
ответ подчиненным(и) не выдается. Возможен ответ подчиненного с кодом0xF0
Недопустимая команда
это означает, что он не смог выполнить данныую команду. Формат такого ответа:AA 0xF0 CC EE
, гдеEE
- код ошибки выполнения. (см. class DevBadCode)
Пример использования (example.py):
from struct import pack
from sdg_utils import log_open
from sdg_dev import SdgDevMaster, DevException, SdgDevAsync
log = log_open()
class MyMaster(SdgDevMaster):
def __init__(self):
super().__init__(port='', log=log.getChild('mastr'))
def check_id(self):
return self.send(b'\x00', ackfrmt='H') == 0xAAAA
def send_val(self, val):
return self.send(b'\x31' + pack('I', val), ackfrmt='')
def request_val(self):
return self.send(b'\x32', ackfrmt='I', timeout=.1, remix=0)
class MySlave(SdgDevAsync):
def __init__(self, port):
super().__init__(port, log=log.getChild('slave'))
self.val = 0x04030201
self.ID = 0xAAAA
self.add_incmd(b'\x00', '', self._getid)
self.add_incmd(b'\x31', 'I', self._setval)
self.add_incmd(b'\x32', '', self._getval)
self.add_incmd(b'\x33', '', lambda: pack('BBBB', 5, 6, 7, 8))
def _setval(self, val):
self.val = val
return b''
def _getval(self):
return pack('I', self.val)
def _getid(self):
return pack('H', self.ID)
if __name__ == "__main__":
print('Порт для master-a будет определен автопоиском по всем доступным портам системы.')
PORT = input("Ведите название порта для slave-a или нажмите Enter(по умочанию 'COM26'):")
if not PORT:
PORT = 'COM26'
slave = MySlave(PORT)
master = MyMaster()
master.search_port()
try:
val = master.request_val()
log.info(f"request_val 0x{val:08x}")
log.info(f"send new val 0x01020304")
master.send_val(0x01020304)
val = master.request_val()
log.info(f"request_val 0x{val:08x}")
a, b, c, d = master.send(b'\x33', ackfrmt='BBBB')
log.info(f"{a}, {b}, {c}, {d}")
except DevException as e:
log.error(e)
master.close()
slave.close()
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.