Last modified by superadmin on 2026/06/15 21:58

Show last authors
1 Обработка событий доступа: //Отслеживать количество людей в помещении и при прохождении лица с одноразовым пропуском в пустое помещение генерировать сигнал тревоги.//
2
3 1. Создайте фильтр по метке #ПроходСовершен ~[[[doc:ui.Параметры узла.События и фильтры.WebHome]]].
4 1. (((
5 Скопируйте приведённый ниже код скрипта (% 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
7 {{code language="java"}}
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 )))
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"]]].\\
116 1. В блоке **Параметры сигнала** выберите **По событию**, в поле **Фильтр по событиям** выберите из раскрывающегося списка созданный на предыдущем этапе фильтр.
117 1. Нажмите на кнопку **Сохранить задание**.
118
119 Если в помещении нет людей, по факту получения события **ПроходСовершен** по пропуску типа [Разовый], будет формироваться тревожное событие «//Проход без сопровождения//», которое будет отправлено в ленту событий [[doc:neyross.АРМ НЕЙРОСС Центр.WebHome]], также его можно будет отследить в отчёте [[Журнал событий>>doc:neyross.АРМ НЕЙРОСС Отчеты.Шаблоны отчетов.Базовый набор шаблонов.WebHome||anchor="Базовыйнаборшаблонов-Журналсобытий"]].
120
121 [[image:attach:action_scrypt_example1.png||width="700"]]

Платформа НЕЙРОСС