вторник, 19 ноября 2019 г.

Упражнения с BACnet - журнал операций

Я когда начинал описывать протокол BACnet, сделал такой сетевой "драйвер", который загружает формат Wireshark PCAP и подает на вход службы разбора пакетов APDU. Это позволило написать и отладить разбор форматов ASN кодирования BACnet.
С тех пор прошло много времени. Много кода... Сейчас Мне понадобилось сохранять конфигурацию контроллера в ответ на команду Re-инициализации. Вообще, как себе представляешь можно работать в контроллере с базой данных объектов? И при этом требуется сохранять конфигурацию между сессиями, при перезагрузке. Я придумал, что надо писать во флеш журнал операций модификации данных. Просто так, линейно вперед, пока место не закончится. Когда контроллер просыпается после перезагрузки он должен накатить журнал операций. Журнал, чтобы не плодить разные сущности я решил паковать прямо командами протокола, транзакциям. Например, транзакция понятная - создать объект, дописать свойства к объекту. По сути мы можем сохранять все операции записи типа WriteProperty, прямо из буфера обмена без изменения писать в журнал - во флеш. Вот такая замечательная идея.
Как отладить замечательную идею?
Журнал во флеш, флеш в контроллере. Контроллер перегружается... Не удобно.
Кроме контроллера есть сервер сбора данных, роутер BACnet. Предлагаю сохранить его конфигурацию в файл и поизучать каким-нибудь инструментом. Нужна отладка для журнала файловой системы.
Берем приложение, пригодное для отладки, для рассматривания журналов. Да вот оно - Wireshark. В итоге я пишу функцию, функционал, для записи данных не во флеш, а в файл со структурой PCAP и изучаю, что получилось в итоге. А в итоге имею последовательность команд протокола CreateObject, CreateObject, CreateObject... и на этом выводе примерно за день отлаживаю функцию экспорта объектов из базы данных в журнал.

База данных - это структура типа дерево объектов.
Foreach (DeviceInfo->ObjectTree, (Callback) save_object_cb, to_file);
Т.е. описываем некоторую процедуру обхода дерева с записью каждого элемента в файл/журнал. Так выглядит сериализация дерева.
Каждая запись состоит из шапки::{длина данных, тип записи}, пакета данных, контрольной_суммы. После чего можно записать следующую запись. В шапку можно записать и тип записи, в нашей концепции - это тип сервиса - CreateObject, DeleteObject, WritePropertyMultiple.
По сути нам не нужен этот идентификатор сервиса, потому что CreateObject без параметров можно расценивать как Delete, А операцию повторного создания объекта расценивать, как WritePropertyMultiple. Писать в журнал поток команд протокола подкупает своей простотой.
При ре-инициализации устройства через перезагрузку можно переписать журнал заново. При загрузке просто накатить этот журнал.

Есть проблема: как минимизировать объем данных в журнале, как делать инкрементную запись -- писать только те параметры, которые изменились с прошлой версии базы.
[07.01.2020]
Написал вывод в журнал, с учетом файлов. Получилось две операции: CreateObject, AtomicWriteFile.
Нашел свой старый проект, журналируемая файловая система для флеш. Тогда мы использовали четыре вида полей: APPEND - дописывание файлов, ATTRIB - дописывание/изменение атрибутов, CREATE - создание, DELETE - удаление, SKIP - технологическая операция - заполнение пробелов, для выравнивания на блок записи.
Сейчас думаю использовать старые идеи только расширить понятие файловой системы до объектов. CREATE -- создание объектов CreateObject, ATTRIB - запись атрибутов в формате WritePropertyMultiple, APPEND - дописывание файлов в форме AtomicWriteFile, DELETE - пометить на удаление из базы DeleteObject.

Комментариев нет:

Отправить комментарий