====== motohr ======
Модуль учета моточасов оборудования. Данный должен работать в одной задаче с базой данных.
===== Основные возможности =====
* Учет работы оборудования по любым тегам проекта
* Быстрое и гибкое определение тегов учета при помощи regex-выражений
* Каждой единице или группе оборудования можно задать свой состав счетчиков
* Возможность создавать дикрементируемые счетчики-таймеры
* Возможность подтягивать описание оборудования из строковых тегов
* Ведение для каждой единицы суточной статистики по времени работы и количеству запусков
* Журналирование всех запусков и остановов по каждой единице оборудования
* Минимальное влияние на трафик для jrbustcp-клиентов на больших проектах
* Низкая нагрузка на СУБД на больших проектах
* Удаление старых данных с клиента через специальный строковый тег
===== Конфигурация =====
plugin.motohr:
module.mh:
database: db
machines:
- expr.tag: .*\.MCHB_(.*)_Plata
expr.descr: (.*)(MCHB.*)(_Plata)
repl.descr: $1.$2.descr
include.tag: ^UVRD.*
exclude.tag: .*Beep.*
include.descr: .*(Дробилка|Нория|Шнек).*
exclude.descr: .*(101|102).*
===== Параметры =====
^ Параметр ^ Умолчание ^ Описание ^
|**database**| ''db'' |Модуль базы данных ([[doc:jroboplc:modules:database]]) |
^ machines - правила формирования списка машин и назначения им счетчиков ^^^
|**prefix** | '''' |Префикс имени машины |
|**expr.tag** | ''.*\.MCHB_(.*)_Plata'' |regex-выражение для поиска тегов статуса машины, т.е. содержащих значение статуса, где: 0=стоит, 1=работает |
|**expr.descr** | ''(.*)(MCHB.*)(_Plata)'' |regex-выражение для преобразования имени тега статуса машины в имя тега описания |
|**repl.descr** | ''$1$2.descr'' |Выражение подстановки для формирования имени тега описания машины |
|**include.tag** | '''' |regex-выражения фильтров по имени тега статуса и описанию. Если пусто, то не используется |
|**exclude.tag** |::: |::: |
|**include.descr** |::: |::: |
|**exclude.descr** |::: |::: |
===== Теги =====
^ Имя тега ^ Тип данных ^ Доступ ^ Описание ^
|''connected '' | ''BOOL '' | '''' |Состояние подключения к базе данных |
|''system.time '' | ''LONG '' | '''' |Локальное текущее время в секундах |
|''system.util '' | ''STRING '' | ''RW'' |Тег для ввода системных команд (см. ...) |
| Группы тегов по каждому типу счетчиков ||||
|''cnttype..descr '' | ''STRING '' | '''' |Описание счетчика |
|''cnttype..timer '' | ''BOOL '' | '''' |Счетчик является таймером |
| Группы тегов по каждой единице оборудования ||||
|''.cnt '' | ''INT '' | ''RW'' |Значение счетчика без учета рабочего времени с момента последнего старта |
|''.time '' | ''LONG '' | '''' |Локальное время в секундах с момента последнего старта, либо 0, если машина остановлена |
|''.descr '' | ''STRING '' | ''RW'' |Описание машины |
где:
* ''ctId'' - идентификатор типа счетчика, значения от 1 и более. Значение 1 всегда имеет счетчик "Всего", называемый далее **''total''**.
* ''machName'' - имя машины
Примечание:
*Локальное время в секундах - от 1970-01-01T00:00:00Z без часового пояса.
Пример выборки тегов:
^ Имя тега ^ Тип данных ^ Значение тега ^
|''mh.cnttype.1.descr'' | ''STRING'' | ''Всего '' |
|''mh.cnttype.1.timer'' | ''BOOL '' | ''off '' |
|''mh.cnttype.2.descr '' | ''STRING'' | ''Счетчик A'' |
|''mh.cnttype.2.timer '' | ''BOOL '' | ''off '' |
|''mh.cnttype.3.descr '' | ''STRING'' | ''Счетчик B'' |
|''mh.cnttype.3.timer '' | ''BOOL '' | '' off '' |
|''mh.cnttype.4.descr '' | ''STRING'' | ''Таймер 1 '' |
|''mh.cnttype.4.timer '' | ''BOOL '' | ''on '' |
|''mh.100.cnt1 '' | ''INT '' | ''5328 '' |
|''mh.100.cnt2 '' | ''INT '' | ''5328 '' |
|''mh.100.cnt4 '' | ''INT '' | ''-5328 '' |
|''mh.100.descr '' | ''STRING'' | ''100 Нория '' |
|''mh.100.time '' | ''LONG '' | ''1740347568 '' |
|''mh.system.time '' | ''LONG '' | ''1740349832 '' |
|''mh.system.util '' | ''STRING'' | '' '' |
|''mh.connected '' | ''BOOL'' | ''on '' |
|''UVRD.MCHB_100_Plata '' | ''INT '' | ''1 '' |
===== База данных =====
{{:doc:jroboplc:modules:motohr_db.png|}}
[[doc:jroboplc:modules:motohr_db|sql]], [[doc:jroboplc:modules:motohr_dbscr|dbscr]]
База данных создается автоматически.
В таблицах, где есть поле ''DELETED'', удаление записей происходит установкой ''DELETED=1'', и в дальнейшем на стороне клиента данные записи отфильтровываются.
Записи в таблицах создаются автоматически по yml-конфигурации модуля.
=== MH_COUNTER_TYPE ===
Типы счетчиков
* ''TIMER'' - направление счетчика: 0 = обычный счетчик (инкремент), 1 = таймер (декремент)
=== MH_MACH ===
Машины
* ''DESCR'' - описание машины, подтягиваемое из тега описания. Если тег описания отсутствует, то допустима произвольная запись в данное поле
* ''TAGNAME'' - полное имя тега состояния машины, например: ''UVRD.MCHB_100_Plata''
=== MH_COUNTER ===
Счетчики
* ''SEC'' - значение счетчика в секундах без учета рабочего времени с момента последнего старта
=== MH_MACH_STATE ===
Текущее состояния машин
* ''DT'' - дата/время последнего старта или стопа машины
* ''RUNNING'' - 0 = машина стоит, 1 = машина работает
* ''STATCNT'' - кол-во запусков машины с начала текущих суток
* ''STATSEC'' - значение счетчика ''total'' на начало текущих суток
=== MH_STAT ===
Статистика по суткам
* ''PERIOD'' - период в формате ''yyyymmdd''
* ''CNT'' - кол-во запусков машины за сутки
* ''SEC'' - время работы машины за сутки в секундах
=== MH_INTERVAL ===
Интервалы работы машин
* ''DTBEG'' - время старта
* ''DTEND'' - время стопа
* ''SEC'' - время от старта до стопа в секундах
=== MH_LOGBOOK ===
Журнал изменений значений счетчиков пользователем
===== Принцип работы =====
=== Формирование списка типов счетчиков ===
Создается тип счетчика ''total'' (Всего), после чего из базы данных загружаются другие типы счетчиков.
Тип счетчика ''total'' - это обязательный счетчик, сбрасываемый только при полной замене оборудования. Данный тип не нужно явно прописывать, он создается по умолчанию. Другие типы счетчиков добавляются в базу данных через клиентское приложение.
=== Формирование списка машин ===
Выполняется поиск тегов статуса по всем модулям приложения по правилам, описанным в конфигурации в разделе ''machines''. Данные теги должны отдавать статус машины: 0 - стоит, 1 - работает.
Из найденого тега статуса формируется имя тега описания, после чего из него берется значение - текст описания машины. Если тег описания не найден, то берется описание машины из ''MH_MACH.DESCR'', введенное пользователем посредством тега машины ''descr'' или непосредственно update-запросом к данной таблице.
Допускается попадание одной и той же машины в несколько правил.
=== Синхронизация ===
Полученная конфигурация машин и счетчиков сохраняется/обновляется в базе данных. Из базы данных загружается состояние машин и значения назначенных счетчиков.
=== Мониторинг ===
Выполняется отслеживание изменения состояния машины.
Если машина запустилась, то:
* в тег машины ''time'' записывается текущее время в секундах
* в таблице ''MH_MACH_STATE'' обновляются поля ''RUNNING = 1'', ''DT = now'', ''STATCNT = STATCNT + 1''
Если машина остановилась, то:
* в тег машины ''time'' записывается 0
* в таблице ''MH_MACH_STATE'' обновляются поля ''RUNNING = 0'', ''DT = now''
* в таблицу ''MH_MACH_INTERVAL'' добавляется запись с временем старта/стопа и длительностью работы в секундах (SEC)
* в таблице ''MH_COUNTER'' увеличиваются значения всех счетчиков машины на полученное значение SEC (для таймеров уменьшается)
* в тегах счетчиков машины также увеличиваются значения на полученное значение SEC (для таймеров уменьшается)
=== Запись статистики ===
В 00:00:00 происходит сброс накопленных за сутки данных в таблицу статистики. По каждой машине:
* в таблице ''MH_STAT'' создается запись:
* ''CNT = MH_MACH_STATE.STATCNT''
* ''SEC = T - MH_MACH_STATE.STATSEC''
* в таблице ''MH_MACH_STATE'' обновляются поля:
* ''STATCNT = 0''
* ''STATSEC = T''
где T - значение актуальное счетчика ''total'' (с учетом рабочего времени с момента последнего старта).
===== Как получить актуальные значения счетчиков =====
Счетчики (в тегах и в БД) не обновляются каждую секунду. Это сделано для предотвращения частой записи в БД довольно большего объема данных, особенно в крупных проектах. Тоже самое отностится и к тегам, т.к. ежесекундное изменение большого количества тегов увеличит трафик передачи данных между приложениями, например, по jrbustcp протоколу.
По этой причине, чтобы получить актуальное значение счетчика, нужно вычислить и прибавить к накопленному значению счетчика время работы с момента последнего старта. Как это делается, показано далее на примерах.
Пример с использованием тегов:
long machtime = getTagVal("mh.100.time");
long systime = getTagVal("mh.system.time");
int cnt = getTagVal("mh.100.total") + (machtime == 0? 0: systime - machtime);
Примеры с использованием БД:
select
mh_cnt_sec(c.sec, ms.dt, ms.running, ct.timer)
from mh_mach m
left join mh_counter c on c.mach_id = m.id
join mh_counter_type ct on ct.id = c.counter_type_id
join mh_mach_state ms on ms.mach_id = m.id
where
m.name = '100' and ct.id = 1
Для удобства можно использовать view ''MH_COUNTER_CALC'' - это сводная таблица по всем машинам и счетчикам с актуальными значениями:
select * from mh_counter_calc
===== Установка счетчика =====
Пользовательская установка значений возможна только через теги во все счетчики.
В таймеры можно записать значение от 0 включительно и более. В не-таймеры можно записать только 0.
Запись 0 в ''total'' возможна только при остановленной машине.
Если счетчик временно не используется, можно его отключить, записав значение ''0x7FFF_FFFF''.
Также при необходимости можно править значения счетчиков в базе данных, предварительно остановив приложение jrobo во избежание перезаписи данных.
===== Системные команды =====
Для очистки таблиц от старых записей используется строковый тег ''system.util'', поддерживающий следующие команды:
* ''sweep-interval '' - удаление из ''MH_INTERVAL'' записей старше заданной даты включительно
* ''sweep-stat '' - удаление из ''MH_STAT'' записей старше заданной даты включительно
* ''pach-mach'' - удаление из ''MH_MACH'' не актуальных машин, которые отсутствуют в текущем сформированном списке машин
* ''reinit'' - перезагрузка модуля. Данную команду необходимо послать для вступления в силу изменений, сделанных в базе данных клиентом.
Команды ''sweep-*'' использовать с осторожностью, т.к. можно легко остаться с пустыми таблицами.