Есть куча всякой периферии. Общение идет по CAN, RS232/UART, RS422/485, TCP, UDP и тп. Протоколы обычно совсем разные, но иногда — схожие, отличающиеся только нюансами способа передачи. Бывает peer-2-peer, бывает один-ко-многим. Один-ко-многим подразумевает мастера, слейвы только отвечают. Если peer-2-peer, или, как в CAN — коллизии разруливаются аппаратно — тогда слейвы могут асинхронно генерить сообщения.
Да, у протоколов может быть, а может не быть — адресация. Там, где транспорт обязывает иметь адрес для каждого пакета CAN/UDP, протокол пользуется средствами транспорта. Если это что-то типа RS232/UART, RS422/485, то адрес добавляется в посылку данных. peer-2-peer соединения могут быть установлены с использованием адреса один раз, и далее какая-либо адресация пропадает. Или не пропадает.
Хочется как-то более менее универсально описать всё это так, чтобы для добавления нового протокола (или способа использования существующего поверх другого транспорта) нужно было бы дописать самую малость — чтобы как из кубиков составлялось — просто заменил парочку и всё работает. Ну, и хочется, чтобы ранее написанный код от такой подмены не переставал работать, а без вопросов переехал бы на новый протокол/транспорт.
В принципе, кое-какие мысли есть, но буду рад всем идеям.
Пока затык вот такой сейчас. Как бы задание адреса сделать? Варианты примерно такие (терминологию/имена взял из API сокетов) sendTo, recvFrom и адрес куда/откуда send, recv — без адреса sendTo, recvFrom и опциональный адрес
адрес отправки и адрес, откуда пришло — задавать/получать условно перед/после отправкой/приемом через опции сокета
UPD — в перечисленных случаях подразумевалось, что полезная нагрузка — сообщение — передается туда-сюда как набор байтов. Есть еще вариант оперировать объектами Message, предоставляющими интерфейс IMessage, который в себе инкапсулирует и адрес и данные, и черта в ступе по желанию. Но это как-то не очень удобно начинает получаться, на мой взгляд
UPD2 — адрес можно передавать вместе с данными — байтовый массив — префикс длинной N, где N зафисит от конкретного протокола
еще варианты?
В целом, конечно, предлагаю обсудить не только описанный нюанс, но и вообще подобную архитектуру в комплексе
UPD По поводу адресов. Обычно это однобайтные значения. Но, если транспортом будет UDP, там уже как минимум 4х-байтный IPv4, а вообще адрес может быть произвольного размера. И тут не совсем понятно, то ли делать как в сокетах — гибко, но неудобно, то ли использовать только 32битное целое и считать, что его хватит всем, то ли совместить оба подхода перегрузками.
Здравствуйте, abrec, Вы писали:
У>>Здравствуйте!
A>Адаптеры в виде микросервисов с реализацией нюансов обмена. далее из них более-менее стандартизованный протокол в процессинг.
Ну да, как-то так, в общих чертах, я и планирую. Но интересно больше деталей )
И вот только как адреса вкорячить поудобнее — пока не придумал
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте, abrec, Вы писали:
У>>>Здравствуйте!
A>>Адаптеры в виде микросервисов с реализацией нюансов обмена. далее из них более-менее стандартизованный протокол в процессинг.
У>Ну да, как-то так, в общих чертах, я и планирую. Но интересно больше деталей ) У>И вот только как адреса вкорячить поудобнее — пока не придумал
Смотря какой уровень абстракции Вам нужен.В общем напрашивается два уровня: как уже сказали сервисы и то что под ними, хотя сервисов может и не быть. Вариантом может быть много, в общем виде у нас идет обмен сообщениями. Может подойти патерн "Шаблонный метод" у каждого класса протокола свой метод отправки сообщений.
Здравствуйте, удусекшл, Вы писали:
У>UPD По поводу адресов. Обычно это однобайтные значения. Но, если транспортом будет UDP, там уже как минимум 4х-байтный IPv4, а вообще адрес может быть произвольного размера. И тут не совсем понятно, то ли делать как в сокетах — гибко, но неудобно, то ли использовать только 32битное целое и считать, что его хватит всем, то ли совместить оба подхода перегрузками.
Под IPv6 32-битного числа не хватит. И под IPv4, если адрес включает номер порта, его тоже не хватит.
Сокеты сделаны очень хорошо, любой существующий протокол в них более-менее укладывается. Я бы от них отталкивался.
Другой вариант — это сделать, как в Plan9/Go: адрес в програмном интерфейсе — это просто строка, а преобразование его в "проводной" формат — это личное дело системы.
Здравствуйте, удусекшл, Вы писали:
У>UPD По поводу адресов. Обычно это однобайтные значения. Но, если транспортом будет UDP, там уже как минимум 4х-байтный IPv4, а вообще адрес может быть произвольного размера. И тут не совсем понятно, то ли делать как в сокетах — гибко, но неудобно, то ли использовать только 32битное целое и считать, что его хватит всем, то ли совместить оба подхода перегрузками.
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте!
У>Есть куча всякой периферии. Общение идет по CAN, RS232/UART, RS422/485, TCP, UDP и тп.
Думаю, плясать надо от вопроса "Для чего общаемся с периферией?". Например:
— получить информацию о возможностях устройства
— дать команду устройству
— получить состояние устройства
и т.п.
На основе этого сделать интерфейс работы с устройством.
Потом сделать много реализаций этого интерефейса — для CAN, TCP, RS232 и т.п.
У>Протоколы обычно совсем разные, но иногда — схожие, отличающиеся только нюансами способа передачи. Бывает peer-2-peer, бывает один-ко-многим. Один-ко-многим подразумевает мастера, слейвы только отвечают. Если peer-2-peer, или, как в CAN — коллизии разруливаются аппаратно — тогда слейвы могут асинхронно генерить сообщения.
Можно выделить общий функционал в отдельные классы — "устройство MasterSlave" и "устройство Peer2Peer"
У>Да, у протоколов может быть, а может не быть — адресация. Там, где транспорт обязывает иметь адрес для каждого пакета CAN/UDP, протокол пользуется средствами транспорта. Если это что-то типа RS232/UART, RS422/485, то адрес добавляется в посылку данных. peer-2-peer соединения могут быть установлены с использованием адреса один раз, и далее какая-либо адресация пропадает. Или не пропадает.
Адрес неразрывно связан с протоколом. Обобщать его смысла, наверное нет. Это детали реализации протокола работы с устройством.
class TCPDevice(ip_address) implements IDevice
class TCP6Device(ip6_address) implements IDevice
class RS232() implements IDevice # no address
class TCPNetworkDevice(ip_address, gateway_address, mask) implements IDevice # multi-address
У>Хочется как-то более менее универсально описать всё это так, чтобы для добавления нового протокола (или способа использования существующего поверх другого транспорта) нужно было бы дописать самую малость — чтобы как из кубиков составлялось — просто заменил парочку и всё работает. Ну, и хочется, чтобы ранее написанный код от такой подмены не переставал работать, а без вопросов переехал бы на новый протокол/транспорт.
Имхо, как сказал выше, надо поднять уровень абстракции, чтобы охватить все возможные варианты.
Работать не на уровне протокола, а выше — зачем этот протокол нужен.
У>Хочется как-то более менее универсально описать всё это так, чтобы для добавления нового протокола (или способа использования существующего поверх другого транспорта) нужно было бы дописать самую малость — чтобы как из кубиков составлялось — просто заменил парочку и всё работает. Ну, и хочется, чтобы ранее написанный код от такой подмены не переставал работать, а без вопросов переехал бы на новый протокол/транспорт.
Звучит вот прямо как WCF (communication foundation) — всё в конфиге, а в случае изменений просто исправь конфиг. Вот только вышло у них как-то дико многословно и любви особой не снискало.