Как я могу реализовать протокол последовательной связи в объектно-ориентированной форме? - PullRequest
5 голосов
/ 30 ноября 2010

Я работаю со встроенным устройством, которое подключено к ПК через RS232.

Мне нужно программное обеспечение для связи с этим встроенным устройством.

Я программирую на Delphi. Я никогда не использовал объектно-ориентированный в прошлом. Но я пытаюсь это изменить.

Я не могу мыслить объектно-ориентированным способом, чтобы решить эту проблему.

У меня есть этот протокол:

<STX><STX><COMMAND>[<DATA><DATA>...]<CHKSUM><ETX>

где:

<STX> is the Start of TeXt (0x55);
<COMMAND> can be 0x01 for read, 0x02 for write, etc;
<DATA> is any value;
<CHKSUM> is the checksum;
<ETX> is the End of TeXt (0x04).

Программный компьютер отправит команду через последовательный порт, и устройство ответит, используя тот же протокол.

Например:

Reset command
PC sends     : <STX><STX><0x09><0x00><CHKSUM><ETX>
Device answer: <STX><STX><0x09><0x00><CHKSUM><ETX>

Get Version
PC sends     : <STX><STX><0x00><0x02><CHKSUM><ETX>
Device answer: <STX><STX><0x00><0x00><VER_L><VER_H><CHKSUM><ETX>

Я должен отправить поток файлов на устройство.

Я хотел бы получить предложения и / или примеры наилучшего способа реализации этого объектно-ориентированным способом. Я бы тоже хотел провести юнит-тест.

Спасибо

Ответы [ 3 ]

5 голосов
/ 30 ноября 2010

Вам следует обратить внимание на другие последовательные модели отправки / получения, такие как HTTP.В .NET объект HTTPWebRequest - это место, где вы собираете вместе все фрагменты информации для отправки по проводам, включая команду (МЕТОД HTTP: GET, PUT, POST и т. Д.) И поток байтов.Объект HTTPWebRequest (и стек HTTP) внутренне обрабатывает «бумажную работу» по вычислению контрольных сумм данных, разбивке больших данных на более мелкие пакеты и т. Д. Все, что должен сделать ваш код, - это создать объект запроса, установить команду, назначитьпоток данных в свойство объекта запроса и отправка.

Еще одна причина, по которой вы должны смотреть на существующие модели объектов связи, такие как .NET HTTP, заключается в том, что последовательные соединения обычно асинхронны с точки зрения вашего центрального процессора.Много времени ЦП может пройти при передаче символов запроса по последовательному порту и при ожидании ответа.Используйте асинхронную модель для вашего запроса / ответа, чтобы не блокировать вызывающий поток и потенциально заморозить ваш пользовательский интерфейс.

Чтобы продолжить пример .NET HTTP, HTTPWebRequest имеет метод GetResponse, который отправляет запрос и будетблокировать вызывающий поток до получения ответа.HTTPWebRequest также имеет пару BeginGetResponse () / EndGetResponse (), так что вы можете отправить запрос и предоставить обратный вызов, который будет выполнен, когда ответ придет в более позднее время.

Даже если ваш непосредственный дизайн в порядке сМодель синхронного вызова с блокировкой потоков, вы должны, по крайней мере, исследовать шаблоны асинхронного кодирования и рассмотреть возможность реализации своего объекта как такового.Вы всегда можете вызвать асинхронный метод синхронным способом, блокирующим потоки, но гораздо сложнее вызвать асинхронный метод синхронным методом.Потратьте немного времени сейчас, чтобы дать себе больше возможностей в будущем.

3 голосов
/ 30 ноября 2010

Ну, я думаю, что существует столько же решений, сколько и программистов.Не зная больше о вашей системе, я бы, вероятно, пошел с этим подходом:

Создайте базовый класс команд, скажем так;TBaseCommand.Определите свой общий интерфейс на этом уровне, например Send (), Receive (), Run () и т. Д. *

Заполняйте код только для функций, общих для всех команд, таких как отправка, получение и т. Д.

Функции, которые будут различаться по исполнению, делаются виртуальными для определения на следующем уровне.Исходя из этого, создайте новый класс для каждой команды и введите специальный код команды, например, Run ().

Наличие Run () позволит вам легко смоделировать ваши команды на экране путем переопределения Run ()function.

, а ваш транспортный протокол должен применяться и удаляться вашим коммуникационным интерфейсом (отдельный класс протокола?).Ваш класс протокола также может обрабатывать ошибки контрольной суммы и пытаться повторно отправить и т. Д. Если это не удается устранить, сообщите об ошибке.

Это было всего лишь несколько вещей на моей голове с вашим ограниченным описанием ...

2 голосов
/ 30 ноября 2010

Трудно ответить, но из-за небольшого количества информации, которую я имею, вот как я это сделаю:

Либо вы класс, который знает, как сериализовать себя, либо вы используете шаблон посетителя для сериализации. Преимущество этого состоит в том, что вы отделяете ваши данные от сериализации и позволяете вам легче реализовать другой механизм сериализации.

Таким образом, у меня будет класс Data, класс Command, который содержит коллекцию (выберите предпочтительный контейнер) данных. Класс Command, скорее всего, будет обрабатывать вычисление контрольной суммы с помощью открытого метода. Я также хотел бы иметь класс связи, чтобы инкапсулировать Команду и начинать и заканчивать связь. Тогда у меня был бы класс, отвечающий за взаимодействие с последовательным портом, у которого был бы метод Send, который брал бы ссылку на класс связи.

Из доступной информации я могу придумать дизайн.

Что касается модульного тестирования, с хорошим дизайном, вы должны быть в состоянии провести модульное тестирование практически всего. Не забудьте использовать заглушки, вы не хотите подключаться к этому последовательному порту во время тестирования, поэтому создайте поддельный класс последовательной связи, который, например, записывает в строку, и сравните полученную строку с ожидаемой спецификацией значения.

...