[
 {
  "id": "aa0e4b3f0f2e0090",
  "type": "UI-listener",
  "name": "Демо: UI-Panel",
  "path": "/web-client",
  "hb": "30",
  "wholemsg": "true",
  "passcode": ""
 },
 {
  "id": "1760580618b6eca6",
  "type": "udp-config",
  "name": "Демо: матрица",
  "port": "12347",
  "portType": "num",
  "localportType": "random",
  "outport": "",
  "outportType": "num",
  "connectionType": "unicast",
  "ipv": "4",
  "iface": "",
  "group": "",
  "datatype": "utf8",
  "outip": "192.168.1.11",
  "outipType": "str",
  "multicastttl": 1,
  "autoConnect": true,
  "debug": "false",
  "delimiter": "",
  "delimiterTimeout": 0,
  "keepDelimiter": false,
  "bufferSize": 64
 },
 {
  "id": "1ab031db571a416b",
  "type": "device-connection",
  "name": "Демо: матрица",
  "driver": "avcit-phinx",
  "transportType": "udp",
  "keepAlive": false,
  "keepAliveInterval": 30,
  "driverDebug": false,
  "tcpConfig": "",
  "sshConfig": "",
  "udpConfig": "1760580618b6eca6",
  "telnetConfig": "",
  "httpConfig": "",
  "localConfig": "",
  "rs232Config": "",
  "irConfig": "",
  "embeddedConfig": "",
  "wsConfig": "",
  "customParams": {
   "sendGapMs": {
    "type": "num",
    "value": 40
   },
   "ackTimeoutMs": {
    "type": "num",
    "value": 1500
   }
  }
 },
 {
  "id": "91d689ea00f6a303",
  "type": "telnet-config",
  "name": "Демо: звуковой процессор",
  "host": "192.168.1.12",
  "hostType": "str",
  "port": 23,
  "portType": "num",
  "username": "",
  "usernameType": "str",
  "password": "",
  "passwordType": "str",
  "usernamePrompt": "[Ll]ogin[: ]*$",
  "passwordPrompt": "[Pp]assword[: ]*$",
  "shellPrompt": "",
  "appendLineEnding": false,
  "autoConnect": "true",
  "debug": "false",
  "reconnectInterval": 5000,
  "delimiter": "\\r\\n",
  "delimiterTimeout": 0,
  "keepDelimiter": false,
  "bufferSize": 64
 },
 {
  "id": "15203811eaad571c",
  "type": "device-connection",
  "name": "Демо: звуковой процессор",
  "driver": "Tesira",
  "transportType": "telnet",
  "keepAlive": false,
  "keepAliveInterval": 30,
  "driverDebug": false,
  "tcpConfig": "",
  "sshConfig": "",
  "udpConfig": "",
  "telnetConfig": "91d689ea00f6a303",
  "httpConfig": "",
  "localConfig": "",
  "rs232Config": "",
  "irConfig": "",
  "embeddedConfig": "",
  "wsConfig": "",
  "customParams": {}
 },
 {
  "id": "3e40226e00c0299f",
  "type": "ssh-config",
  "name": "Демо: кодек ВКС",
  "host": "192.168.1.13",
  "hostType": "str",
  "port": 22,
  "portType": "num",
  "usernameType": "str",
  "passwordType": "str",
  "autoConnect": "true",
  "debug": "false",
  "reconnectInterval": 5000,
  "privateKey": "",
  "passphrase": "",
  "appendLineEnding": false,
  "shellPrompt": "Last login|\\bready\\b|[$#>]\\s*$",
  "delimiter": "\\n",
  "delimiterTimeout": 0,
  "keepDelimiter": false,
  "bufferSize": 64
 },
 {
  "id": "811a7bdb7a23c17a",
  "type": "device-connection",
  "name": "Демо: кодек ВКС",
  "driver": "vinteo-st",
  "transportType": "ssh",
  "keepAlive": false,
  "keepAliveInterval": 30,
  "driverDebug": false,
  "tcpConfig": "",
  "sshConfig": "3e40226e00c0299f",
  "udpConfig": "",
  "telnetConfig": "",
  "httpConfig": "",
  "localConfig": "",
  "rs232Config": "",
  "irConfig": "",
  "embeddedConfig": "",
  "wsConfig": "",
  "customParams": {}
 },
 {
  "id": "548f33cbd70f15ba",
  "type": "tab",
  "label": "Первая программа",
  "disabled": false,
  "info": "Учебная программа к интерфейсу «Первая программа»: от простого к сложному — правило на кнопку, карта входов, ответ устройства, кнопка-переключатель (switch и JSONata), переход на страницу из программы; на странице «Устройства» — вид элементов по ответам звукового процессора и кодека (значения из ответа). Выделите комментарий блока — пояснение откроется на боковой панели «Информация».\n\nАдреса устройств — заглушки: что настроить после импорта, написано в первом комментарии.",
  "env": []
 },
 {
  "id": "0dd00b2ec7f180a3",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "d0deb971115bcbf3",
  "name": "Что настроить после импорта",
  "info": "Адреса устройств — заглушки. После импорта откройте конфигурационные узлы (меню → «Конфигурационные\nузлы») и укажите свои: «Демо: матрица» (UDP) — адрес матрицы; «Демо: звуковой процессор» (Telnet) —\nадрес Tesira; «Демо: кодек ВКС» (SSH) — адрес кодека VINTEO ST, логин и пароль кодека. Порты в узлах —\nте, что у этих устройств по умолчанию; если на объекте другие, поменяйте их там же.\nЗвук (блоки 5): Instance Tag DemoLevels и канал 1 — громкость зала в проекте процессора; укажите свои.\nДрайверы avcit-phinx, Tesira и vinteo-st должны быть сохранены на контроллере под этими именами.\nUI-Panel: создаётся узел UI-listener «/web-client» (подпись «Демо: UI-Panel»). Если на контроллере такой\nузел уже есть, переключите на него узлы «События панели» и «Команды панели» и удалите лишний.\nИнтерфейс «Первая программа» должен быть загружен в UI-Designer с теми же именами элементов и страниц.",
  "x": 160,
  "y": 80,
  "wires": [
   []
  ]
 },
 {
  "id": "d0deb971115bcbf3",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Что настроить после импорта",
  "style": {
   "label": true
  },
  "nodes": [
   "0dd00b2ec7f180a3"
  ],
  "x": 40,
  "y": 40,
  "w": 270,
  "h": 80
 },
 {
  "id": "d58d487d25088a84",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "458641693cae0720",
  "name": "Старт: карты",
  "info": "Через 1 с после «Развернуть» узел change кладёт в глобальную память три карты (JSON):\nglobal.fpInputs — «кнопка → параметры матрицы»: { \"Fp_Map_Hdmi1_b\": { \"input\": 1, \"output\": 2 }, … };\nglobal.fpTitles — «вход → название»: { \"1\": \"HDMI 1\", … };\nglobal.fpButtons — «вход → кнопка секции 2»: { \"1\": \"Fp_Map_Hdmi1_b\", … }.\nКлюч карты — имя элемента интерфейса или номер входа: дальше узлы change берут значение по ключу,\nнапример global.fpInputs[msg.payload.object] — запись карты для нажатой кнопки.\nПоменять вход у кнопки или название входа — правка только здесь.",
  "x": 160,
  "y": 260,
  "wires": [
   []
  ]
 },
 {
  "id": "70f03d6304f361c4",
  "type": "inject",
  "z": "548f33cbd70f15ba",
  "g": "458641693cae0720",
  "name": "При запуске",
  "props": [
   {
    "p": "payload"
   }
  ],
  "repeat": "",
  "crontab": "",
  "once": true,
  "onceDelay": "1",
  "topic": "",
  "payload": "",
  "payloadType": "date",
  "x": 160,
  "y": 320,
  "wires": [
   [
    "737d8bdd5a4b1a6f"
   ]
  ]
 },
 {
  "id": "737d8bdd5a4b1a6f",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "458641693cae0720",
  "name": "Карты кнопок и входов",
  "rules": [
   {
    "t": "set",
    "p": "fpInputs",
    "pt": "global",
    "to": "{\"Fp_Map_Hdmi1_b\": {\"input\": 1, \"output\": 2}, \"Fp_Map_Hdmi2_b\": {\"input\": 2, \"output\": 2}, \"Fp_Map_Hdmi3_b\": {\"input\": 3, \"output\": 2}}",
    "tot": "json"
   },
   {
    "t": "set",
    "p": "fpTitles",
    "pt": "global",
    "to": "{\"1\": \"HDMI 1\", \"2\": \"HDMI 2\", \"3\": \"HDMI 3\"}",
    "tot": "json"
   },
   {
    "t": "set",
    "p": "fpButtons",
    "pt": "global",
    "to": "{\"1\": \"Fp_Map_Hdmi1_b\", \"2\": \"Fp_Map_Hdmi2_b\", \"3\": \"Fp_Map_Hdmi3_b\"}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 460,
  "y": 320,
  "wires": [
   []
  ]
 },
 {
  "id": "458641693cae0720",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Старт: карты",
  "style": {
   "label": true
  },
  "nodes": [
   "d58d487d25088a84",
   "70f03d6304f361c4",
   "737d8bdd5a4b1a6f"
  ],
  "x": 40,
  "y": 220,
  "w": 570,
  "h": 140
 },
 {
  "id": "cbc4eba61b03e7be",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "Наглядно: правило на кнопку",
  "info": "Секция 1 интерфейса. У каждой кнопки HDMI своё правило ui - switch (событие push) и свой выход.\nНа каждом выходе — узел change с готовыми параметрами команды route: msg.parameters = { input, output }.\nВсе три change ведут в один device - command «Матрица: подать вход» (команда route).\nПодсветку кнопок ставит сама панель: кнопки — в группе Interlock в UI-Designer.",
  "x": 160,
  "y": 500,
  "wires": [
   []
  ]
 },
 {
  "id": "8d998745d372d0d1",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 560,
  "wires": [
   [
    "27f85270eecb7c62"
   ]
  ]
 },
 {
  "id": "27f85270eecb7c62",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "Кнопки HDMI: по правилу",
  "outputs": 3,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_Hdmi1_b",
    "event": "push",
    "output": 1,
    "uuid": "8d46997f-716f-5ecc-860d-bca31a1efdda"
   },
   {
    "object": "Fp_Hdmi2_b",
    "event": "push",
    "output": 2,
    "uuid": "e562c832-00bd-5d53-9b58-242ffdda1e87"
   },
   {
    "object": "Fp_Hdmi3_b",
    "event": "push",
    "output": 3,
    "uuid": "9d220016-abae-5288-ad8f-2bfd2934e4c9"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 560,
  "wires": [
   [
    "0873757f178582e8"
   ],
   [
    "f5931122258f313f"
   ],
   [
    "f65bf0ae0a8f738b"
   ]
  ]
 },
 {
  "id": "98e9ae24e44e11dd",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "Матрица: подать вход",
  "connection": "1ab031db571a416b",
  "command": "route",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 1060,
  "y": 560,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "0873757f178582e8",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "HDMI 1 → экран",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"input\": 1, \"output\": 1}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 500,
  "wires": [
   [
    "98e9ae24e44e11dd"
   ]
  ]
 },
 {
  "id": "f5931122258f313f",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "HDMI 2 → экран",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"input\": 2, \"output\": 1}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 560,
  "wires": [
   [
    "98e9ae24e44e11dd"
   ]
  ]
 },
 {
  "id": "f65bf0ae0a8f738b",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "7ce45328c1ca73a3",
  "name": "HDMI 3 → экран",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"input\": 3, \"output\": 1}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 620,
  "wires": [
   [
    "98e9ae24e44e11dd"
   ]
  ]
 },
 {
  "id": "7ce45328c1ca73a3",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Наглядно: правило на кнопку",
  "style": {
   "label": true
  },
  "nodes": [
   "cbc4eba61b03e7be",
   "8d998745d372d0d1",
   "27f85270eecb7c62",
   "98e9ae24e44e11dd",
   "0873757f178582e8",
   "f5931122258f313f",
   "f65bf0ae0a8f738b"
  ],
  "x": 40,
  "y": 460,
  "w": 1170,
  "h": 200
 },
 {
  "id": "ae1a8225241d26f3",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "1f62ef8dd091067f",
  "name": "Компактно: карта входов",
  "info": "Секция 2 интерфейса. Одно правило ui - switch по шаблону Fp_Map_*_b ловит все три кнопки;\nимя нажатой приходит в msg.payload.object.\nУзел change «Кнопка → параметры по карте» берёт msg.parameters из глобальной карты:\nglobal.fpInputs[msg.payload.object] — для Fp_Map_Hdmi2_b это { \"input\": 2, \"output\": 2 }.\nДальше — тот же device - command «Матрица: подать вход» (блок «Наглядно»).\nПодсветку кнопок ставит программа по ответу матрицы (блок «Ответ матрицы»).",
  "x": 160,
  "y": 800,
  "wires": [
   []
  ]
 },
 {
  "id": "a0533d16d909a90f",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "1f62ef8dd091067f",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 860,
  "wires": [
   [
    "90cb531f4a3c8b34"
   ]
  ]
 },
 {
  "id": "90cb531f4a3c8b34",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "1f62ef8dd091067f",
  "name": "Кнопки HDMI: по шаблону",
  "outputs": 1,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "pattern": "Fp_Map_*_b",
    "matchMode": "wildcard",
    "event": "push",
    "output": 1
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 860,
  "wires": [
   [
    "0d6afdeaf3dffb37"
   ]
  ]
 },
 {
  "id": "0d6afdeaf3dffb37",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "1f62ef8dd091067f",
  "name": "Кнопка → параметры по карте",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "fpInputs[msg.payload.object]",
    "tot": "global",
    "dc": true
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 860,
  "wires": [
   [
    "98e9ae24e44e11dd"
   ]
  ]
 },
 {
  "id": "1f62ef8dd091067f",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Компактно: карта входов",
  "style": {
   "label": true
  },
  "nodes": [
   "ae1a8225241d26f3",
   "a0533d16d909a90f",
   "90cb531f4a3c8b34",
   "0d6afdeaf3dffb37"
  ],
  "x": 40,
  "y": 760,
  "w": 870,
  "h": 140
 },
 {
  "id": "0ed7aaa0f1cf5a54",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Ответ матрицы: надписи и подсветка",
  "info": "device - response - listener получает ответы матрицы на route: { input, output, ack }.\nДрайвер присылает ответ дважды: ack false — команда отправлена, ack true — матрица подтвердила.\nswitch «Подтверждено?» пропускает только ack true; switch «Какой выход?» разводит ответы:\nвыход 1 — экран (надпись секции 1), выход 2 — экран председателя (надпись и подсветка секции 2).\nchange берёт название входа по карте global.fpTitles[msg.payload.input] и кладёт его в msg.topic\nпод именем надписи; api - helper - 2 меняет текст. Нет названия в карте — останется «—».\nДля выхода 2 ещё change «Вход → кнопка» (global.fpButtons) → interlock - 2: кнопка выбрана, остальные — нет.",
  "x": 160,
  "y": 1040,
  "wires": [
   []
  ]
 },
 {
  "id": "d33fc092f2571442",
  "type": "device-response-listener",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Матрица: ответы",
  "outputs": 2,
  "connection": "1ab031db571a416b",
  "driverName": "avcit-phinx",
  "totalOutputs": 2,
  "includeMetadata": true,
  "payloadFormat": "full",
  "outputsMap": "{\"route\": 1}",
  "x": 160,
  "y": 1160,
  "wires": [
   [],
   [
    "4d2ab9554304dbdd"
   ]
  ]
 },
 {
  "id": "4d2ab9554304dbdd",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Подтверждено?",
  "outputs": 1,
  "property": "payload.ack",
  "propertyType": "msg",
  "rules": [
   {
    "t": "true"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 460,
  "y": 1160,
  "wires": [
   [
    "dc7dbda3cd7c17e8"
   ]
  ]
 },
 {
  "id": "dc7dbda3cd7c17e8",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Какой выход?",
  "outputs": 2,
  "property": "payload.output",
  "propertyType": "msg",
  "rules": [
   {
    "t": "eq",
    "v": "1",
    "vt": "num"
   },
   {
    "t": "eq",
    "v": "2",
    "vt": "num"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 760,
  "y": 1160,
  "wires": [
   [
    "a15df11e0e1552cb"
   ],
   [
    "485f0f09efee10c5",
    "1930992a7dd992ce"
   ]
  ]
 },
 {
  "id": "a15df11e0e1552cb",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Вход → название экрана",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{}",
    "tot": "json"
   },
   {
    "t": "set",
    "p": "topic.Fp_Screen_val_lb",
    "pt": "msg",
    "to": "fpTitles[msg.payload.input]",
    "tot": "global"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 1100,
  "wires": [
   [
    "27085bcb7abc82b8"
   ]
  ]
 },
 {
  "id": "485f0f09efee10c5",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Вход → название председателя",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{}",
    "tot": "json"
   },
   {
    "t": "set",
    "p": "topic.Fp_Chair_val_lb",
    "pt": "msg",
    "to": "fpTitles[msg.payload.input]",
    "tot": "global"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 1160,
  "wires": [
   [
    "568b0008857b1e41"
   ]
  ]
 },
 {
  "id": "1930992a7dd992ce",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Вход → кнопка",
  "rules": [
   {
    "t": "set",
    "p": "payload",
    "pt": "msg",
    "to": "fpButtons[msg.payload.input]",
    "tot": "global"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 1220,
  "wires": [
   [
    "bbac624a09d6770a"
   ]
  ]
 },
 {
  "id": "27085bcb7abc82b8",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Надпись: экран",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Screen_val_lb",
    "event": "text",
    "uuid": "f329a171-7dad-5bb1-afe0-9f3848bb34d9",
    "value": "—"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 1360,
  "y": 1100,
  "wires": [
   [
    "c5ef1e1a94df7b06"
   ]
  ]
 },
 {
  "id": "568b0008857b1e41",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Надпись: председатель",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Chair_val_lb",
    "event": "text",
    "uuid": "897300bf-170a-5489-acf5-07e386db48b2",
    "value": "—"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 1360,
  "y": 1160,
  "wires": [
   [
    "c5ef1e1a94df7b06"
   ]
  ]
 },
 {
  "id": "bbac624a09d6770a",
  "type": "interlock-2",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Подсветка: карта входов",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "eventType": "uiState",
  "activeStatus": "selected",
  "defaultStatus": "default",
  "buttons": [],
  "array_btn": [
   "Fp_Map_Hdmi1_b",
   "Fp_Map_Hdmi2_b",
   "Fp_Map_Hdmi3_b"
  ],
  "buttons_uuid": [
   "e179237a-5cbf-59c2-abcf-7306f0308da5",
   "b073814b-ecf6-575d-b5c4-02ddcc63db75",
   "47156fa0-9269-5840-82e2-fe284745a12f"
  ],
  "inputProp": "payload",
  "inputPropType": "msg",
  "x": 1360,
  "y": 1220,
  "wires": [
   [
    "c5ef1e1a94df7b06"
   ]
  ]
 },
 {
  "id": "c5ef1e1a94df7b06",
  "type": "UI-Panel out",
  "z": "548f33cbd70f15ba",
  "g": "a52c47ff7e39a5bd",
  "name": "Команды панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 1660,
  "y": 1160,
  "wires": []
 },
 {
  "id": "a52c47ff7e39a5bd",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Ответ матрицы: надписи и подсветка",
  "style": {
   "label": true
  },
  "nodes": [
   "0ed7aaa0f1cf5a54",
   "d33fc092f2571442",
   "4d2ab9554304dbdd",
   "dc7dbda3cd7c17e8",
   "a15df11e0e1552cb",
   "485f0f09efee10c5",
   "1930992a7dd992ce",
   "27085bcb7abc82b8",
   "568b0008857b1e41",
   "bbac624a09d6770a",
   "c5ef1e1a94df7b06"
  ],
  "x": 40,
  "y": 1000,
  "w": 1770,
  "h": 260
 },
 {
  "id": "59b3918f4570069d",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Микрофон через switch",
  "info": "Секция 3, кнопка «через switch» — toggle (флажок «Отметить как toggle» в UI-Designer): панель сама\nпереключает её вид и присылает событие value_changed со значением pressed (нажата — включить микрофон)\nили default (обычная — выключить). switch «Нажата?» по msg.payload.value выбирает один из двух change:\nmsg.command = setMute и msg.parameters = { \"mute\": false } или { \"mute\": true }.",
  "x": 160,
  "y": 1400,
  "wires": [
   []
  ]
 },
 {
  "id": "0913ce1563f5a87b",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 1460,
  "wires": [
   [
    "a0030f2b9b87d374"
   ]
  ]
 },
 {
  "id": "a0030f2b9b87d374",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Микрофон: через switch",
  "outputs": 1,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_MicSwitch_b",
    "event": "value_changed",
    "output": 1,
    "uuid": "550ca711-6867-57ca-a4ce-6044679d02b2"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 1460,
  "wires": [
   [
    "a0e56f0798c1069a"
   ]
  ]
 },
 {
  "id": "a0e56f0798c1069a",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Нажата?",
  "outputs": 2,
  "property": "payload.value",
  "propertyType": "msg",
  "rules": [
   {
    "t": "eq",
    "v": "pressed",
    "vt": "str"
   },
   {
    "t": "eq",
    "v": "default",
    "vt": "str"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 760,
  "y": 1460,
  "wires": [
   [
    "18f3653ac6b1b7be"
   ],
   [
    "950cf5027a458fc1"
   ]
  ]
 },
 {
  "id": "18f3653ac6b1b7be",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Микрофон: включить",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "setMute",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"mute\": false}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 1400,
  "wires": [
   [
    "d5b068cfc587981a"
   ]
  ]
 },
 {
  "id": "950cf5027a458fc1",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Микрофон: выключить",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "setMute",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"mute\": true}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 1520,
  "wires": [
   [
    "d5b068cfc587981a"
   ]
  ]
 },
 {
  "id": "d5b068cfc587981a",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "43395324f6d23e3b",
  "name": "Кодек: микрофон",
  "connection": "811a7bdb7a23c17a",
  "command": "setMute",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 1360,
  "y": 1460,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "43395324f6d23e3b",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Микрофон через switch",
  "style": {
   "label": true
  },
  "nodes": [
   "59b3918f4570069d",
   "0913ce1563f5a87b",
   "a0030f2b9b87d374",
   "a0e56f0798c1069a",
   "18f3653ac6b1b7be",
   "950cf5027a458fc1",
   "d5b068cfc587981a"
  ],
  "x": 40,
  "y": 1360,
  "w": 1470,
  "h": 200
 },
 {
  "id": "34e0949be7c533d2",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "3b7a1581e6ade872",
  "name": "Микрофон через JSONata",
  "info": "Секция 3, кнопка «через JSONata» — тоже toggle, тоже value_changed. Вместо switch и двух change —\nодин change: msg.command = setMute, msg.parameters — выражение JSONata (тип «выражение»):\n{ \"mute\": payload.value = \"default\" }\nВыражение вычисляется по сообщению: payload.value = \"default\" даёт true, если кнопка стала обычной\n(выключить микрофон: mute true), и false, если нажата (pressed — микрофон включён: mute false).",
  "x": 160,
  "y": 1700,
  "wires": [
   []
  ]
 },
 {
  "id": "f39a7fccdb9fc211",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "3b7a1581e6ade872",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 1760,
  "wires": [
   [
    "4c240d31a18787b5"
   ]
  ]
 },
 {
  "id": "4c240d31a18787b5",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "3b7a1581e6ade872",
  "name": "Микрофон: через JSONata",
  "outputs": 1,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_MicJsonata_b",
    "event": "value_changed",
    "output": 1,
    "uuid": "15bc5e95-d5e4-598f-b846-ea3303140a06"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 1760,
  "wires": [
   [
    "f418bf4e27477964"
   ]
  ]
 },
 {
  "id": "f418bf4e27477964",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "3b7a1581e6ade872",
  "name": "setMute по JSONata",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "setMute",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"mute\": payload.value = \"default\"}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 1760,
  "wires": [
   [
    "a223c59198b84233"
   ]
  ]
 },
 {
  "id": "a223c59198b84233",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "3b7a1581e6ade872",
  "name": "Кодек: микрофон (JSONata)",
  "connection": "811a7bdb7a23c17a",
  "command": "setMute",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 1060,
  "y": 1760,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "3b7a1581e6ade872",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Микрофон через JSONata",
  "style": {
   "label": true
  },
  "nodes": [
   "34e0949be7c533d2",
   "f39a7fccdb9fc211",
   "4c240d31a18787b5",
   "f418bf4e27477964",
   "a223c59198b84233"
  ],
  "x": 40,
  "y": 1660,
  "w": 1170,
  "h": 140
 },
 {
  "id": "1c1f3059e4b86f0c",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "51b79c7013f8174e",
  "name": "Переход из программы",
  "info": "Секция 4: кнопка «Открыть подсказку» сама ничего не открывает — у неё нет ссылки в UI-Designer.\nui - switch ловит нажатие (push), api - helper - 2 с типом сообщения navigation и страницей «Подсказка»\nпереключает панель на эту страницу интерфейса. navigation переходит только на страницы (не оверлеи);\nназад со страницы «Подсказка» ведёт кнопка «Закрыть» — ссылка на страницу в UI-Designer.\nИсточник входных данных (msg.topic) в этой цепочке пуст — страница берётся из настроек узла.",
  "x": 160,
  "y": 1940,
  "wires": [
   []
  ]
 },
 {
  "id": "194d91eef60fadf1",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "51b79c7013f8174e",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 2000,
  "wires": [
   [
    "90d639c1c38eb5e7"
   ]
  ]
 },
 {
  "id": "90d639c1c38eb5e7",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "51b79c7013f8174e",
  "name": "Открыть подсказку",
  "outputs": 1,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_Open_b",
    "event": "push",
    "output": 1,
    "uuid": "789f7b7b-31b5-5079-9787-4c9331ff3850"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 2000,
  "wires": [
   [
    "7298fbf653399720"
   ]
  ]
 },
 {
  "id": "7298fbf653399720",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "51b79c7013f8174e",
  "name": "Перейти: Подсказка",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "navigation",
  "object": [
   {
    "name": "Подсказка"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 760,
  "y": 2000,
  "wires": [
   [
    "a751c52c7225392a"
   ]
  ]
 },
 {
  "id": "a751c52c7225392a",
  "type": "UI-Panel out",
  "z": "548f33cbd70f15ba",
  "g": "51b79c7013f8174e",
  "name": "Команды панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 1060,
  "y": 2000,
  "wires": []
 },
 {
  "id": "51b79c7013f8174e",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Переход из программы",
  "style": {
   "label": true
  },
  "nodes": [
   "1c1f3059e4b86f0c",
   "194d91eef60fadf1",
   "90d639c1c38eb5e7",
   "7298fbf653399720",
   "a751c52c7225392a"
  ],
  "x": 40,
  "y": 1900,
  "w": 1170,
  "h": 140
 },
 {
  "id": "c597aef1e7c3499d",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "5. Звук: кнопка и ползунок → процессор",
  "info": "Страница «Устройства», секция 5. Кнопка Fp_Mute_b — toggle (флажок «Отметить как toggle» в UI-Designer):\nпанель сама переключает её вид и присылает value_changed: pressed (нажата, зелёная — звук включить)\nили default (обычная — звук выключить). change «Звук: mute по кнопке» готовит команду setMute,\nпараметры — выражение JSONata:\n{ \"instanceTag\": \"DemoLevels\", \"channel\": 1, \"state\": payload.value = \"default\" }\nstate = true (выключить звук), если кнопка стала обычной.\nПолзунок Fp_Vol_sl присылает при отпускании (slide_end) число от 0 до 1 в msg.payload.value.\nchange «Громкость: 0…1 → дБ» пересчитывает его в децибелы диапазона −60…0 дБ:\n{ \"instanceTag\": \"DemoLevels\", \"channel\": 1, \"level\": $round(payload.value * 60 - 60) }\n— 0 → −60 дБ, 0.5 → −30 дБ, 1 → 0 дБ (общая запись: значение × (max − min) + min).\nОбе команды идут в один device - command «Звук: команда»: имя команды — в msg.command.\nВид кнопки и ползунка здесь не меняется — его ставит ответ процессора (блок «Звук: ответ процессора»).\nDemoLevels и канал 1 — громкость зала в проекте звукового процессора; на своём объекте укажите свои.",
  "x": 160,
  "y": 2180,
  "wires": [
   []
  ]
 },
 {
  "id": "984020b2d4e8cc23",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 2240,
  "wires": [
   [
    "d9c9f76d7e8e8579"
   ]
  ]
 },
 {
  "id": "d9c9f76d7e8e8579",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "Звук: кнопка и ползунок",
  "outputs": 2,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_Mute_b",
    "event": "value_changed",
    "output": 1,
    "uuid": "297bc480-45f7-5271-a99e-4b3d72e3367f"
   },
   {
    "object": "Fp_Vol_sl",
    "event": "slide_end",
    "output": 2,
    "uuid": "574df3b5-b0a9-5a24-8937-b088adf5759a"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 2240,
  "wires": [
   [
    "f7c723fb66fe896a"
   ],
   [
    "700751e447864119"
   ]
  ]
 },
 {
  "id": "f7c723fb66fe896a",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "Звук: mute по кнопке",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "setMute",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"instanceTag\": \"DemoLevels\", \"channel\": 1, \"state\": payload.value = \"default\"}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 2180,
  "wires": [
   [
    "cba17fc5e989e7b3"
   ]
  ]
 },
 {
  "id": "700751e447864119",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "Громкость: 0…1 → дБ",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "setLevel",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"instanceTag\": \"DemoLevels\", \"channel\": 1, \"level\": $round(payload.value * 60 - 60)}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 2300,
  "wires": [
   [
    "cba17fc5e989e7b3"
   ]
  ]
 },
 {
  "id": "cba17fc5e989e7b3",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "bfb8fa436e0c0bbf",
  "name": "Звук: команда",
  "connection": "15203811eaad571c",
  "command": "setMute",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 1060,
  "y": 2240,
  "wires": [
   [
    "df9bea7fdc1d3537"
   ],
   []
  ]
 },
 {
  "id": "bfb8fa436e0c0bbf",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "5. Звук: кнопка и ползунок → процессор",
  "style": {
   "label": true
  },
  "nodes": [
   "c597aef1e7c3499d",
   "984020b2d4e8cc23",
   "d9c9f76d7e8e8579",
   "f7c723fb66fe896a",
   "700751e447864119",
   "cba17fc5e989e7b3"
  ],
  "x": 40,
  "y": 2140,
  "w": 1170,
  "h": 200
 },
 {
  "id": "9f52bce920156114",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Звук: подписка на ответы процессора",
  "info": "Звуковой процессор сам присылает каждое изменение, если на него подписаться (команда subscribe).\nПодписок две — mute и уровень громкости зала (DemoLevels, канал 1). Имя подписки — fpHallMute и fpHallLevel:\nс этим именем (publishToken) процессор присылает изменения, в том числе сделанные не с этой панели.\nПодписаться нужно при запуске и после каждого нового подключения к процессору: первый выход\ndevice - command «Звук: команда» сообщает о подключении (msg.payload.status = connected).\nСразу после подписки процессор присылает текущее значение — панель показывает его без нажатий.",
  "x": 160,
  "y": 2480,
  "wires": [
   []
  ]
 },
 {
  "id": "df9bea7fdc1d3537",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Подключился?",
  "outputs": 1,
  "property": "payload.status",
  "propertyType": "msg",
  "rules": [
   {
    "t": "eq",
    "v": "connected",
    "vt": "str"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 1360,
  "y": 2540,
  "wires": [
   [
    "b00f9740b290b916"
   ]
  ]
 },
 {
  "id": "b00f9740b290b916",
  "type": "delay",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Пауза 2 с",
  "pauseType": "delay",
  "timeout": "2",
  "timeoutUnits": "seconds",
  "rate": "1",
  "nbRateUnits": "1",
  "rateUnits": "second",
  "randomFirst": "1",
  "randomLast": "5",
  "randomUnits": "seconds",
  "drop": false,
  "allowrate": false,
  "outputs": 1,
  "x": 1660,
  "y": 2540,
  "wires": [
   [
    "be981c40ce6d41dc",
    "8753b29feb49e446"
   ]
  ]
 },
 {
  "id": "5231bca05b1f4ad6",
  "type": "inject",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "При запуске",
  "props": [
   {
    "p": "payload"
   }
  ],
  "repeat": "",
  "crontab": "",
  "once": true,
  "onceDelay": "3",
  "topic": "",
  "payload": "",
  "payloadType": "date",
  "x": 1660,
  "y": 2660,
  "wires": [
   [
    "be981c40ce6d41dc",
    "8753b29feb49e446"
   ]
  ]
 },
 {
  "id": "be981c40ce6d41dc",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Подписка: mute зала",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"instanceTag\": \"DemoLevels\", \"attribute\": \"mute\", \"channel\": 1, \"subscriptionName\": \"fpHallMute\", \"minInterval\": 0}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1960,
  "y": 2540,
  "wires": [
   [
    "0f829e06b9c16bc9"
   ]
  ]
 },
 {
  "id": "8753b29feb49e446",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Подписка: громкость зала",
  "rules": [
   {
    "t": "set",
    "p": "parameters",
    "pt": "msg",
    "to": "{\"instanceTag\": \"DemoLevels\", \"attribute\": \"level\", \"channel\": 1, \"subscriptionName\": \"fpHallLevel\", \"minInterval\": 200}",
    "tot": "json"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1960,
  "y": 2660,
  "wires": [
   [
    "0f829e06b9c16bc9"
   ]
  ]
 },
 {
  "id": "0f829e06b9c16bc9",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "65be3b042bd6884f",
  "name": "Звук: подписаться",
  "connection": "15203811eaad571c",
  "command": "subscribe",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 2260,
  "y": 2600,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "65be3b042bd6884f",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Звук: подписка на ответы процессора",
  "style": {
   "label": true
  },
  "nodes": [
   "9f52bce920156114",
   "df9bea7fdc1d3537",
   "b00f9740b290b916",
   "5231bca05b1f4ad6",
   "be981c40ce6d41dc",
   "8753b29feb49e446",
   "0f829e06b9c16bc9"
  ],
  "x": 40,
  "y": 2440,
  "w": 2370,
  "h": 260
 },
 {
  "id": "c675ff0abe89c375",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Звук: ответ процессора → кнопка и ползунок",
  "info": "device - response - listener «Звук: ответы» получает уведомления подписок (тип ответа subscribeNotification):\nmsg.payload = { \"publishToken\": \"fpHallLevel\", \"value\": -20, \"valueType\": \"number\", … } — имя подписки и значение.\nЧерез это подключение приходят и уведомления других программ (например, «Демо-зала»): switch «Какая подписка?»\nпропускает только свои — по msg.payload.publishToken.\nmute: value true — звук выключен, false — включён. change «Mute → вид кнопки» (JSONata):\n{ \"Fp_Mute_b\": payload.value ? \"default\" : \"pressed\" } → api - helper - 2 «Кнопка: звук зала».\nУровень: value — дБ. change «Уровень → ползунок и надпись» (JSONata):\n{ \"Fp_Vol_sl\": payload.value, \"Fp_Vol_val_lb\": $round(payload.value) & \" дБ\" }\n→ api - helper - 2 «Громкость: ползунок и надпись». В его карточке Fp_Vol_sl («Числовое значение») Min −60\nи Max 0: дБ из ответа узел сам переводит в положение ползунка 0…1. Без Min и Max сообщение до панели не дойдёт.\nУзел отладки «Что прислал процессор» выключен: включите его — ответы появятся в боковой панели «Отладка».",
  "x": 160,
  "y": 2840,
  "wires": [
   []
  ]
 },
 {
  "id": "0f6e27cb3b75f6da",
  "type": "device-response-listener",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Звук: ответы",
  "outputs": 2,
  "connection": "15203811eaad571c",
  "driverName": "Tesira",
  "totalOutputs": 2,
  "includeMetadata": true,
  "payloadFormat": "full",
  "outputsMap": "{\"subscribeNotification\": 1}",
  "x": 160,
  "y": 2960,
  "wires": [
   [],
   [
    "6e8ea2dd383e8190",
    "f806afff81ca4f0e"
   ]
  ]
 },
 {
  "id": "6e8ea2dd383e8190",
  "type": "debug",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Что прислал процессор",
  "active": false,
  "tosidebar": true,
  "console": false,
  "tostatus": false,
  "complete": "payload",
  "targetType": "msg",
  "statusVal": "",
  "statusType": "auto",
  "x": 460,
  "y": 2840,
  "wires": []
 },
 {
  "id": "f806afff81ca4f0e",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Какая подписка?",
  "outputs": 2,
  "property": "payload.publishToken",
  "propertyType": "msg",
  "rules": [
   {
    "t": "eq",
    "v": "fpHallMute",
    "vt": "str"
   },
   {
    "t": "eq",
    "v": "fpHallLevel",
    "vt": "str"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 460,
  "y": 2960,
  "wires": [
   [
    "b15ceac54556db63"
   ],
   [
    "65c6ed2b16535fe3"
   ]
  ]
 },
 {
  "id": "b15ceac54556db63",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Mute → вид кнопки",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{\"Fp_Mute_b\": payload.value ? \"default\" : \"pressed\"}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 2900,
  "wires": [
   [
    "fcd55cad52f0a911"
   ]
  ]
 },
 {
  "id": "65c6ed2b16535fe3",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Уровень → ползунок и надпись",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{\"Fp_Vol_sl\": payload.value, \"Fp_Vol_val_lb\": $round(payload.value) & \" дБ\"}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 3020,
  "wires": [
   [
    "667c80f3abd14bea"
   ]
  ]
 },
 {
  "id": "fcd55cad52f0a911",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Кнопка: звук зала",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Mute_b",
    "event": "uiState",
    "uuid": "297bc480-45f7-5271-a99e-4b3d72e3367f",
    "value": "default"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 1060,
  "y": 2900,
  "wires": [
   [
    "cf0479820934b0ad"
   ]
  ]
 },
 {
  "id": "667c80f3abd14bea",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Громкость: ползунок и надпись",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Vol_sl",
    "event": "value",
    "uuid": "574df3b5-b0a9-5a24-8937-b088adf5759a",
    "value": "-20",
    "min": "-60",
    "max": "0",
    "step": "60"
   },
   {
    "name": "Fp_Vol_val_lb",
    "event": "text",
    "uuid": "1f728e7a-974a-59be-a1ff-feb5b64c355d",
    "value": "—"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 1060,
  "y": 3020,
  "wires": [
   [
    "cf0479820934b0ad"
   ]
  ]
 },
 {
  "id": "cf0479820934b0ad",
  "type": "UI-Panel out",
  "z": "548f33cbd70f15ba",
  "g": "d119ba4eeadbcfba",
  "name": "Команды панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 1360,
  "y": 2960,
  "wires": []
 },
 {
  "id": "d119ba4eeadbcfba",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "Звук: ответ процессора → кнопка и ползунок",
  "style": {
   "label": true
  },
  "nodes": [
   "c675ff0abe89c375",
   "0f6e27cb3b75f6da",
   "6e8ea2dd383e8190",
   "f806afff81ca4f0e",
   "b15ceac54556db63",
   "65c6ed2b16535fe3",
   "fcd55cad52f0a911",
   "667c80f3abd14bea",
   "cf0479820934b0ad"
  ],
  "x": 40,
  "y": 2800,
  "w": 1470,
  "h": 260
 },
 {
  "id": "a8201c56afa8fb58",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "6. ВКС: кнопки и список → кодек",
  "info": "Страница «Устройства», секция 6. Правила ui - switch: «Контакты» (push), выбор строки списка Fp_Contacts_ls\n(item_selected), «Позвонить», «Завершить» (push). Команду кодеку задаёт change (msg.command) —\ndevice - command «Кодек: команда» один на все кнопки.\nВыбор строки: панель присылает ключ строки — имя контакта — в msg.payload.value. change «Строка → кому звоним»\nзапоминает номер: global.fpNumber = global.fpContacts[msg.payload.value] (карту «имя → номер» сохранил блок\n«ВКС: ответы кодека») и кладёт имя в надпись: msg.topic = { \"Fp_Target_val_lb\": payload.value } (JSONata).\n«Позвонить»: switch «Контакт выбран?» пропускает нажатие, только если номер уже есть (global.fpNumber не пуст);\nchange «Команда: позвонить» — msg.command = dial, msg.parameters.number = global.fpNumber.\nНадпись о звонке здесь не меняется — её ставит ответ кодека (блок «ВКС: ответы кодека»).",
  "x": 160,
  "y": 3200,
  "wires": [
   []
  ]
 },
 {
  "id": "1bc25cbfc86cf35f",
  "type": "UI-Panel in",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "События панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 160,
  "y": 3320,
  "wires": [
   [
    "11e4a5a463b8eec5"
   ]
  ]
 },
 {
  "id": "11e4a5a463b8eec5",
  "type": "ui-switch",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "ВКС: кнопки и список",
  "outputs": 4,
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "rules": [
   {
    "object": "Fp_Contacts_b",
    "event": "push",
    "output": 1,
    "uuid": "6ae29936-b5fd-51b0-afd6-fb36cd0e91a2"
   },
   {
    "object": "Fp_Contacts_ls",
    "event": "item_selected",
    "output": 2,
    "uuid": "eebd512a-99a7-5c9f-af89-7899df775bc1"
   },
   {
    "object": "Fp_Call_b",
    "event": "push",
    "output": 3,
    "uuid": "2ba0c313-ff4a-533e-95ab-04f0ff01b1a9"
   },
   {
    "object": "Fp_Hangup_b",
    "event": "push",
    "output": 4,
    "uuid": "f2abe3e7-0054-5109-8765-4027d41f3749"
   }
  ],
  "checkall": "true",
  "x": 460,
  "y": 3320,
  "wires": [
   [
    "4c71d550c29e0440"
   ],
   [
    "70544b46cf3bdd42"
   ],
   [
    "6820d9b9460635f6"
   ],
   [
    "89a3e4da46161dcf"
   ]
  ]
 },
 {
  "id": "4c71d550c29e0440",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Команда: адресная книга",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "getContacts",
    "tot": "str"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 3200,
  "wires": [
   [
    "758f53695a7c7c00"
   ]
  ]
 },
 {
  "id": "70544b46cf3bdd42",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Строка → кому звоним",
  "rules": [
   {
    "t": "set",
    "p": "fpNumber",
    "pt": "global",
    "to": "fpContacts[msg.payload.value]",
    "tot": "global"
   },
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{\"Fp_Target_val_lb\": payload.value}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 760,
  "y": 3260,
  "wires": [
   [
    "20a89b6b28696945"
   ]
  ]
 },
 {
  "id": "20a89b6b28696945",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Надпись: кому звоним",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Target_val_lb",
    "event": "text",
    "uuid": "e3cec47c-5ccd-5c04-b3ab-c5a1e24c0314",
    "value": "Выберите контакт"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 1060,
  "y": 3260,
  "wires": [
   [
    "c95367842714d751"
   ]
  ]
 },
 {
  "id": "c95367842714d751",
  "type": "UI-Panel out",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Команды панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 1360,
  "y": 3260,
  "wires": []
 },
 {
  "id": "6820d9b9460635f6",
  "type": "switch",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Контакт выбран?",
  "outputs": 1,
  "property": "fpNumber",
  "propertyType": "global",
  "rules": [
   {
    "t": "nnull"
   }
  ],
  "checkall": "false",
  "repair": false,
  "x": 760,
  "y": 3380,
  "wires": [
   [
    "dd84e8cd7c4ed571"
   ]
  ]
 },
 {
  "id": "dd84e8cd7c4ed571",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Команда: позвонить",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "dial",
    "tot": "str"
   },
   {
    "t": "set",
    "p": "parameters.number",
    "pt": "msg",
    "to": "fpNumber",
    "tot": "global"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 3380,
  "wires": [
   [
    "758f53695a7c7c00"
   ]
  ]
 },
 {
  "id": "89a3e4da46161dcf",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Команда: завершить",
  "rules": [
   {
    "t": "set",
    "p": "command",
    "pt": "msg",
    "to": "hangup",
    "tot": "str"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 1060,
  "y": 3440,
  "wires": [
   [
    "758f53695a7c7c00"
   ]
  ]
 },
 {
  "id": "758f53695a7c7c00",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "c629461fac7c4c0b",
  "name": "Кодек: команда",
  "connection": "811a7bdb7a23c17a",
  "command": "getContacts",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 1360,
  "y": 3380,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "c629461fac7c4c0b",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "6. ВКС: кнопки и список → кодек",
  "style": {
   "label": true
  },
  "nodes": [
   "a8201c56afa8fb58",
   "1bc25cbfc86cf35f",
   "11e4a5a463b8eec5",
   "4c71d550c29e0440",
   "70544b46cf3bdd42",
   "20a89b6b28696945",
   "c95367842714d751",
   "6820d9b9460635f6",
   "dd84e8cd7c4ed571",
   "89a3e4da46161dcf",
   "758f53695a7c7c00"
  ],
  "x": 40,
  "y": 3160,
  "w": 1470,
  "h": 320
 },
 {
  "id": "265c2e86a3251444",
  "type": "comment",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "ВКС: ответы кодека → надпись и список",
  "info": "Состояние звонка поток спрашивает у кодека раз в 3 с (getCallInfo). Ответ — тип callInfo:\nmsg.payload.inCall = true (идёт разговор) или false (нет звонка). change «Звонок → текст и цвет» (JSONata)\nготовит полную запись для api - helper - 2 — у одного элемента два события, текст и цвет фона:\n{ \"Fp_Call_val_lb\": { \"text\": payload.inCall ? \"Идёт разговор\" : \"Нет звонка\",\n                     \"backgroundColor\": payload.inCall ? \"#DCFCE7\" : \"#FFFFFF\" } }\nАдресная книга — ответ contacts: msg.payload.list = [{ \"name\": …, \"number\": …, … }, …].\nchange «Контакты → строки списка» (JSONata):\nmsg.topic = { \"Fp_Contacts_ls\": [payload.list.{ name: number }] } — каждая запись становится строкой\n{ \"имя\": \"номер\" }; api - helper - 2 событием «Список (JSON)» заменяет строки Fp_Contacts_ls.\nglobal.fpContacts = payload.list{ name: number } — та же книга одним объектом «имя → номер» (без точки перед {\nJSONata собирает все записи в один объект) — по нему «Позвонить» находит номер выбранной строки.\nОтветы кодека на запросы других программ (например, «Демо-зала») тоже приходят сюда — список и надпись обновятся.\nУзел отладки «Что прислал кодек» выключен: включите его, чтобы увидеть ответы в боковой панели «Отладка».",
  "x": 160,
  "y": 3620,
  "wires": [
   []
  ]
 },
 {
  "id": "27b5f559caedcc8a",
  "type": "inject",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Раз в 3 с",
  "props": [
   {
    "p": "payload"
   }
  ],
  "repeat": "3",
  "crontab": "",
  "once": true,
  "onceDelay": "5",
  "topic": "",
  "payload": "",
  "payloadType": "date",
  "x": 160,
  "y": 3680,
  "wires": [
   [
    "b2577afd12b6d1f8"
   ]
  ]
 },
 {
  "id": "b2577afd12b6d1f8",
  "type": "device-command",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Кодек: состояние звонка",
  "connection": "811a7bdb7a23c17a",
  "command": "getCallInfo",
  "parameters": {},
  "commandMetadata": {},
  "commandParams": [],
  "statusFeedback": true,
  "x": 460,
  "y": 3680,
  "wires": [
   [],
   []
  ]
 },
 {
  "id": "055847206138e015",
  "type": "device-response-listener",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Кодек: ответы",
  "outputs": 3,
  "connection": "811a7bdb7a23c17a",
  "driverName": "vinteo-st",
  "totalOutputs": 3,
  "includeMetadata": true,
  "payloadFormat": "full",
  "outputsMap": "{\"contacts\": 1, \"callInfo\": 2}",
  "x": 160,
  "y": 3800,
  "wires": [
   [],
   [
    "1d5b9e7839febc11",
    "1c658b87fdb9a763"
   ],
   [
    "1d5b9e7839febc11",
    "40770021f19f53c1"
   ]
  ]
 },
 {
  "id": "1d5b9e7839febc11",
  "type": "debug",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Что прислал кодек",
  "active": false,
  "tosidebar": true,
  "console": false,
  "tostatus": false,
  "complete": "payload",
  "targetType": "msg",
  "statusVal": "",
  "statusType": "auto",
  "x": 460,
  "y": 3740,
  "wires": []
 },
 {
  "id": "1c658b87fdb9a763",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Контакты → строки списка",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{\"Fp_Contacts_ls\": [payload.list.{name: number}]}",
    "tot": "jsonata"
   },
   {
    "t": "set",
    "p": "fpContacts",
    "pt": "global",
    "to": "payload.list{name: number}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 460,
  "y": 3800,
  "wires": [
   [
    "e7e93dcdf32d3e27"
   ]
  ]
 },
 {
  "id": "e7e93dcdf32d3e27",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Список контактов",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Contacts_ls",
    "event": "list",
    "uuid": "eebd512a-99a7-5c9f-af89-7899df775bc1",
    "value": "[]"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 760,
  "y": 3800,
  "wires": [
   [
    "c908e8923d2a3352"
   ]
  ]
 },
 {
  "id": "40770021f19f53c1",
  "type": "change",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Звонок → текст и цвет",
  "rules": [
   {
    "t": "set",
    "p": "topic",
    "pt": "msg",
    "to": "{\"Fp_Call_val_lb\": {\"text\": payload.inCall ? \"Идёт разговор\" : \"Нет звонка\", \"backgroundColor\": payload.inCall ? \"#DCFCE7\" : \"#FFFFFF\"}}",
    "tot": "jsonata"
   }
  ],
  "action": "",
  "property": "",
  "from": "",
  "to": "",
  "reg": false,
  "x": 460,
  "y": 3860,
  "wires": [
   [
    "874540207fe829c7"
   ]
  ]
 },
 {
  "id": "874540207fe829c7",
  "type": "api-helper-2",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Надпись: звонок",
  "ui": "Первая программа",
  "interfaceUuid": "012728b9-2cfd-5165-a830-2558318f968f",
  "action_type": "uiState",
  "object": [
   {
    "name": "Fp_Call_val_lb",
    "event": "text",
    "uuid": "9d51cf2a-7fdd-5fbd-8950-44639bd54d03",
    "value": "Нет звонка"
   },
   {
    "name": "Fp_Call_val_lb",
    "event": "backgroundColor",
    "uuid": "9d51cf2a-7fdd-5fbd-8950-44639bd54d03",
    "value": "#FFFFFF"
   }
  ],
  "inputProp": "topic",
  "inputPropType": "msg",
  "debug": false,
  "x": 760,
  "y": 3860,
  "wires": [
   [
    "c908e8923d2a3352"
   ]
  ]
 },
 {
  "id": "c908e8923d2a3352",
  "type": "UI-Panel out",
  "z": "548f33cbd70f15ba",
  "g": "113d0acfba7e7ebd",
  "name": "Команды панели",
  "server": "aa0e4b3f0f2e0090",
  "passcode": "",
  "x": 1060,
  "y": 3830.0,
  "wires": []
 },
 {
  "id": "113d0acfba7e7ebd",
  "type": "group",
  "z": "548f33cbd70f15ba",
  "name": "ВКС: ответы кодека → надпись и список",
  "style": {
   "label": true
  },
  "nodes": [
   "265c2e86a3251444",
   "27b5f559caedcc8a",
   "b2577afd12b6d1f8",
   "055847206138e015",
   "1d5b9e7839febc11",
   "1c658b87fdb9a763",
   "e7e93dcdf32d3e27",
   "40770021f19f53c1",
   "874540207fe829c7",
   "c908e8923d2a3352"
  ],
  "x": 40,
  "y": 3580,
  "w": 1170,
  "h": 320
 }
]