Hide last authors
| author | version | line-number | content |
|---|---|---|---|
| |
1.1 | 1 | Обработка событий доступа: //Отслеживать количество людей в помещении и при прохождении лица с одноразовым пропуском в пустое помещение генерировать сигнал тревоги.// |
| 2 | |||
| 3 | 1. Создайте фильтр по метке #ПроходСовершен ~[[[doc:ui.Параметры узла.События и фильтры.WebHome]]]. | ||
| 4 | 1. ((( | ||
| 5 | (% style="color: rgb(23,43,77);" %)Скопируйте приведённый ниже код скрипта (% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %)и создайте файл с произвольным именем и расширением **JSON**, например: (%%)//задание_автоматизации_Проход_без_сопровождения.json//(% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %). Для этого удобно использовать простые текстовые редакторы типа Блокнот или Notepad++. Вы также можете обратиться к специалистам компании ИТРИУМ, мы вышлем подготовленный файл.\\ | ||
| 6 | |||
| |
2.1 | 7 | {{code language="java"}} |
| |
1.1 | 8 | import extensions.automation.scripts.AutomationActionScript |
| 9 | import extensions.automation.signals.{AutomationSignal, NeyrossEventAutomationSignal} | ||
| 10 | import models.common.{Event, EventExtensions, FunctionalElement} | ||
| 11 | import models.neyross.Pass | ||
| 12 | import proto.neyross.PassProto | ||
| 13 | import utils.common.{EventBuilder, Tags} | ||
| 14 | import scala.collection.mutable.TreeMap | ||
| 15 | import scala.concurrent.{ExecutionContext, Future} | ||
| 16 | import scala.concurrent.duration._ | ||
| 17 | import java.time.OffsetDateTime | ||
| 18 | import models.pacs.PacsRoomComponent | ||
| 19 | import slick.basic.DatabaseConfig | ||
| 20 | import slick.jdbc.JdbcProfile | ||
| 21 | import akka.actor.ActorRef | ||
| 22 | |||
| 23 | class AdvancedRoomControl extends extensions.automation.scripts.AutomationActionScript { | ||
| 24 | private implicit val ec: ExecutionContext = ctx.executionContext | ||
| 25 | private implicit val dbConfig: DatabaseConfig[JdbcProfile] = ctx.dbConfig | ||
| 26 | |||
| 27 | private val scheduler = ctx.injector.instanceOf[utils.bootstrap.Scheduler] | ||
| 28 | private val eventTransmissionActor: ActorRef = ctx.injectNamedActor(actors.common.EventTransmissionActor.Name) | ||
| 29 | |||
| 30 | private val rooms = new PacsRoomComponent() | ||
| 31 | private val roomsIds = Seq(1l, 45l, 123l, 56l) | ||
| 32 | private val enter2lastRegularPassTime = TreeMap.empty[String, Option[OffsetDateTime]] | ||
| 33 | private var passCount = 0 | ||
| 34 | |||
| 35 | override def init: Future[Unit] = { | ||
| 36 | val dbAction = for { | ||
| 37 | rooms <- rooms.findInIds(roomsIds) | ||
| 38 | } yield rooms.flatMap(_.enterAccessPoints) | ||
| 39 | ctx.dbRun(dbAction).map(tokens => { | ||
| 40 | enter2lastRegularPassTime.addAll( | ||
| 41 | tokens.map(token => (token, None)) | ||
| 42 | ) | ||
| 43 | }) | ||
| 44 | } | ||
| 45 | |||
| 46 | private def reportIfUnaccompanied(token: String): Future[Unit] = { | ||
| 47 | passCount = passCount + 1 | ||
| 48 | val currentLastRegularPassTime = enter2lastRegularPassTime(token) | ||
| 49 | Future.successful( | ||
| 50 | scheduler.executeOnce(10 seconds)({ | ||
| 51 | if (enter2lastRegularPassTime(token) == currentLastRegularPassTime) { | ||
| 52 | val warningEventBuilder = new EventBuilder | ||
| 53 | val event = warningEventBuilder.setHeadline("Проход без сопровождения") | ||
| 54 | .setDescription(s"Проход пользователя с одноразовым пропуском без сопровождения через точку доступа $token") | ||
| 55 | .addEventTags(Tags.Alarm, Tags.PACS) | ||
| 56 | .build() | ||
| 57 | eventTransmissionActor ! event | ||
| 58 | } | ||
| 59 | })(s"pass_check_$passCount") | ||
| 60 | ) | ||
| 61 | } | ||
| 62 | |||
| 63 | private def handleAccessTaken(pass: Pass, token: String): Future[Unit] = { | ||
| 64 | if (enter2lastRegularPassTime.get(token).nonEmpty) { | ||
| 65 | pass.`type` match { | ||
| 66 | case Some(PassProto.Pass.Type.REGULAR) => | ||
| 67 | Future.successful( | ||
| 68 | enter2lastRegularPassTime.addOne((token, Some(OffsetDateTime.now()))) | ||
| 69 | ) | ||
| 70 | case Some(PassProto.Pass.Type.ONETIME) => | ||
| 71 | enter2lastRegularPassTime(token) match { | ||
| 72 | case Some(lastTime) if lastTime.plusSeconds(10).isBefore(OffsetDateTime.now()) => | ||
| 73 | reportIfUnaccompanied(token) | ||
| 74 | case None => | ||
| 75 | reportIfUnaccompanied(token) | ||
| 76 | case _ => | ||
| 77 | Future.unit | ||
| 78 | } | ||
| 79 | case _ => | ||
| 80 | Future.unit | ||
| 81 | } | ||
| 82 | } else { | ||
| 83 | Future.unit | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | override def onSignal(signal: AutomationSignal): Future[Unit] = { | ||
| 88 | signal match { | ||
| 89 | case NeyrossEventAutomationSignal(eventDto) => | ||
| 90 | val isAccessTakenEvent = eventDto.event.eventTags.getOrElse(Nil).contains(Tags.AccessTaken) | ||
| 91 | if (isAccessTakenEvent) { | ||
| 92 | val passAndTokenOpt = for { | ||
| 93 | passExtension: AnyRef <- eventDto.extensions.get(EventExtensions.EventPass) | ||
| 94 | feExtension: AnyRef <- eventDto.extensions.get(EventExtensions.FunctionalElement) | ||
| 95 | functionalElement = feExtension.asInstanceOf[FunctionalElement] | ||
| 96 | pass = passExtension.asInstanceOf[Pass] | ||
| 97 | } yield (pass, functionalElement.token) | ||
| 98 | passAndTokenOpt match { | ||
| 99 | case Some((pass, token)) => | ||
| 100 | handleAccessTaken(pass, token) | ||
| 101 | case _ => | ||
| 102 | Future.failed(new IllegalArgumentException("unable to get pass or functional element token")) | ||
| 103 | } | ||
| 104 | } else { | ||
| 105 | Future.unit | ||
| 106 | } | ||
| 107 | case _ => | ||
| 108 | Future.unit | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
| 112 | new AdvancedRoomControl | ||
| 113 | {{/code}} | ||
| 114 | ))) | ||
| |
1.3 | 115 | 1. (% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %)В разделе **Автоматизация** нажмите на кнопку **Добавить новое задание [[image:attach:ui.Параметры узла.WebHome@btn_add_new.png||thumbnail="true" height="18"]]**, нажмите на кнопку **Импорт** и укажите путь к подготовленному на предыдущем этапе файлу ~[[[Автоматизация>>doc:ui.Параметры узла.Автоматизация.WebHome||style="" shape="rect"]]].\\ |
| |
1.1 | 116 | 1. В блоке **Параметры сигнала** выберите **По событию**, в поле **Фильтр по событиям** выберите из раскрывающегося списка созданный на предыдущем этапе фильтр. |
| 117 | 1. Нажмите на кнопку **Сохранить задание**. | ||
| 118 | |||
| 119 | Если в помещении нет людей, по факту получения события **ПроходСовершен** по пропуску типа [Разовый], будет формироваться тревожное событие «//Проход без сопровождения//», которое будет отправлено в ленту событий [[doc:neyross.АРМ НЕЙРОСС Центр.WebHome]], также его можно будет отследить в отчёте [[Журнал событий>>doc:neyross.АРМ НЕЙРОСС Отчеты.Шаблоны отчетов.Базовый набор шаблонов.WebHome||anchor="Базовыйнаборшаблонов-Журналсобытий"]]. | ||
| 120 | |||
| 121 | [[image:attach:action_scrypt_example1.png||width="700"]] |