Pull to refresh

Отражение динамики в модели СКУД

Abnormal programming *System Analysis and Design *Algorithms *
В предыдущей статье рассматривалась структурная модель СКУД как совокупности ролей объектов и двойных связей между ними. Такая модель позволяет отразить результаты всех интересующих нас процессов, протекающих в системе. Процессы в системе выражаются через взаимодействия объектов, а результаты взаимодействий запоминаются в связях. Можно сказать, что связи — это память о взаимодействиях, но сами процессы взаимодействия в структурной модели никак не отражаются. Наблюдатель видит взаимодействия через изменения в поведении или изменения в состоянии объектов, которые мы будем называть устройствами. Например, при поднесении карты c RFID меткой к считывателю последний сообщает о считывании звуковым сигналом и миганием светодиода. Это может интерпретироваться как изменение состояния физического считывателя, при этом само взаимодействие между картой и считывателем, собственно чтение, не рассматривается. Предполагается, что считыватель проходит через ряд дискретных состояний. Такие дискретные состояния удобно моделировать при помощи машин состояний, но для этого нужно установить канал между физическим миром и виртуальным миром (компьютерной моделью). Такой канал, управляемый контроллером канала, передает физические сигналы от устройства, которые специальным модулем связи преобразуются в сигналы, управляющие машиной состояний устройства. Канал может быть двухсторонним:




Одно устройство может быть связано с несколькими каналами и один канал может быть связан с несколькими устройствами, при этом обслуживать все каналы может один модуль связи:



Устройства в модели СКУД



Устройствами мы называем объекты, поведение которых может быть описано набором дискретных состояний моделируемых машинами состояний. Определение набора состояний для каждого устройства осуществляется конструктором моделируемой системы.

Машина состояний считывателя



В реализованной СКУД использовались два считывателя. Один считыватель был установлен на турникете, а второй на картоприемнике. При такой схеме расположения считывателей посетитель с разовым пропуском может покинуть зону доступа только при возврате карты через картоприемник: считыватель картоприемника сформирует статус метки Выход разрешен, а считыватель на турникете — Выход запрещен. Оба считывателя обслуживаются двумя каналами, через один канал поступает информация об имени считывателя, а по второму — об имени карты.

Поэтому у считывателя есть следующие дискретные состояния:

  • считыватель готов к получению сигналов;
  • получен имя считывателя;
  • получено имя карты;
  • получены имена считывателя и карты.




Использование отдельного состояния Получены имена считывателя и карты вместо совмещения его с начальным состоянием вызвано тем, что считыватель является частью системы. В этом случае возврат в начальное состояние будет осуществляться по сигналу от турникета.
Переход в эти состояния осуществляются при получении одного из сигналов: определено имя считывателя, определено имя карты, осуществлен переход или сработал таймер (сигнал от машины турникета), получена ошибка. Обозначим эти сигналы для примера следующим образом: определено имя считывателя — nr, определено имя карты — nc, получен сигнал от турникета — ts, получена ошибка — er. Так как в общем случае неизвестно, что определится раньше — имя считывателя или карты, то машина состояний с сигналами и соответствующими переходами будет иметь вид:



Машина реализована очень просто: так как новое состояние однозначно определяется текущим состоянием и сигналом, то в качестве ключа, определяющего переход берется текстовая величина состояние_сигнал. Зная начальное состояние и новое состояние легко определить и переход, который будет задаваться текстовой величиной текущее_состояние#новое_состояние.Тогда для машины считывателя мы получим следующие соответствия между ключом и новым состоянием, а также переходом:

Состояние Сигнал Расшифровка сигнала Ключ Состояние Переход
0 nr Имя считывателя 0_nr 1 0#1
0 nc Имя карты 0_nc 2 0#2
1 nc Имя карты 1_nc 3 1#3
1 er Ошибка 1_er 0 1#0
2 nr Имя считывателя 2_nr 3 2#3
2 er Ошибка 2_er 0 2#0
3 ts Сигнал турникета 3_ts 0 3#0


Другими словами, сигналы и переходы в машине состояний считывателя полностью описываются вектором gen

gen=[[0_nr, 0_nc, 1_nc, 1_er, 2_nr, 2_er, 3_ts], [1, 2, 3, 0, 3, 0, 0]]


Алгоритм работы машины состояний совершенно очевиден (первоначальное состояние задается при запуске программы):



Все действия, которые происходят при изменении состояний, осуществляются только на переходах соответствующими скриптами. Для машины считывателя эти действия приведены в таблице:

Переход Действия
0#1 Определение имени считывателя в системе
0#2 Определение имени карты в системе
1#3, 2#3 Вызов машины турникета (сигналы eo, xo)
1#0, 2#0, 3#0 Действий нет


Приведенная машина используется в случае, когда считыватель работает в режиме идентификации карты посетителя для перехода через турникет. В реализованной СКУД считыватель картоприемника может работать и в режиме регистрации нового посетителя (новой карты). В этом случае взаимодействия между ним и турникетом нет, и приведенная машина работать не будет, так как она не сможет выйти из состояния 3. Чтобы машина в режиме регистрации после определения номера считывателя и номера карты возвращалась в начальное состояние ее нужно подменить на следующую:



А как же быть с тем, что из состояний 1 и 2 можно перейти по двум разным переходам (на этих переходах осуществляются разные действия)? Дадим переходам имена (на рисунке они указаны в ромбах)



Например, между состояниями 1 и 0 два перехода по сигналу nc и по сигналу er. Для единственного перехода он имел имя 1#0, для нескольких переходов будем использовать имена текущее_состояние#имя_перехода#новое_состояние.

Состояние Сигнал Расшифровка сигнала Ключ Состояние Переход
0 nr Имя считывателя 0_nr 1 0#1
0 nr Имя карты 0_nc 2 0#2
1 nc Имя карты 1_nc 0 1#0#0
1 er Ошибка 1_er 0 1#1#0
2 nr Имя считывателя 2_nr 0 2#0#0
2 er Ошибка 2_er 0 2#1#0


Для того, чтобы можно было использовать алгоритм, приведенный выше, изменим правило образования имени состояния в gen[1]: имя_перехода#имя_нового_состояния. Тогда вектор gen, определяющий поведение машины будет иметь вид:

gen=[[0_nr, 0_nc, 1_nc, 1_er, 2_nr, 2_er], [1, 2, 0#0, 1#0, 0#0, 1#0]]


Минимальные изменения алгоритма связаны с определением нового состояния, т.к. nState=gen[1][keyInd] содержит не имя нового состояния, а его комбинацию с именем перехода, но совершенно очевидно, как его найти.
Машина в режиме регистрации на переходах выполняет другие действия, она не общается с турникетом

Переход Действия
0#1 Определение имени считывателя в системе
0#2 Определение имени карты в системе
1#0#0, 2#0#0 Запись новых данных
1#1#0, 2#1#0 Сообщение об ошибке


Машина состояний турникета



Турникет представляет собой «сложное» устройство, в котором есть два замка и устройство фиксирующее переход, обычно это геркон. Есть еще сигнальные лампы, показывающие состояние замков и возможно, источник звука. Один замок назовем входом, а другой — выходом. Так как каждый замок может находиться в одном из двух состояний (открыт/закрыт), то у турникета могут быть следующие состояния:



Управление турникетом осуществляется по командам считывателя, командам управляющего устройства (в нашем случае — тачскрином планшета), а также сигналу геркона. Кроме того, для того, чтобы предотвратить «зависание» системы в случае отказа от перехода (считыватель сработал, замок открылся, а посетитель не прошел), в систему добавлен таймер, который также влияет на переходы в машине турникета.
Переход в эти состояния осуществляются при получении одного из сигналов: открыть вход, открыть выход (от считывателя), закрыть вход/выход (от геркона — турникета), открыть/закрыть вход/выход (от тачскрина), закрыть вход/выход (от таймера):

Состояние Сигнал Расшифровка сигнала Ключ Состояние Переход
0 eo Открыть вход (считыватель) 0_eo 1 0#0#1
0 xo Открыть выход (считыватель) 0_xo 2 0#0#2
0 ep Открыть вход (тачскрин) 0_ep 1 0#1#1
0 xp Открыть выход (тачскрин) 0_xp 2 0#1#2
1 gt Закрыть вход (геркон) 1_gt 0 1#0#0
1 tt Закрыть вход (таймер) 1_tt 0 1#1#0
2 gt Закрыть выход (геркон) 2_gt 0 2#0#0
2 tt Закрыть выход (таймер) 2_tt 0 2#1#0


Машина состояний турникета с сигналами и переходами, приведенными в таблице, будет иметь вид:



Машина турникета выполняет следующие действия на переходах:

Переход Действия
0#0#1, 0#1#1 Открытие входа, включение таймера, вызов машины интерфейса(сигнал eo)
0#0#2, 0#1#2 Открытие выхода, включение таймера, вызов машины интерфейса(сигнал eo)
1#0#0 Закрытие входа, запись данных в связи, вызов машины считывателя (сигнал ts), вызов машины интерфейса (сигнал ts)
1#1#0 Закрытие входа, вызов машины считывателя (сигнал ts), вызов машины интерфейса (сигнал ts)
2#0#0 Закрытие выхода, запись данных в связи, вызов машины считывателя (сигнал ts), вызов машины интерфейса (сигнал ts)
2#1#0 Закрытие выхода, вызов машины считывателя (сигнал ts), вызов машины интерфейса (сигнал ts)


Построенная машина турникета позволяет осуществить односторонний проход в любом направлении при регистрации карты со статусом постоянная или временная на считывателе турникета и выход посетителя с картой со статусом разовая только через ее регистрацию на считывателе картоприемника. Также возможно управление турникетом с планшета (нажатие на стрелку 1 откроет вход, а 2 — выход. Закрытие происходит по сигналам геркона и таймера):



В тоже время, периодически возникают случаи, когда необходимо открытие или закрытие входа/выхода по кнопке безотносительно к наличию карты. Для этого используются «светофоры» слева (вход) и справа (выход). Карты на входе или выходе работают только тогда, когда у соответствующего светофора «горит» желтый свет. Красный сигнал закрывает соответствующий замок и никакой картой его открыть нельзя, а зеленый — наоборот открывает и ни геркон, ни таймер его закрыть не могут.
И теперь возникает вопрос: если при нажатии на зеленую кнопку светофора мы открываем вход, т.е. осуществляем в машине турникета переход в состояние 1, то как предотвратить переход в состояние 0 по сигналу геркона gt или таймера tt? Понятно, что при «машинном» подходе не хочется рассматривать работу с флагами и т.п., а хочется работать с машиной, заданной вектором gen.

Расширим понятие ключа в векторе gen. Добавим в строку для формирование ключа величину, которую будем называть условием, т.е ключ это состояние_сигнал+условие. Определим следующие значения условия в зависимости, какой свет «горит» на светофорах и какой ключ будет для сигналов от геркона gt и таймера tt в состоянии 1:

Светофор Цвет светофора Условие Ключ
Оба светофора Желтый 1_gt, 1_tt
Только вход Не желтый (красный или зеленый) ls 1_gtIs, 1_ttIs
Только выход Не желтый (красный или зеленый) rs 1_gtrs, 1_ttrs
Оба светофора Не желтый (красный или зеленый) bs 1_gtbs, 1_ttbs


Теперь мы знаем ответ на вопрос. После открытия входа зеленой кнопкой левого светофора сигнал от геркона создаст ключ 1_gtIs, а сигнал от таймера — 1_ttIs, которых нет в векторе gen и поэтому никакого перехода не произойдет. Турникет останется в состоянии 1.
Рассмотрим дополнительные переходы в машине турникета связанные с нажатиями на кнопки светофоров. Сигналы от светофора входа обозначим lr — красный, ly- желтый, lg — зеленый, а от светофора выхода — rr — красный, ry- желтый, rg — зеленый.

Состояние Сигнал Расшифровка сигнала Ключ Состояние Переход
0 lg Открыть вход зеленой кнопкой светофора 0_lg, 0_lgls, 0_lgrs,0_lgbs 1 0#2#1
1 lr,ly Закрыть вход красной или желтой кнопкой светофора 1_lrls, 1_lrbs, 1_lyls, 1_lybs
0 1#2#0
0 rg Открыть выход зеленой кнопкой светофора 0_rg, 0_rgls, 0_rgrs,0_rgbs 2 0#2#2
2 ry,rr Закрыть выход красной или желтой кнопкой светофора 2_ryrs,2_rrrs, 2_ryrs,2_rrbs 0 2#2#0
1 rg Открыть выход зеленой кнопкой светофора (при открытом входе) 1_rgls,1_rgbs 3 1#2#3
2 lg Открыть вход зеленой кнопкой светофора (при открытом выходе) 2_lgrs,2_lgbs 3 2#2#3
3 lr,ly Закрыть вход красной или желтой кнопкой светофора 3_lybs,3_lrbs 1 3#2#1
3 ry,rr Закрыть выход красной или желтой кнопкой светофора 3_rybs,3_rrbs 2 3#2#2


Соответствующие переходы в машине состояний:



Полный вектор gen для машины состояний турникета:

gen=[[0_eo, 0_xo, 0_ep, 0_xp, 1_gt, 1_tt, 2_gt, 2_tt, 0_lg, 0_lgls, 0_lgrs, 0_lgbs, 1_lrls, 1_lrbs, 1_lyls, 1_lybs, 
           0_rg, 0_rgls, 0_rgrs, 0_rgbs, 2_ryrs, 2_rrrs, 2_ryrs, 2_rrbs, 1_rgls, 1_rgbs, 2_lgrs, 2_lgbs, 
           3_lybs, 3_lrbs, 3_rybs, 3_rrbs, 1_xols, 1_xpls, 3_gtls, 3_ttls, 2_eors, 2_eprs, 3_gtrs, 3_ttrs], 
        [0#1, 0#2, 1#1, 1#2, 0#0,1#0, 0#0, 1#0, 2#1, 2#1, 2#1, 2#1, 2#0, 2#0, 2#0, 2#0,
          2#2, 2#2, 2#2, 2#2, 2#0, 2#0, 2#0, 2#0, 2#3, 2#3, 2#3, 2#3, 
          2#1, 2#1, 2#2, 2#2, 0#3, 1#3, 0#1, 1#1, 0#3, 1#3, 0#2, 1#2]].


Действия на дополнительных переходах понятны из расшифровок сигнала.

Машина состояний интерфейса



Управление турникетов может осуществляться с планшета и наоборот, состояние интерфейса зависит от сигналов от считывателя и турникета.
Как видно из начального состояния интерфейса (рисунок выше) для управления используется две кнопки в виде стрелок и по три кнопки на каждом светофоре. Стрелки работают только тогда, когда на соответствующем светофоре желтый свет. Если на светофоре красный или зеленый, то стрелка не работает. Другими словами, у светофора есть состояние включен и выключен. Также по два таких же состояния есть и у стрелок.
В итоге получаем следующие возможные состояния интерфейса:

  • все выключено. Ожидаем нажатие на кнопку;
  • включена стрелка-вход;
  • включена стрелка-выход;
  • включен светофор-вход;
  • включен светофор-выход;
  • включены оба светофора;
  • включена стрелка-выход при включенном светофоре-вход;
  • включена стрелка-вход при включенном светофоре-выход.




Соберем, как и ранее все сигналы и переходы в таблицу (укажем сигналы, относящиеся только к левой половине диаграммы, а вектор gen приведем полностью).

Состояние Сигнал Расшифровка сигнала Ключ Состояние Переход
0 ae Нажать на стрелку-вход 0_ae 1 0#0#1
0 eo Открыть вход (считыватель) 0_eo 1 0#1#1
1 ts Закрыть вход (турникет) 1_ts 0 1#0
0 lr Нажать красный сигнал светофора-вход 0_lr 3 0#0#3
0 lg Нажать зеленый сигнал светофора-вход 0_lg 3 0#1#3
3 lr Нажать красный сигнал светофора-вход 3_lr 3 3#0#3
3 lg Нажать зеленый сигнал светофора-вход 3_lg 3 3#1#3
3 ly Нажать желтый сигнал светофора-вход 3_ly 0 3#0
3 rr Нажать красный сигнал светофора-выход 3_rr 5 3#0#5
3 rg Нажать зеленый сигнал светофора-выход 3_rg 5 3#1#5
3 ax Нажать на стрелку-выход 3_ax 6 3#0#6
3 xo Открыть выход (считыватель) 3_xo 6 3#1#6
5 ry Нажать желтый сигнал светофора-выход 5_ry 3 5#3
6 ts Закрыть вход (турникет) 6_ts 3 6#3


Соответствующие переходы в машине:



Полный вектор gen для машины состояний интерфейса:

gen=[[0_ae, 0_eo, 0_ax, 0_ex, 1_ts, 2_ts, 0_lr, 0_lg, 0_rr, 0_rg, 3_ly, 4_ry, 3_ax, 3_xo, 6_ts, 
          	 4_ae, 4_eo, 7_ts, 3_lr, 3_lg, 3_rr, 3_rg, 4_rr, 4_rg, 4_lr, 4_lg, 5_ry, 5_ly, 5_lr, 5_lg, 5_rr, 5_rg],
                    [0#1, 1#1, 0#2, 1#2, 0, 0, 0#3, 1#3, 0#4, 1#4, 0, 0, 0#6, 1#6, 3,
         	 0#7, 1#7, 4, 0#3, 1#3, 0#5, 1#5, 0#4, 1#4, 0#5, 1#5, 3, 4, 0#5, 1#5, 2#5, 3#5]]


Действия на переходах иллюстрируются состояниями интерфейса.



Кроме того, на переходах изменяется условие для машины турникета и происходит ее вызов (сигналы ep,xp,lr,lg,ly,rr,rg,ry):

Переход Условие
0#0#3,0#1#3 ls
3#0
3#0#5,3#1#5 bs
5#3 ls
0#0#4,0#1#4 rs
4#0
4#0#5,4#1#5 bs
5#4 rs


Таким образом, мы построили при помощи трех машин состояний, синхронизирующихся при помощи обменов сигналами, простую динамическую модель СКУД, позволяющую реализовывать достаточно сложную систему управления.
В дальнейшем будет приведен живой пример реализации СКУД, основанной на принципах изложенных в этой и предыдущей статьях.
Tags:
Hubs:
Total votes 7: ↑7 and ↓0 +7
Views 4K
Comments Comments 4