# arcsvr

Модуль архивации значений тегов и сообщений. Предназначен для замены старого архиватора (arcsvr.exe). Данный модуль требует включения в задачу.

Модуль используется только совместно с модулем database.

Внимание! Модуль `arcsvr` должен работать совместно с модулем `database` в одной задаче.

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

Пример рабочей конфигурации http://prom-auto.ru/download/jroboplc/bundles/jroboplc-arcsvr-shdk.rar.

## Основные отличия от старого arcsvr

- Не требуется использование утилиты `arcman`. База данных, служебные и архивные таблицы и прочие метаданные создаются и обновляются автоматически.
- Оптимизация производительности. На обработку одного цикла используется одна транзакция. Используются подготовленные запросы.
- Предотвращение в базе данных «версионного мусора».
- Для архивирования значений тегов:
  - Поле `REC` в архивных таблицах имеет тип `BIGINT`.
  - `min(REC)` указывает на наиболее старую запись в архивной таблице, `max(REC)` указывает на наиболее свежую запись.
  - Возможность использовать в архивной таблице типов данных `smallint, integer, float, double`. В старом только `smallint`.
  - Архивирование данных как с использованием atg-файлов (roboplant), так и без. При этом список тегов задается при помощи regex-выражений.
  - Возможность задания любого периода архивирования, в т.ч. и менее секунды, что в старом было сделать нельзя.
  - Два режима архивирования:
    - с заданной периодичностью
    - по изменению
- Для архивирования сообщений:
  - Архивирование данных как с использованием ams-файлов (roboplant), так и без. При этом сообщение и список тегов задается в yml-файле простым описанием (arcmes.plain).
  - Добавлен новый тип сообщения «по изменению» с сохранением значения тега.
  - Добавлено привязка сообщения к месту (place) для использования в сложных распределенных системах.

## Общие параметры

Параметр | Умолчание | Описание
--- | --- | ---
database | `db` | Модуль базы данных (database)
schema | `` | Имя схемы (для firebird это префикс имен метаданных).
place | `имя модуля` | Название места сообщения по умолчанию. Может быть перекрыто в сообщениях при необходимости.
tagsources | `` | Deprecated! Определения модулей источников тегов полностью автоматизировано. Список модулей, предоставляющих теги устройств. Требуется в случае, если архивируемые теги не находятся непосредственно в системе, а импортируются посредством другого модуля, например, rpclient

## Теги модуля

Имя тега | Описание
--- | ---
Connected | Состояние работы модуля. Нормальное значение `on`, иначе архивация не выполняется из-за отсутствия подключения к базе данных или ошибки при инициализации (подробности смотреть в log-файлах)

# Архивирование тегов

В системе может быть более одного одновременно работающих модулей arcsvr. Один модуль может архивировать значения в одну и более таблиц. Два разных модуля не могут одновременно работать с одной и той же архивной таблицей.

#### Пример конфигурации

    plugin.arcsvr:
      enable: on

      module.arcval:
        database:   dbtag

        arcval.robo:
          - projects/NRMEL.atg
          - projects/NRMGR.atg

        arcval.regex:
          UVHL_2S:
            period_align: on
            period_ms:  2000
            size:       604800
            type:       int16
            mode:       period
            tags:
              - UVHL.MCHB.*_Plata
              - UVHL.MDTA.*_Value
              - ~ .*Beep.*

          UVHL_4S:
            period_ms:  4000
            size:       302400
            type:       int16
            mode:       period
            tags:
              - UVHL.(MCHB|MDTA).*\.Sost
              - ~ .*Beep.*

          UVHL_BLOK:
            period_ms:  1000
            force_s:    86400 # once a day
            size:       10000
            type:       int16
            mode:       change
            tags:
              - UVHL.*_Blok

          UVHL_CHNL:
            period_ms:  1000
            force_s:    0     # no forcing
            size:       1000
            type:       int32
            mode:       change
            tags:
              - UVHL.*_(Channel|Chnl).*

          ARCVAL_TEST:
            period_ms:  1000
            force_s:    10
            size:       40
            type:       float
            mode:       change
            tags:
              - SCR.Device1_Pressure
              - SCR.Device1_Temperature

## Параметры архивации тегов

Параметр | Умолчание | Описание
--- | --- | ---
arcval.robo | `` | Список atg-файлов из roboplant-проекта. В нескольких файлах может использоваться одно и то же имя архивной таблицы (например, ARC_2SEC и ARC_4SEC), при этом значения размера и периода архивирования будут взяты из последнего. Привязка выполнения записи ко времени, кратному period_ms, выполняется при указании period_ms>=60000. Формат atg-файла здесь.
arcval.regex | `` | Набор описаний архивных таблиц с использованием regex-выражений. Внутри данного параметра содержатся имена архивных таблиц. Внутри имени архивной таблицы, содержится описание архива. Имя таблицы не должно использоваться другими архивами.
Описание архивной таблицы для arcval.regex
mode | `period` | Режим архивирования: `period` и `change`
type | `int16` | Тип поля данных: int16 - SMALLINT int32 - INTEGER int64 - BIGINT float - FLOAT double - DOUBLE PRECISION
size | `604800` | Количество записей в архивной таблице
period_ms | `1000` | Период архивирования, мс. См."Периодичность архивирования"
force_s | `60` | Период обязательной записи. Только для режима `change`.
period_align | `off` | Привязка выполнения записи ко времени, кратному period_ms или force_s для архивов режима `period` или `change` соответственно
tags | `` | Список регулярных выражения, задающих правила отбора тегов. Соответствие определяется в заданной списком последовательности. Символ `~` обозначает исключающее правило.

## Периодичность архивирования

Для robo-архивов, описанных в atg-файлах запись в архивную таблицу выполняется через фиксированное время, указанное в параметре `Period` в файле. Время задается в миллисекундах. Так как модуль arcsvr выполняется задачей, то период архивирования должен быть кратным времеми цикла задачи. Тоже самое применимо и для regex-архивов в режиме `period`.

Для regex-архивов в режиме `change` запись в архивную таблицу выполняется только по изменению хотя бы одного из тегов архива, но не чаще чем через фиксированное время, указанное в `period_ms`. Если указанно время форсированной записи `force_s` отличное от нуля, то запись будет выполнена в любом случае, даже если ни один из тегов не изменился.

## Удаление null-колонок

Поля архивных таблиц автоматически добавляются и удаляются в соответствии с заданным набором тегов (atg-файлами или regex-выражениями).

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

В тоже время возможна ситуация, когда тег был действительно удален, и его поле с null-данными уже не нужно. Избавиться от null-полей поможет команда `m:pack [arcname]`.

    arcval:pack

В данном случае команда, посылаемая модулю с именем arcval, удаляет все null-поля у всех regex-архивов. Также можно указать имя архива для проведения операции только над одной архивной таблицей.

# Архивирование сообщений

В системе может быть более одного одновременно работающих модулей arcsvr, архивирующих сообщения. Каждый модуль должен использовать свою базу данных.

#### Пример конфигурации

    plugin.arcsvr:

      module.arcmes:

        database:   dbmes
        place:      Крупоцех

        arcmes.robo:
          - projects/NRMEL.ams; Элеватор
          - projects/NRMGR.ams; Гречезавод

        arcmes.plain:
          - id:        101
            mestext:   Авария весов
            place:     Размол
            clb_inp:   red
            clf_inp:   white
            clb_out:   $400080
            clf_out:   white
            clb_ack:   gray
            clf_ack:   black
            no_visual: off
            no_affirm: off
            no_out:    off
            no_in:     off
            eventtype: 0
            eventval:  2
            tags:
              - W004_2_1:State; 4.2.1 Весы в/с
              - W004_2_2.State; 4.2.2 Весы 1/с
              - W004_2_3.State; 4.2.3 Весы отруби

          - id:        102
            mestext:   Весы в стопе
            place:     Размол
            colors:    blue;white
            eventtype: 0
            eventval:  0
            tags:
              - W004_2_1:State; 4.2.1 Весы в/с
              - W004_2_2.State; 4.2.2 Весы 1/с
              - W004_2_3.State; 4.2.3 Весы отруби

        arcmes.regex:
          - id:        103
            mestext:   Весы в стопе
            colors:    blue;white
            eventtype: 0
            eventval:  0
            tagdescr:  "Весы {1}"
            tagregex:  "(\\w*)\\..*"
            tags:
              - W.*\.State
              - ~ WOTR.*

## Параметры архивации сообщений

Параметр | Умолчание | Описание
--- | --- | ---
version | `1` | Версия алгоритма архивации сообщений: 1 - старый вариант, 2 - новый (см. )
arcmes.robo | `` | Список ams-файлов из roboplant-проекта. Имя файла указывается через точку с запятой с местом:
    - путь_и_имя_ams-файла[;место]
В нескольких файлах может использоваться сообщения с одинаковыми MesId, при этом остальные параметры сообщения будут взяты из последнего файла. Формат ams-файла здесь.
arcmes.plain | `` | Список описаний простых сообщений (plain).
arcmes.regex | `` | Список описаний regex сообщений
Описание сообщений типа plain и regex
id | `` | Сообщения из этого списка должны иметь уникальные id, не пересекающиеся ни с robo-, ни c plain-сообщениями.
mestext | `` | Текст сообщения
place | `` | Место (участок, цех, подразделение). Произвольный текст
eventtype | `0` | Операция для определения наступления события 0: x = val 1: x >= val 2: x <= val 3: (x & val) = val 4: (x & val) = 0 5: (x & val) > 0 6: ((x & val) > 0) && (x & val) != val 7: by change где `x` - текущее значение тега, `val` - заданное значение в параметре `eventval`
eventval | `1` | Значение для определения наступления события (целое число)
clb_inp | `red` | Цвет фона для входящего сообщения
clf_inp | `white` | Цвет шрифта для входящего сообщения
clb_out | `maroon` | Цвет фона для уходящего сообщения
clf_out | `white` | Цвет шрифта для уходящего сообщения
clb_ack | `gray` | Цвет фона для подтверждения
clf_ack | `black` | Цвет шрифта для подтверждения
colors | `` | Задание цвета в одну строку: `clb_inp`;`clf_inp`;`clb_out`;`clf_out`;`clb_ack`;`clf_ack`
no_visual | `off` | Флаг для визуализации «не отображать в мониторе и строке активных сообщений»
no_affirm | `off` | Флаг для визуализации «без подтверждения»
no_out | `off` | Флаг «не архивировать уходящие» (момент завершения события)
Описание сообщений только типа plain
tags | `` | Список имен тегов с текстовым описанием тегов, указываемым через точку с запятой. В имени тега имя модуля отделяется двоеточием, либо точкой.
Описание сообщений только типа regex
tagdescr | `` | Только для regex. Текст для формирования описания тега. Возможно использовать вставки {N}, где N - номер группы regex-выражения в `tagregex`
tagregex | `` | regex-выражение, применяемое к имени тега для формирования tagdescr
tags | `` | Список регулярных выражения, задающих правила отбора тегов. Соответствие определяется в заданной списком последовательности. Символ `~` обозначает исключающее правило.

## Место

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

## Флаги

В таблице `MESLIST` хранятся типы сообщений. Все сообщения можно разделить на две категории:

- создаваемые архиватором `arcsvr`, т.е. появляющиеся по определенному событию (аварии, уведомления, и т.д.),
- и создаваемые программой визуализации (подтверждения, изменения параметров, фиксация действий оператора).

Для сохранения обратной совместимости с существующими программами визуализации в поле `MESLIST.ALARM` сохраняются битовые флаги типа сообщения:

- b0 = всегда равен 1 и означает, что сообщения данного типа относятся к категории создаваемых arcsvr
- b1 = Флаг для визуализации «не отображать в мониторе и строке активных сообщений»
- b2 = Флаг для визуализации «без подтверждения»
- b3 = Флаг «не архивировать уходящие» (момент завершения события)
- b4 = Флаг «не архивировать входящие» (момент наступления события)
- b5 = всегда равен b3

## Цвета

Для указания цвета можно использовать либо название, либо код десятичном или шестнадцатеричном виде с префиксом `$`:

Название цвета | Hex-значение | Цвет
--- | --- | ---
Aqua | $FFFF00 |
Black | $000000 |
Blue | $FF0000 |
Cream | $F0FBFF |
DarkGrey | $808080 |
Fuchsia | $FF00FF |
Gray | $808080 |
Green | $008000 |
LimeGreen | $00FF00 |
LightGray | $C0C0C0 |
Maroon | $000080 |
MediumGray | $A4A0A0 |
MintGreen | $C0DCC0 |
NavyBlue | $800000 |
OliveGreen | $008080 |
Purple | $800080 |
Red | $0000FF |
Silver | $C0C0C0 |
SkyBlue | $F0CAA6 |
Teal | $808000 |
White | $FFFFFF |
Yellow | $00FFFF |

## Удаление старых сообщений

В архивной таблице `MESSAGES` сообщения сохраняются без циклической перезаписи, и таким образом постоянно накапливаются. Для удаления ненужных данных используется команда `w:sweepmes <year>`. Пример использования:

    arcmes:sweepmes 2016

Данная команда, посылаемая модулю с именем `arcmes`, удаляет все записи старше 2016 года включительно.

## Алгоритм архивации сообщений V2

Для работы по данному алгоритму необходимо пересоздать базу сообщений.

В таблице `MESSAGES` добавлены поля `DTEND` и `DTACK`:

    CREATE TABLE MESSAGES (
        IDM      INTEGER NOT NULL,
        DT       TIMESTAMP,
        DTEND    TIMESTAMP,
        DTACK    TIMESTAMP,
        IDMSG    INTEGER,
        IDTAG    INTEGER,
        IDUSER   INTEGER,
        IDPLACE  INTEGER,
        DATA     VARCHAR(128),
        ACT      CHAR(1),
        CLB      INTEGER,
        CLF      INTEGER
    )

При работе в режиме `version: 1` поля `DTEND` и `DTACK` не используются.

При работе в режиме `version: 2` поля дат имеют следующее назначение:

- `DT` - дата наступления события
- `DTEND` - дата ухода события (перестает быть актуальным). Если `null`, то сообщение считается актуальным.
- `DTACK` - дата подтверждения. Если `null`, то сообщение считается не подтвержденным.

При наступлении события в `MESSAGES` создается запись (сообщение), где `DT` содержит текущую дату, а `DTEND` и `DTACK` содержат null.

При уходе события в `MESSAGES` находится соответствующее актуальное сообщение с `DTEND` = null и прописывается текущая дата в `DTEND`.

В `DTACK` значение прописывает scada-клиент.

Для удобства использования в scada-клиентах в базе данных имеются дополнительные метаобъекты:

- view MESMONITOR - выдает отсортированный список текущих сообщений (используется для мониторинга сообщений)

      CREATE VIEW MESMONITOR(
          IDM,
          ORD,
          DT,
          DTEND,
          DTACK,
          IDPLACE,
          PLACENAME,
          IDUSER,
          USERNAME,
          MESTEXT,
          TAGTEXT,
          DATA,
          FULLTEXT,
          CLB,
          CLF)

- view MESVIEW - выдает отсортированный список всех сообщений (используется для просмотра архива)

      CREATE VIEW MESVIEW(
          IDM,
          DT,
          DTEND,
          DTACK,
          IDPLACE,
          PLACENAME,
          IDUSER,
          USERNAME,
          MESTEXT,
          TAGTEXT,
          DATA,
          FULLTEXT,
          CLB,
          CLF,
          ACT)

- procedure SAVE_MESSAGE - сохраняет текстовое сообщение (используется для фиксации действий пользователя)

      CREATE PROCEDURE SAVE_MESSAGE (
          MSGTEXT VARCHAR(1024),
          TAGTEXT VARCHAR(1023),
          DATATEXT VARCHAR(128),
          IDUSER INTEGER,
          IDPLACE INTEGER,
          CLB INTEGER,
          CLF INTEGER)
      RETURNS (
          IDM INTEGER,
          IDMSG INTEGER,
          IDTAG INTEGER)