| Both sides previous revision Previous revision Next revision | Previous revision |
| doc:jroboplc:modules:arctrm_dev [2026/07/22 21:43] – denis | doc:jroboplc:modules:arctrm_dev [2026/08/01 18:06] (current) – denis |
|---|
| ===== 1. Назначение ===== | ===== 1. Назначение ===== |
| |
| ''ArctrmModule'' - модуль архивации температурных значений. Он читает значения датчиков из тегов уже настроенных модулей оборудования, сохраняет периодические срезы в базу Firebird и пишет события изменения состояния связи с устройствами. | ''ArctrmModule'' - модуль архивации температурных значений. Он читает значения датчиков из тегов уже настроенных модулей оборудования, сохраняет периодические срезы в базу Firebird и пишет события изменения состояния связи с устройствами и потери актуальности данных подвесов. |
| |
| Сам модуль не реализует протокол обмена с оборудованием. Доступ к данным выполняется через ''Ref'': каждый ''Sensor'' ссылается на тег вида ''<deviceName>:Pdv<num>.T<sensorIndex>'', а ''ArctrmDevice'' контролирует состояние устройства через ''<deviceName>:SYSTEM.ErrorFlag''. По коду видно, что конфигурация устройств берется из секции ''promauto.termo5''; тип ''promauto.termo5'' создается периферийным плагином как ''PaTermo5Module''. | Сам модуль не реализует протокол обмена с оборудованием. Доступ к данным выполняется через ''Ref'': каждый ''Sensor'' ссылается на тег вида ''<deviceName>:Pdv<num>.T<sensorIndex>'', ''Podves'' проверяет актуальность данных по ''<deviceName>:Pdv<num>.Time'', а ''ArctrmDevice'' контролирует состояние устройства через ''<deviceName>:SYSTEM.ErrorFlag''. По коду видно, что конфигурация устройств берется из секции ''promauto.termo5''; тип ''promauto.termo5'' создается периферийным плагином как ''PaTermo5Module''. |
| |
| Описание плагина в ''ArctrmPlugin.getPluginDescription()'' - ''termo value archiver''. | Описание плагина в ''ArctrmPlugin.getPluginDescription()'' - ''termo value archiver''. |
| | ''ArctrmDataService'' | Инкапсулирует работу с БД: поиск модуля базы, проверку Firebird, загрузку и выполнение скрипта, синхронизацию ''PODVES'', запись ''TEMPER'' и ''EVENTLOG'', удаление старых архивных строк и учет текущего размера архива. | | | ''ArctrmDataService'' | Инкапсулирует работу с БД: поиск модуля базы, проверку Firebird, загрузку и выполнение скрипта, синхронизацию ''PODVES'', запись ''TEMPER'' и ''EVENTLOG'', удаление старых архивных строк и учет текущего размера архива. | |
| | ''ArctrmDevice'' | Описывает одно настроенное устройство, содержит список ''Podves'', читает ''SYSTEM.ErrorFlag'' и пишет события изменения статуса устройства. | | | ''ArctrmDevice'' | Описывает одно настроенное устройство, содержит список ''Podves'', читает ''SYSTEM.ErrorFlag'' и пишет события изменения статуса устройства. | |
| | ''Podves'' | Описывает один подвес устройства, содержит список ''Sensor'', синхронизирует запись в ''PODVES'', сохраняет одну строку архива со всеми своими датчиками. | | | ''Podves'' | Описывает один подвес устройства, проверяет актуальность данных по тегу ''Pdv<num>.Time'', содержит список ''Sensor'', синхронизирует запись в ''PODVES'', сохраняет строку архива с актуальными данными и формирует событие потери актуальности. | |
| | ''Sensor'' | Ссылается на температурный тег, читает целочисленное значение и заменяет отсутствующие или выходящие за диапазон значения специальными кодами. | | | ''Sensor'' | Ссылается на температурный тег, читает целочисленное значение и заменяет отсутствующие или выходящие за диапазон значения специальными кодами. | |
| | ''Duration'' | Разбирает строковый период и выравнивает дату-время на границу периода. | | | ''Duration'' | Разбирает строковый период и выравнивает дату-время на границу периода. | |
| | ''Constants'' | Содержит коды событий и специальные значения датчиков. | | | ''Constants'' | Содержит коды событий, специальные значения датчиков и предел актуальности данных подвеса. | |
| | ''Defaults'' | Содержит значения конфигурации по умолчанию. | | | ''Defaults'' | Содержит значения конфигурации по умолчанию. | |
| | ''ArctrmException'' | Проверяемое исключение для ошибок подготовки и инициализации Arctrm. | | | ''Params'' | Пустой класс; в текущей реализации не используется. | |
| | ''Context'' | Пустой класс; в текущей реализации не используется. | | | ''ArctrmException'' | Проверяемое исключение для ошибок конфигурации, подготовки и инициализации Arctrm. | |
| |
| Прямое подключение к базе выполняет только ''ArctrmDataService''. Остальная часть модуля работает с объектами предметной модели и теговыми ссылками. | Прямое подключение к базе выполняет только ''ArctrmDataService''. Остальная часть модуля работает с объектами предметной модели и теговыми ссылками. |
| * состояние ''lastStatus'', по которому определяется необходимость записи события. | * состояние ''lastStatus'', по которому определяется необходимость записи события. |
| |
| ''Podves'' создается по записи внутри конфигурации устройства. Номер подвеса получается из ключа конфигурации через ''entry.getKey().substring(1)'' и ''Integer.parseInt(...)''. Например, ключ ''p3'' дает номер ''3''. Имя подвеса формируется как ''<deviceName>.<podvesNum>'', а значение конфигурации сохраняется как описание ''descr''. | ''Podves'' создается по записи внутри конфигурации устройства. Номер подвеса получается из ключа конфигурации через ''entry.getKey().substring(1)'' и ''Integer.parseInt(...)''. Например, ключ ''p3'' дает номер ''3''. Имя подвеса формируется как ''<deviceName>.<podvesNum>'', а значение конфигурации сохраняется как описание ''descr''. Кроме списка датчиков подвес создает ссылку ''refTime'' на тег ''<deviceName>:Pdv<num>.Time'' и хранит признаки ''dataValid'' и ''needSaveEvent''. |
| |
| ''Sensor'' создается для каждого индекса от ''0'' до ''sensorCount - 1''. Имя тега строится так: | ''Sensor'' создается для каждого индекса от ''0'' до ''sensorCount - 1''. Имя тега строится так: |
| - Генерирует SQL вставки в ''TEMPER'' с колонками ''T0..T<n-1>''. | - Генерирует SQL вставки в ''TEMPER'' с колонками ''T0..T<n-1>''. |
| |
| После подготовки сервиса модуль вызывает ''prepare()'' у каждого устройства. Устройства подготавливают ссылки на ''SYSTEM.ErrorFlag'', а подвесы - ссылки всех датчиков. | После подготовки сервиса модуль вызывает ''prepare()'' у каждого устройства. Устройства подготавливают ссылки на ''SYSTEM.ErrorFlag'', а подвесы - ссылки всех датчиков и ''Pdv<num>.Time''. |
| |
| В конце подготовки выставляется ''needInit = true'', а ''lastDt'' сбрасывается в ''null''. | В конце подготовки выставляется ''needInit = true'', а ''lastDt'' сбрасывается в ''null''. |
| - Берется серверное время базы через ''svc.now()''. | - Берется серверное время базы через ''svc.now()''. |
| - Время округляется вниз до границы периода через ''Duration.floorToPeriod(...)''. | - Время округляется вниз до границы периода через ''Duration.floorToPeriod(...)''. |
| - Все устройства, подвесы и датчики обновляют текущие значения. | - Все устройства и подвесы обновляют состояние; датчики опрашиваются только у подвесов с актуальным значением ''Pdv<num>.Time''. |
| - Если рассчитанный ''dt'' отличается от ''lastDt'', сохраняется архивный срез и выполняется очистка старых строк. | - Если рассчитанный ''dt'' отличается от ''lastDt'', сохраняется архивный срез и выполняется очистка старых строк. |
| - Для каждого устройства проверяется состояние связи и при изменении пишется событие в ''EVENTLOG''. | - Для каждого устройства проверяется состояние связи и при изменении пишется событие в ''EVENTLOG''. |
| ==== Сохранение данных ==== | ==== Сохранение данных ==== |
| |
| При наступлении нового периода каждое устройство вызывает ''savePodves(...)'', каждый подвес собирает значения своих датчиков и передает их в ''svc.saveTemper(dt, id, values)''. В базу пишется одна строка ''TEMPER'' на один подвес. | При наступлении нового периода каждое устройство вызывает ''savePodves(...)''. Подвес с актуальными данными собирает значения своих датчиков и передает их в ''svc.saveTemper(dt, id, values)''; в базу пишется одна строка ''TEMPER''. Если ссылка на ''Pdv<num>.Time'' не найдена или значение находится вне диапазона ''0..600'', строка для этого подвеса не создается. |
| |
| События состояния устройства сохраняются отдельно через ''svc.saveEvent(...)''. Событие пишется только при изменении статуса относительно ''lastStatus''. | События состояния устройства сохраняются отдельно через ''svc.saveEvent(...)''. Событие пишется только при изменении статуса относительно ''lastStatus''. Событие ''EVENT_PODVES_UPDATE_STALE'' формируется при первой потере актуальности данных подвеса и сохраняется вызовом ''Podves.save(...)'' при наступлении следующего архивного периода. |
| |
| ==== Останов и reload ==== | ==== Останов и reload ==== |
| ==== Таблица ''EVENTLOG'' ==== | ==== Таблица ''EVENTLOG'' ==== |
| |
| Назначение: хранение событий модуля и событий изменения состояния устройств. | Назначение: хранение событий модуля, изменения состояния устройств и потери актуальности данных подвесов. |
| |
| <code sql> | <code sql> |
| | ''DT'' | Время события; при записи берется ''db.getServerDatetime()''. | | | ''DT'' | Время события; при записи берется ''db.getServerDatetime()''. | |
| | ''EVENT_CODE'' | Код события из ''Constants''. | | | ''EVENT_CODE'' | Код события из ''Constants''. | |
| | ''MESSAGE'' | Сообщение; для статуса устройства используется имя устройства. | | | ''MESSAGE'' | Сообщение; для статуса устройства используется имя устройства, для потери актуальности - имя подвеса, для инициализации - пустая строка. | |
| |
| Индекс: ''IX_EVENTLOG_DT'' по полю ''DT''. | Индекс: ''IX_EVENTLOG_DT'' по полю ''DT''. |
| |
| ^ Константа ^ Значение ^ Где используется ^ | ^ Константа ^ Значение ^ Где используется ^ |
| | ''EVENT_ARCTRM_INIT'' | ''0'' | Записывается при инициализации Arctrm. | | | ''EVENT_ARCTRM_INIT'' | ''100'' | Записывается при инициализации Arctrm. | |
| | ''EVENT_CONNECTED'' | ''1'' | Записывается при переходе устройства в состояние связи. | | | ''EVENT_DEVICE_CONNECTED'' | ''99'' | Записывается при переходе устройства в состояние связи. | |
| | ''EVENT_DISCONNECTED'' | ''2'' | Записывается, если ''SYSTEM.ErrorFlag == true''. | | | ''EVENT_DEVICE_DISCONNECTED'' | ''1'' | Записывается, если ''SYSTEM.ErrorFlag == true''. | |
| | ''EVENT_NOLINK'' | ''3'' | Записывается, если ссылка на ''SYSTEM.ErrorFlag'' не найдена. | | | ''EVENT_DEVICE_NOLINK'' | ''0'' | Записывается, если ссылка на ''SYSTEM.ErrorFlag'' не найдена и предыдущий статус имел другой код. | |
| | | ''EVENT_PODVES_UPDATE_STALE'' | ''3'' | Записывается при первой потере актуальности данных подвеса; в ''MESSAGE'' передается имя ''<deviceName>.<podvesNum>''. | |
| |
| Очистка ''EVENTLOG'' в коде не реализована. | Очистка ''EVENTLOG'' в коде не реализована. |
| -> ArctrmDevice.update() | -> ArctrmDevice.update() |
| -> Podves.update() | -> Podves.update() |
| -> Sensor.update() | -> Podves.checkTimeValid() |
| | -> Sensor.update() при актуальных данных |
| </code> | </code> |
| |
| ''Sensor.update()'' работает только с теговой ссылкой: | Сначала ''Podves.update()'' проверяет ссылку ''Pdv<num>.Time''. Данные считаются актуальными, если ссылка существует, а значение тега находится в диапазоне от ''0'' до ''PODVES_UPDATE_TIME_LIMIT = 600'' включительно. При неактуальных данных ''Sensor.update()'' не вызывается и значения датчиков остаются прежними. |
| | |
| | Для подвеса с актуальными данными ''Sensor.update()'' работает с теговой ссылкой: |
| |
| ^ Условие ^ Записываемое значение ^ | ^ Условие ^ Записываемое значение ^ |
| | Тег не найден через ''ref.linkIfNotValid()'' | ''VALUE_NOLINK = 3000'' | | | Тег не найден через ''ref.linkIfNotValid()'' | ''VALUE_NOLINK = 3013'' | |
| | Значение меньше ''-1000'' | ''VALUE_BROKEN = 3010'' | | | Значение меньше ''-1000'' | ''VALUE_SHORTAGE = 3010'' | |
| | Значение больше ''2000'' | ''VALUE_SHORTAGE = 3011'' | | | Значение больше ''2000'' | ''VALUE_BROKEN = 3011'' | |
| | Значение в диапазоне | Исходное целое значение тега | | | Значение в диапазоне | Исходное целое значение тега | |
| |
| Архивные строки пишутся только если рассчитанный ''dt'' отличается от ''lastDt''. При записи: | Архивные строки пишутся только если рассчитанный ''dt'' отличается от ''lastDt''. При записи: |
| |
| * каждое устройство сохраняет все свои подвесы; | * каждое устройство вызывает ''save(...)'' для всех своих подвесов; |
| * каждый подвес формирует список текущих значений датчиков; | * каждый подвес с актуальными данными формирует список текущих значений датчиков; |
| * ''ArctrmDataService.saveTemper(...)'' вставляет одну строку ''TEMPER''. | * ''ArctrmDataService.saveTemper(...)'' вставляет одну строку ''TEMPER'' для каждого подвеса с актуальными данными; |
| | * подвес с неактуальными данными не создает строку ''TEMPER'', но при установленном ''needSaveEvent'' записывает событие ''EVENT_PODVES_UPDATE_STALE''. |
| |
| Формат подготовленного SQL строится один раз при подготовке: | Формат подготовленного SQL строится один раз при подготовке: |
| В этом примере ''plugin.arctrm'' и ''module.arctrm'' соответствуют схеме загрузки конфигурации: ''ConfigurationYaml.getModuleConf(...)'' ищет ''plugin.<pluginName>'' и внутри него ''module.<moduleName>''. Значения ''database'', ''period'', ''size'', ''schema'' и ''sensorCount'' читаются в ''ArctrmModule.loadModule()''. | В этом примере ''plugin.arctrm'' и ''module.arctrm'' соответствуют схеме загрузки конфигурации: ''ConfigurationYaml.getModuleConf(...)'' ищет ''plugin.<pluginName>'' и внутри него ''module.<moduleName>''. Значения ''database'', ''period'', ''size'', ''schema'' и ''sensorCount'' читаются в ''ArctrmModule.loadModule()''. |
| |
| Секция ''promauto.termo5'' передается в ''ArctrmDevice.load(...)''. Ключи ''mytrm1'' и ''mytrm2'' становятся именами модулей-источников тегов. Ключи ''p0'', ''p5'' и ''p1'' дают номера подвесов ''0'', ''5'' и ''1'', потому что код берет часть ключа после первого символа и разбирает ее как число. При ''sensorCount: 6'' для каждого подвеса создаются ссылки на теги ''Pdv<num>.T0'' ... ''Pdv<num>.T5''. | Секция ''promauto.termo5'' передается в ''ArctrmDevice.load(...)''. Ключи ''mytrm1'' и ''mytrm2'' становятся именами модулей-источников тегов. Ключи ''p0'', ''p5'' и ''p1'' дают номера подвесов ''0'', ''5'' и ''1'', потому что код берет часть ключа после первого символа и разбирает ее как число. При ''sensorCount: 6'' для каждого подвеса создаются ссылки на теги ''Pdv<num>.T0'' ... ''Pdv<num>.T5'', а также ссылка на ''Pdv<num>.Time''. |
| |
| Комментарий ''#604800'' в строке ''size'' является YAML-комментарием и не участвует в значении параметра. Активное значение в примере - ''30''. | Комментарий ''#604800'' в строке ''size'' является YAML-комментарием и не участвует в значении параметра. Активное значение в примере - ''30''. |
| |
| ^ Условие ^ Код события ^ | ^ Условие ^ Код события ^ |
| | Ссылка на ''SYSTEM.ErrorFlag'' не найдена | ''EVENT_NOLINK'' | | | Ссылка на ''SYSTEM.ErrorFlag'' не найдена | ''EVENT_DEVICE_NOLINK = 0'' | |
| | Ссылка есть, ''ErrorFlag == true'' | ''EVENT_DISCONNECTED'' | | | Ссылка есть, ''ErrorFlag == true'' | ''EVENT_DEVICE_DISCONNECTED = 1'' | |
| | Ссылка есть, ''ErrorFlag == false'' | ''EVENT_CONNECTED'' | | | Ссылка есть, ''ErrorFlag == false'' | ''EVENT_DEVICE_CONNECTED = 99'' | |
| | |
| | Событие пишется только при изменении состояния относительно ''lastStatus''. Поле ''lastStatus'' изначально равно ''0'', поэтому начальное состояние ''EVENT_DEVICE_NOLINK'' не записывается, а начальные состояния ''EVENT_DEVICE_DISCONNECTED'' и ''EVENT_DEVICE_CONNECTED'' записываются. Низкоуровневые ошибки обмена с оборудованием Arctrm не анализирует; они видны только через теги внешних модулей. |
| | |
| | ==== Неактуальные данные подвеса ==== |
| | |
| | Ссылка на ''Pdv<num>.Time'' считается неактуальной, если она не найдена либо содержит значение меньше ''0'' или больше ''600''. При переходе ''dataValid'' из ''null'' или ''true'' в ''false'' устанавливается ''needSaveEvent''. До восстановления актуальности датчики не опрашиваются, а строка ''TEMPER'' для подвеса не записывается. |
| |
| Событие пишется только при изменении состояния относительно ''lastStatus''. Низкоуровневые ошибки обмена с оборудованием Arctrm не анализирует; они видны только через теги внешних модулей. | При наступлении следующего архивного периода ''Podves.save(...)'' записывает ''EVENT_PODVES_UPDATE_STALE = 3'' с именем подвеса в ''MESSAGE'' и сбрасывает ''needSaveEvent''. Повторное событие возможно только после восстановления актуальности и ее новой потери; отдельное событие восстановления не предусмотрено. |
| |
| ==== Некорректные значения датчиков ==== | ==== Некорректные значения датчиков ==== |
| |
| Значения ниже ''-1000'' заменяются на ''VALUE_BROKEN'', значения выше ''2000'' - на ''VALUE_SHORTAGE''. Отдельные события и отдельное логирование для таких значений не реализованы. | Значения ниже ''-1000'' заменяются на ''VALUE_SHORTAGE = 3010'', значения выше ''2000'' - на ''VALUE_BROKEN = 3011''. Отдельные события и отдельное логирование для таких значений не реализованы. |
| |
| Если тег датчика не найден, значение становится ''VALUE_NOLINK''. Такие датчики дополнительно подсчитываются в ''getInfo()''. | Если тег датчика не найден, значение становится ''VALUE_NOLINK = 3013''. Такие датчики дополнительно подсчитываются в ''getInfo()''. |
| |
| ==== Неожиданные исключения ==== | ==== Неожиданные исключения ==== |
| | Однократная загрузка списка колонок ''TEMPER'' при init | Позволяет добавить только отсутствующие ''T*''-колонки. | | | Однократная загрузка списка колонок ''TEMPER'' при init | Позволяет добавить только отсутствующие ''T*''-колонки. | |
| |
| JDBC batch-вставки не используются: при наступлении периода выполняется одна вставка на каждый подвес. | JDBC batch-вставки не используются: при наступлении периода выполняется одна вставка на каждый подвес с актуальными данными. |
| |
| ===== 11. Ограничения ===== | ===== 11. Ограничения ===== |
| * ''ArctrmPlugin.java''; | * ''ArctrmPlugin.java''; |
| * ''ArctrmException.java''; | * ''ArctrmException.java''; |
| * ''Context.java''; | * ''Params.java''; |
| * ''src/main/resources/dbscr/dbscr.arctrm.yml''; | * ''src/main/resources/dbscr/dbscr.arctrm.yml''; |
| * ''DatabaseProtoServiceImpl.java''; | * ''DatabaseProtoServiceImpl.java''; |
| * Пример конфигурации предоставлен как документационный; штатный Arctrm-конфиг в просмотренных файлах репозитория не найден. | * Пример конфигурации предоставлен как документационный; штатный Arctrm-конфиг в просмотренных файлах репозитория не найден. |
| * Бизнес-смысл событий известен только по именам констант. | * Бизнес-смысл событий известен только по именам констант. |
| * Низкоуровневое поведение оборудования находится вне Arctrm; модуль видит только теги и ''SYSTEM.ErrorFlag''. | * Низкоуровневое поведение оборудования находится вне Arctrm; модуль видит только теги датчиков, ''Pdv<num>.Time'' и ''SYSTEM.ErrorFlag''. |
| * Требования к эксплуатационной очистке ''EVENTLOG'', удалению старых ''PODVES'' и реакции на внешние изменения базы в коде не определены. | * Требования к эксплуатационной очистке ''EVENTLOG'', удалению старых ''PODVES'' и реакции на внешние изменения базы в коде не определены. |