Сигналізація
Важливим елементом будь-якого інтерфейсу візуалізації є сповіщення користувача про порушення — сигналізація. Для спрощення сприйняття, а також через тісний зв'язок візуалізації та сповіщення (як правило, сповіщення доповнюють візуалізацію) вирішено інтегрувати інтерфейс сповіщень у інтерфейс візуалізації. Для цього, у всіх віджетах, передбачається два додаткових атрибути рівня сеансу: "alarm" та "alarmSt". Атрибут "alarm" використовується для формування сигналу віджетом згідно до його логіки, а атрибут "alarmSt" використовується для контролю за фактом сигналізації гілки дерева сеансу.
Атрибут "alarm" є рядком, який має наступний формат: "{lev}|{categ}|{message}|{type}|{tp_arg}"
Де:
- lev — рівень сигналізації: число від 0 до 255;
- categ — категорія сигналу: параметр підсистеми збору, об'єкт, шлях або комбінація;
- message — повідомлення сигналізації;
- type — типи сповіщень, вказуються у вигляді цілого числа (0...7), що містять ознаки способів сповіщень; типові способи сповіщень:
- 1 — візуальне;
- 2 — гудок, часто відбувається через PC-speaker;
- 4 — звуковий сигнал з файлу звуку або синтез мови; якщо у tp_arg вказано ім'я ресурсу звукового файлу, то відтворюється саме він, інакше виконується синтез мови з тексту, вказаного у message.
- tp_arg — аргумент типу; часто використовується для прямого вказання ресурсу звукового сигналу — файл звукового формату, при здійснені звукової сигналізації.
Атрибут "alarmSt" є цілим числом, яке відображає максимальний рівень сигналу та факт квітування гілки дерева сеансу. Формат числа має наступний вигляд:
- перший байт (0...255) характеризує рівень сигналу гілки;
- другий байт вказує тип сповіщення, так як і у атрибуті "alarm";
- третій байт вказує тип несквітованого сповіщення, так як і у атрибуті "alarm";
- четвертий байт має спеціальне значення, яке визначається окремими бітами:
- біт 0 — вказує, встановленням, на факт квітування сповіщень у першому байті;
- біт 1 — вказує, при встановленні його та бита 0, на повернення квітування — включення сповіщення.
Формування сигналу та отримання його візуалізатором.
Формування сигналу здійснюється самим віджетом, шляхом встановлення власного атрибуту "alarm" потрібним чином та, згідно до нього, автоматично встановлюється атрибут "alarmSt" поточного та вищестоящих віджетів. Візуалізатори отримують сповіщення про сигнал за допомогою стандартного механізму сповіщення про зміну атрибутів віджетів.
Враховуючи те, що обробка умов сигналізації здійснюється у віджетах, сторінки, що містять об'єкти сигналізації, повинні виконуватися у фоні, незалежно від відкритості їх на цей момент. Це здійснюється шляхом встановлення ознаки виконання сторінки у фоні.
Хоча механізм сигналізації й побудовано у середовищі візуалізації, можливість формування невізуальних елементів сигналізації залишається, наприклад, шляхом створення сторінки, яка ніколи не буде відкриватися.
Квітація
Квітація (від quietance) — процес підтвердження факту того, що оперативний персонал звернув увагу на порушення у роботі ТП. Зазвичай цей процес передбачає вживання заходів оператором для усунення порушення та натискання відповідної кнопки припинення сигналізації.
Квітація здійснюється шляхом вказання кореня гілки віджетів та типів сповіщення, що дозволяє реалізувати квітацію на боці візуалізатору як за групами, наприклад, за об'єктом сигналізації, так і індивідуально за об'єктом джерела. При цьому можна незалежно квитувати різні типи сигналізацій. Встановлення квітації здійснюється простою модифікацією атрибуту "alarmSt".
Приклад скрипту, для роботи з сигналами, приведено нижче:
//Виокремлення факту наявності сигналізацій різних способів-типів сповіщення
cvt_light_en = alarmSt&0x100; cvt_alarm_en = alarmSt&0x200; cvt_sound_en = alarmSt&0x400;
//Виокремлення факту наявності несквітованих сигналізацій різних способів сповіщення
cvt_light_active = alarmSt&0x10000; cvt_alarm_active = alarmSt&0x20000; cvt_sound_active = alarmSt&0x40000;
//Обробка подій кнопок квітації та квітація різних способів сповіщення
for(ev_rez = "", off = 0; (sval=event.parse(0,"\n",off)).length; ) {
if(sval == "ws_BtPress:/cvt_light") alarmSt = 0x1000001;
else if(sval == "ws_BtPress:/cvt_alarm") alarmSt = 0x1000002;
else if(sval == "ws_BtPress:/cvt_sound") alarmSt = 0x1000004;
else ev_rez += sval + "\n";
}
event = ev_rez;
Зовнішні методи сповіщення
Основним та типовим способом сповіщення є дисплейна світлова сигналізація аварійними кольорами та їх динамікою у елементів візуалізації, яка присутня завжди та не потребує специфічної конфігурації. Однак, часто потрібні сповіщення зовнішнього типу, наприклад: зовнішньою лампою, бузером PC або "ревуном", довільним звуком, синтезованою мовою та інше.
Для здійснення такої можливості, зовнішні способи сповіщення, та відповідні до них типи сповіщення, вільно описуються для серверу візуалізації та самого візуалізатору. На боці серверу візуалізації описується формування/отримання ресурсу сповіщення та саме сповіщення. На боці візуалізатору описується сповіщення згідно ресурсам серверу візуалізації.
Опис правил та сценаріїв зовнішнього сповіщення здійснюється за допомогою користувацьких атрибутів текстового типу для сторінок проєкту візуалізації, які застосовуються при відкритті цих сторінок. Тобто, потенційно, для кожної відкриваної сторінки можна описати власні правила сповіщення, хоча, зазвичай достатньо та описуються загальні правила сповіщення на головній сторінці проєкту — сторінці, яка відкривається одноразово та не закривається при роботі:
- Для серверу/рушія візуалізації, атрибутом "notify{N}" у форматі:
//flags=notifyServ[{DL}][|resource[|queue[|qMergeMess]]];
//resStatic={ResourceFile}
if(doRes) { Текст команди формування ресурсу. }
if(doNtf) { Текст команди сповіщення. }
- Для візуалізатору, атрибутом "notifyVis[Vision|WebVision]{N}" у форматі:
//flags=notify[{DL}][|resource[|queue[|quietanceRet]]];
//name={Ім'я сповіщувача}
//ico={Ім'я іконки}
{ Текст команди сповіщення для будь-якого або конкретного візуалізатору. }
Прапорці:
- notify[{DL}], notifyServ[{DL}] — включає сповіщення з повтором через час DL, якщо вказано; для DL = 0 повтор здійснюється одразу; notifyServ[{DL}] використовується для примусового сповіщення на боці серверу замість візуалізатору із notify[{DL}].
- resource — запитувати-формувати (примусово) ресурс сповіщення у сервера візуалізації, може бути звуковим файлом, текстом або іншими даними формування сповіщення; але наразі сповіщувачі переважно очікують аудіо.
- queue — ресурси сповіщення визначаються не лише за глобальною ознакою порушення та квітації, а й згідно до пріоритетної черги джерел сповіщення-ресурсів. Черга формується на боці серверу візуалізації, а для візуалізаторів вказується необхідність роботи з нею при запиті ресурсів.
- qMergeMess — поєднувати сповіщення у черзі за рівністю сповіщення.
- quietanceRet — можливість відкликання-повернення стишення візуалізатору, тобто, по факту — зворотного включення сповіщення.
Наявність поля "resStatic" вмикає отримання ресурсу безпосередньо із таблиці ресурсів або файлу, вказується у спосіб подібний до примітиву "Медіа".
Змінні обміну:
- en[0,1] — сповіщення ввімкнути (1) або вимкнути (0);
- doNtf[0,1] — виклик сценарію сповіщення;
- doRes[0,1] — виклик сценарію формування ресурсу;
- res — вміст або ім'я файлу з вмістом ресурсу, для зовнішніх сценаріїв;
- resTp — тип ресурсу, на кшталт "audio/ogg"; є поверненням та поміщається до стандартного виходу (для Shell) для doRes;
- mess — повідомлення-параметри формування ресурсу або сповіщення;
- lang — мова поточного користувача або системи;
- prcID — унікальний ідентифікатор процедури (на кшталт "ses_AGLKS_ntf2"), переважно для безпечного створення тимчасових файлів.
Приклади та коментарі до функціювання типових способів сповіщення:
- Бузер (buzzer) на боці візуалізатору (flags=notify0) або серверу візуалізації (flags=notifyServ0) із повторенням та контролем програвання:
- alarm = "10|Prm||0x02"
- notifyVisVision1 | notify1 =
//flags=notify0|notifyServ0
if(en && (ntfPrg=SYS.system("which beep")).length &&
(SYS.system("test -s "+prcID+".pid",true) || //No PID file
SYS.system("ps -A -o \"pid cmd\" | grep \"^ *$(cat "+prcID+".pid).*"+ntfPrg.parseLine(0)+"\" > /dev/null",true)) ) //No notify already
{
ntfPrg = ntfPrg.parseLine(0);
SYS.system(ntfPrg+" -f 1000 -l 100000 &\necho $! > "+prcID+".pid", true);
}
else if(!en && !SYS.system("test -s "+prcID+".pid",true))
SYS.system("kill $(cat "+prcID+".pid); rm "+prcID+".pid "+prcID+".res;", true);
- notifyVisVision1 | notify1 =
#!/bin/sh
#flags=notify0|notifyServ0
if test $en = 1; then
ntfPrg=$(which beep)
#No PID file || No notify already
if test ! -s $prcID.pid || ! ps -A -o "pid cmd" | grep "^ *$(cat $prcID.pid).*$ntfPrg" > /dev/null; then
$ntfPrg -f 1000 -l 100000 &
echo $! > $prcID.pid
fi
elif test -s $prcID.pid; then
kill $(cat $prcID.pid)
rm $prcID.pid $prcID.res
fi
- Повторюване програвання готового звукового файлу, одного загального, на боці візуалізатору (flags=notify2) або серверу візуалізації (flags=notifyServ2), тривалість аудіо файлу для внутрішньої мови має бути не більше 10 секунд:
- alarm = "10|Prm||0x04"
- notify2 | notifyVisVision2 =
//flags=notify2|notifyServ2
if(en) SYS.system("play -q alarm.ogg");
- notify2 | notifyVisVision2 =
#!/bin/sh
#flags=notify2|notifyServ2
if test $en = 1; then play -q alarm.ogg; fi
- Програвання індивідуального для джерела звукового файлу, на боці візуалізатору, тривалість аудіо файлу для внутрішньої мови має бути не більше 10 секунд:
- alarm = "10|Prm||0x04|res:al_prm1"
- notify2 =
//flags=queue
- notifyVisVision2 =
//flags=notify2|queue
if(doNtf && en && res.length) {
SYS.fileWrite("tmpPlay", res);
SYS.system("play -q tmpPlay");
SYS.fileRemove("tmpPlay");
}
- notifyVisVision2 =
#!/bin/sh
#flags=notify2|queue
if test $doNtf = 1 -a $en = 1 -a -s $res; then play -q $res; fi
- Синтез мови індивідуального сповіщення для джерела на боці візуалізатору, тривалість повідомлення для внутрішньої мови має бути не більше 10 секунд:
- alarm = "10|Prm|Текстове повідомлення синтезу мови|0x04"
- notify2 =
//flags=queue
- notifyVisVision2 =
//flags=notify2|queue
if(doNtf && en && mess.length) {
SYS.fileWrite("tmpForSpeech", mess);
SYS.system("festival --tts tmpForSpeech");
SYS.fileRemove("tmpForSpeech");
}
- notifyVisVision2 =
#!/bin/sh
#flags=notify2|queue
if test $doNtf = 1 -a $en = 1 -a "x" != "x$mess"; then
echo $mess > tmpForSpeech
festival --tts tmpForSpeech
rm tmpForSpeech
fi
- Приготування звукового файлу, одного загального, та його програвання на боці візуалізатору (flags=notifyServ2) або серверу візуалізації (flags=notifyServ2), тривалість аудіо файлу для внутрішньої мови має бути не більше 10 секунд:
- alarm = "10|Prm||0x04"
- notify2 =
//flags=notify2|notifyServ2|resource
if(doRes) res = SYS.fileRead("alarm.ogg"); //Insert here a different method of the generation
if(doNtf && en && res.length) {
SYS.fileWrite("tmpPlay", res);
SYS.system("play -q tmpPlay");
SYS.fileRemove("tmpPlay");
}
- notify2 =
#!/bin/sh
#flags=notify2|notifyServ2|resource
if test $doRes = 1; then cp -f alarm.ogg $res; fi #Insert here a different method of the generation
if test $doNtf = 1 -a $en = 1 -a -s $res; then play -q $res; fi
- notifyVisVision2 =
//flags=notify2|resource
if(en && res.length) {
SYS.fileWrite("tmpPlay", res);
SYS.system("play -q tmpPlay");
SYS.fileRemove("tmpPlay");
}
- notifyVisVision2 =
#!/bin/sh
#flags=notify2|resource
if test $en = 1 -a -s $res; then play -q $res; fi
- Приготування індивідуального для джерела сповіщення звукового файлу через синтез мови, на боці візуалізатору (flags=notify2) або серверу візуалізації (flags=notifyServ2), тривалість повідомлення для внутрішньої мови має бути не більше 10 секунд:
- alarm = "10|Prm|Текстове повідомлення синтезу мови|0x04"
- notify2 =
//flags=notify2|notifyServ2|queue
if(doRes && mess.length) {
SYS.fileWrite("tmpText", mess);
SYS.system("text2wave tmpText -o tmpWAV");
res = SYS.fileRead("tmpWAV");
SYS.fileRemove("tmpText"); SYS.fileRemove("tmpWAV");
}
if(doNtf && en && res.length) {
SYS.fileWrite("tmpPlay", res);
SYS.system("play -q tmpPlay");
SYS.fileRemove("tmpPlay");
}
- notify2 =
#!/bin/sh
#flags=notify2|notifyServ2|queue
if test $doRes = 1 -a "x" != "x$mess"; then
echo $mess > tmpText
text2wave tmpText -o $res
rm tmpText
fi
if test $doNtf = 1 -a $en = 1 -a -s $res; then play -q $res; fi
- notifyVisVision2 =
//flags=notify2|queue
if(en && res.length) {
SYS.fileWrite("tmpPlay", res);
SYS.system("play -q tmpPlay");
SYS.fileRemove("tmpPlay");
}
- notifyVisVision2 =
#!/bin/sh
#flags=notify2|queue
if test $en = 1 -a -s $res; then play -q $res; fi