====== 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-*'' использовать с осторожностью, т.к. можно легко остаться с пустыми таблицами.