Перейти к содержанию
Переключить боковую панель
Поиск
Поиск
Пользовательские ссылки
русский
Создать учётную запись
Персональные инструменты
expanded
collapsed
Создать учётную запись
Войти
Pages for logged out editors
узнать больше
Навигация
Вернуться на главный сайт:
wirenboard.com
Навигация
Заглавная страница
Читателям
Как внести правку или задать вопрос
Справочник по синтаксису
Инструменты
Служебные страницы
Версия для печати
Пространства имён
Перевести
Варианты
expanded
collapsed
Просмотры
Статистика по языкам
Статистика группы сообщений
Экспорт
Ещё
expanded
collapsed
Экспорт переводов
Параметры
Группа
1-Wire
ADC
ADC:Измерение сопротивлений - технические детали
Backup power for Wiren Board devices
Bluetooth
BMP085
Buzzer
CAN
CMUX
CODESYS
Consumer IR
Controller hardware revisions
CryptodevATECCx08 Auth
DDM845R
Device Tree
DI
Disassembling the controller case
Documentation
Fast Modbus
First power-on Wiren Board 2.8
Gas sensor WB-MSGR
GPIO
Hardware Overview rev. 2.8-rus
Hardware Watchdog Disable
How To Build Linux Kernel
I/O Mapping Matrix
ILI9341
IMX233-OLinuXino-MICRO
Includes. Relay tuning
Inspektor SCADA
IntraHouse
IO modules
LAN9514
MediaWiki:Sitenotice
MOD-MRF24J40
Modbus
Modbus RTU/TCP Slave
Modbus-client
Modem-stretch
MQTT KNX V.0.1.x
NFC
Node-RED
Notification module
NRF24L01
Pin pull-up
Power Meter WB-MAP12H
Power Meter WB-MAP12H Measuring Parameters
Power Meter WB-MAP12H Measuring Registers
Power over Ethernet
Reg
Relay Module Modbus Management
RS-485
RS-485: Wiring and Connection
RS-485:Configuration via Web Interface
Rule Examples
SC16IS752
Sensors Modbus Management
Serial Port
SIM5300E
SIM68V
SIM900R
SNMP
SSH
SVG-Dashboards
TFT01-2.2SP
UART Communication Settings
UEXT-разъемы
Using Wiren Board with peripheral devices
Using Wiren Board with pulsed output devices
View controller files from your computer
Watchdog
WB 4: Errata
WB 5: Errata
WB 6: Errata
WB 7: Errata
WB AC rev. E1.0
WB AC rev. E2.0
WB Dimmers Modbus Registers Map
WB Modbus Devices Firmware Update
WB SH 3.5: Errata
WB SH 3.5: GPIO List
WB SH 3.5: UEXT2
WB-IMX233-CORE
WB-M1W2 1-Wire to Modbus Temperature Measurement Module
WB-MAI2-mini/CC 4-20mA Modbus Analog Inputs
WB-MAO4 0-10V Modbus Analog Outputs
WB-MCM16 Модуль счетных входов 16-канальный
WB-MCM8 Modbus Count Inputs
WB-MGE Modbus-Ethernet Interface Converter
WB-MIO Modbus Interface Converters
WB-MIO-Modbus-Registers
WB-MIR v1 - Modbus IR Remote Control
WB-MIR v2 - Modbus IR Remote Control
Wb-mqtt-db-cli
Wb-mqtt-serial driver
Wb-mqtt-serial templates
WB-MR3xV and WB-MR6xV Modbus Relay Modules
WB-MR6F Modbus Relay Module
WB-MR: Errata
WB-MRM2-mini Modbus Relay Modules
WB-MRPS6 Modbus Relay Modules
WB-MRWL3 Modbus Relay Modules
WB-MSW v.3 Modbus Sensor
WB-MSW v.4 Modbus Sensor
WB-MSWv 3 registers
WB-MSx Consumer IR Manual
WB-UPS Backup power supply for DIN rails
WB5 root password recovery
WB6 root password recovery
WBC-4G v.2
WBE-DI-DR-3
WBE-MICROSD Extension Module
WBE2-AO-10V-2 Analog Outputs 0-10V Extension Module
WBE2-DI-DR-3 Dry Contact Inputs Extension Module
WBE2-DO-OC-2 Open Collector Outputs Extension Module
WBE2-DO-R6C-1 Relay Extension Module
WBE2-DO-SSR-2 Dry Contact Outputs Extension Module
WBE2-I-1-WIRE 1-Wire Extension Module
WBE2-I-CAN-ISO CAN Extension Module
WBE2-I-KNX KNX Extension Module
WBE2-I-KNX: Errata
WBE2-I-RS232 RS-232 Extension Module
WBE2-I-RS485-ISO RS485 Extension Module
WBE2R-R-GPS GPS/GLONASS Extension Module
WBE2R-R-LORA v.1 Extension Module
WBE2R-R-ZIGBEE v.1 ZigBee Extension Module
WBE2S-MICROSD MicroSD Extension Module
Wbincludes:1-Wire Network
Wbincludes:1-Wire Warning
Wbincludes:Configuration MOD
Wbincludes:Configuration WBC
Wbincludes:GSM Modem Default Connection Parameters
Wbincludes:How to enter
Wbincludes:Installation MOD WBE2
Wbincludes:Installation MOD WBE2R
Wbincludes:Installing Software In Console
Wbincludes:Mount MOD
Wbincludes:Mount Relay
Wbincludes:Peripherals
Wbincludes:Relay Purpose2
Wbincludes:Revision
Wbincludes:Setup MOD
Wbincludes:WB-MSW v.3 Body Painting
Wbincludes:WB-MSW v.3 Functions
Wbincludes:WB-MSW v.4 Difference v.3
Wbincludes:WBC-4G Info
Wbincludes:WBC-4G Specifications
Wbincludes:WebUI Change Access Level
WBIO-AI-DCM-4 I/O Module
WBIO-AI-DV-12 Analog Inputs
WBIO-AI-DV-12/4-20mA Analog Inputs
WBIO-AO-10V-8 Analog Outputs 0-10V
WBIO-DI-DR-14 I/O Module
WBIO-DI-DR-16 I/O Module
WBIO-DI-DR-8 I/O Module
WBIO-DI-HVD-16 16-Channel 230V Detector Module
WBIO-DI-HVD-8 8-Channel 230V Detector Module
WBIO-DI-WD-14 Discrete Inputs
WBIO-DO-HS-8 Discrete Outputs
WBIO-DO-R10A-8 Relay Module
WBIO-DO-R10R-4 Relay Module For Roller Shutter
WBIO-DO-R1G-16 1A Relay Module
WBIO-DO-SSR-8 Discrete Outputs Dry Contact
WBMZ-BATTERY - модуль резервного питания
WBMZ2-BATTERY Backup Power Module
Wellpro
Wi-Fi Old
Wiren Board 2.8. Исходные файлы
Wiren Board 4: GPIO List
Wiren Board 4: Модуль расширения RS-232
Wiren Board 4:Аппаратная часть
Wiren Board 4:Первое включение
Wiren Board 5.1: GPIO List
Wiren Board 5.5: GPIO List
Wiren Board 5.8:Список GPIO
Wiren Board 5: Build an image to download in USB Mass-Storage mode
Wiren Board 5: GPIO List
Wiren Board 5: Recovery
Wiren Board 5: Модуль расширения 1-Wire
Wiren Board 5: Модуль расширения ADC
Wiren Board 5: Модуль расширения GPS/Glonass
Wiren Board 5: Модуль расширения RS-232 (WBE-I-RS232)
Wiren Board 5: Модуль расширения RS485-ISO
Wiren Board 5:Аппаратная часть
Wiren Board 5:Первое включение
Wiren Board 5:Схемотехника
Wiren Board 6.1: GPIO List
Wiren Board 6.2: Peripherals
Wiren Board 6.7: Peripherals
Wiren Board 6: Hardware
Wiren Board 6: WBE2R-R-GPS GPS/GLONASS Extension Module:NTPD PPS Setup
Wiren Board 6: Модуль расширения 433MHz (WBE2S-R-433MHZ)
Wiren Board Device Modbus Address
Wiren Board Devices Modbus Management
Wiren Board NETMON-1
Wiren Board NETMON-1: GPIO List
Wiren Board NETMON-2
Wiren Board Smart Home 3.5
Wiren Board Smart Home rev. 3.5
Wiren Board Software
Wiren Board Web Interface
Wiren Board Web Interface 1.0
Wiren Board: Extension Modules
Wirenboard6:InstallingOnTheRemoteSite
Z-Wave
Zabbix
Датчик SHT1x
Движок правил wb-rules 1.7
Доступ к порту RS-485 контроллера Wiren Board с компьютера
Как разрабатывать ПО для Wiren Board
Консоль
Модули расширения
Модуль ввода-вывода с TTL-уровнями (WBIO-DIO-TTL-8)
Модуль выходов "Открытый коллектор" WBE-DO-OС-2
Модуль выходов "сухой контакт" (оптореле) WBE-DO-SSR-2
Модуль наличия напряжения (WBIO-DI-LVD-16)
Модуль наличия напряжения (WBIO-DI-LVD-8)
Модуль расширения CAN (WBE-I-CAN-ISO)
Модуль расширения CAN (WBE-I-CAN-ISO) wb6
Модуль расширения DAC (WBE-AO-10V-2)
Модуль расширения KNX (WBE-I-KNX)
Модуль релейных выходов 3A (WBIO-DO-R3A-8)
Модуль релейных выходов WBE-DO-R6C-1
ПО МКА-3
Первое включение Wiren Board Smart Home
Периферийные устройства
Периферийные устройства с интерфейсом RS-485 серии WB-xxxx
Питание USB-портов
Получение точного времени через GPS/Glonass
Потеря файлов при обновлении ПО
Работа с GPIO
Сounters Pulsar
Сборка образа
Сборка образов прошивки
Создание microSD-карты с образом
Список GPIO
Стандартный образ ФС
Уникальные идентификаторы
Управление низковольтной нагрузкой
Устарело: низкоуровневая работа с ADC в Wiren Board 2, 3 и 4
Участник:EvgenyBoger/CT309-test
Участник:EvgenyBoger/test2
Участник:EvgenyBoger/testtrans
Участник:EvgenyBoger/testtrans2
Участник:EvgenyBoger/Wbincludes:Revision
Шаблон:Node-RED Installing plugin
Шаблон:Testtrans3
Язык
aa - Afar
ab - Abkhazian
abs - Ambonese Malay
ace - Achinese
ady - Adyghe
ady-cyrl - Adyghe (Cyrillic script)
aeb - Tunisian Arabic
aeb-arab - Tunisian Arabic (Arabic script)
aeb-latn - Tunisian Arabic (Latin script)
af - Afrikaans
ak - Akan
aln - Gheg Albanian
alt - Southern Altai
am - Amharic
ami - Amis
an - Aragonese
ang - Old English
anp - Angika
ar - Arabic
arc - Aramaic
arn - Mapuche
arq - Algerian Arabic
ary - Moroccan Arabic
arz - Egyptian Arabic
as - Assamese
ase - American Sign Language
ast - Asturian
atj - Atikamekw
av - Avaric
avk - Kotava
awa - Awadhi
ay - Aymara
az - Azerbaijani
azb - South Azerbaijani
ba - Bashkir
ban - Balinese
ban-bali - ᬩᬲᬩᬮᬶ
bar - Bavarian
bbc - Batak Toba
bbc-latn - Batak Toba (Latin script)
bcc - Southern Balochi
bci - wawle
bcl - Central Bikol
be - Belarusian
be-tarask - Belarusian (Taraškievica orthography)
bg - Bulgarian
bgn - Western Balochi
bh - Bhojpuri
bho - Bhojpuri
bi - Bislama
bjn - Banjar
bm - Bambara
bn - Bangla
bo - Tibetan
bpy - Bishnupriya
bqi - Bakhtiari
br - Breton
brh - Brahui
bs - Bosnian
btm - Batak Mandailing
bto - Iriga Bicolano
bug - Buginese
bxr - Russia Buriat
ca - Catalan
cbk-zam - Chavacano
cdo - Min Dong Chinese
ce - Chechen
ceb - Cebuano
ch - Chamorro
cho - Choctaw
chr - Cherokee
chy - Cheyenne
ckb - Central Kurdish
co - Corsican
cps - Capiznon
cr - Cree
crh - Crimean Turkish
crh-cyrl - Crimean Tatar (Cyrillic script)
crh-latn - Crimean Tatar (Latin script)
cs - Czech
csb - Kashubian
cu - Church Slavic
cv - Chuvash
cy - Welsh
da - Danish
dag - Dagbani
de - German
de-at - Austrian German
de-ch - Swiss High German
de-formal - German (formal address)
din - Dinka
diq - Zazaki
dsb - Lower Sorbian
dtp - Central Dusun
dty - Doteli
dv - Divehi
dz - Dzongkha
ee - Ewe
egl - Emilian
el - Greek
eml - Emiliano-Romagnolo
en - English
en-ca - Canadian English
en-gb - British English
eo - Esperanto
es - Spanish
es-419 - Latin American Spanish
es-formal - español (formal)
et - Estonian
eu - Basque
ext - Extremaduran
fa - Persian
ff - Fulah
fi - Finnish
fit - Tornedalen Finnish
fj - Fijian
fo - Faroese
fr - French
frc - Cajun French
frp - Arpitan
frr - Northern Frisian
fur - Friulian
fy - Western Frisian
ga - Irish
gag - Gagauz
gan - Gan Chinese
gan-hans - Gan (Simplified)
gan-hant - Gan (Traditional)
gcr - Guianan Creole
gd - Scottish Gaelic
gl - Galician
glk - Gilaki
gn - Guarani
gom - Goan Konkani
gom-deva - Goan Konkani (Devanagari script)
gom-latn - Goan Konkani (Latin script)
gor - Gorontalo
got - Gothic
grc - Ancient Greek
gsw - Swiss German
gu - Gujarati
guc - Wayuu
guw - gungbe
gv - Manx
ha - Hausa
hak - Hakka Chinese
haw - Hawaiian
he - Hebrew
hi - Hindi
hif - Fiji Hindi
hif-latn - Fiji Hindi (Latin script)
hil - Hiligaynon
ho - Hiri Motu
hr - Croatian
hrx - Hunsrik
hsb - Upper Sorbian
ht - Haitian Creole
hu - Hungarian
hu-formal - magyar (formal)
hy - Armenian
hyw - Western Armenian
hz - Herero
ia - Interlingua
id - Indonesian
ie - Interlingue
ig - Igbo
ii - Sichuan Yi
ik - Inupiaq
ike-cans - Eastern Canadian (Aboriginal syllabics)
ike-latn - Eastern Canadian (Latin script)
ilo - Iloko
inh - Ingush
io - Ido
is - Icelandic
it - Italian
iu - Inuktitut
ja - Japanese
jam - Jamaican Creole English
jbo - Lojban
jut - Jutish
jv - Javanese
ka - Georgian
kaa - Kara-Kalpak
kab - Kabyle
kbd - Kabardian
kbd-cyrl - Kabardian (Cyrillic script)
kbp - Kabiye
kcg - Tyap
kg - Kongo
khw - Khowar
ki - Kikuyu
kiu - Kirmanjki
kj - Kuanyama
kjp - Eastern Pwo
kk - Kazakh
kk-arab - Kazakh (Arabic script)
kk-cn - Kazakh (China)
kk-cyrl - Kazakh (Cyrillic script)
kk-kz - Kazakh (Kazakhstan)
kk-latn - Kazakh (Latin script)
kk-tr - Kazakh (Turkey)
kl - Kalaallisut
km - Khmer
kn - Kannada
ko - Korean
ko-kp - Korean (North Korea)
koi - Komi-Permyak
kr - Kanuri
krc - Karachay-Balkar
kri - Krio
krj - Kinaray-a
krl - Karelian
ks - Kashmiri
ks-arab - Kashmiri (Arabic script)
ks-deva - Kashmiri (Devanagari script)
ksh - Colognian
ku - Kurdish
ku-arab - Kurdish (Arabic script)
ku-latn - Kurdish (Latin script)
kum - Kumyk
kv - Komi
kw - Cornish
ky - Kyrgyz
la - Latin
lad - Ladino
lb - Luxembourgish
lbe - Lak
lez - Lezghian
lfn - Lingua Franca Nova
lg - Ganda
li - Limburgish
lij - Ligurian
liv - Livonian
lki - Laki
lld - Ladin
lmo - Lombard
ln - Lingala
lo - Lao
loz - Lozi
lrc - Northern Luri
lt - Lithuanian
ltg - Latgalian
lus - Mizo
luz - Southern Luri
lv - Latvian
lzh - Literary Chinese
lzz - Laz
mad - Madurese
mai - Maithili
map-bms - Basa Banyumasan
mdf - Moksha
mg - Malagasy
mh - Marshallese
mhr - Eastern Mari
mi - Maori
min - Minangkabau
mk - Macedonian
ml - Malayalam
mn - Mongolian
mni - Manipuri
mnw - Mon
mo - Moldovan
mr - Marathi
mrh - Mara
mrj - Western Mari
ms - Malay
ms-arab - بهاس ملايو
mt - Maltese
mus - Muscogee
mwl - Mirandese
my - Burmese
myv - Erzya
mzn - Mazanderani
na - Nauru
nah - Nāhuatl
nan - Min Nan Chinese
nap - Neapolitan
nb - Norwegian Bokmål
nds - Low German
nds-nl - Low Saxon
ne - Nepali
new - Newari
ng - Ndonga
nia - Nias
niu - Niuean
nl - Dutch
nl-informal - Nederlands (informeel)
nn - Norwegian Nynorsk
no - Norwegian
nov - Novial
nqo - N’Ko
nrm - Norman
nso - Northern Sotho
nv - Navajo
ny - Nyanja
nys - Nyungar
oc - Occitan
ojb - Ojibwemowin
olo - Livvi-Karelian
om - Oromo
or - Odia
os - Ossetic
pa - Punjabi
pag - Pangasinan
pam - Pampanga
pap - Papiamento
pcd - Picard
pdc - Pennsylvania German
pdt - Plautdietsch
pfl - Palatine German
pi - Pali
pih - Norfuk / Pitkern
pl - Polish
pms - Piedmontese
pnb - Western Punjabi
pnt - Pontic
prg - Prussian
ps - Pashto
pt - Portuguese
pt-br - Brazilian Portuguese
pwn - Paiwan
qu - Quechua
qug - Chimborazo Highland Quichua
rgn - Romagnol
rif - Riffian
rm - Romansh
rmc - Carpathian Romani
rmy - Vlax Romani
rn - Rundi
ro - Romanian
roa-tara - Tarantino
ru - Russian
rue - Rusyn
rup - Aromanian
ruq - Megleno-Romanian
ruq-cyrl - Megleno-Romanian (Cyrillic script)
ruq-latn - Megleno-Romanian (Latin script)
rw - Kinyarwanda
sa - Sanskrit
sah - Sakha
sat - Santali
sc - Sardinian
scn - Sicilian
sco - Scots
sd - Sindhi
sdc - Sassarese Sardinian
sdh - Southern Kurdish
se - Northern Sami
sei - Seri
ses - Koyraboro Senni
sg - Sango
sgs - Samogitian
sh - Serbo-Croatian
shi - Tachelhit
shi-latn - Tachelhit (Latin script)
shi-tfng - Tachelhit (Tifinagh script)
shn - Shan
shy - Shawiya
shy-latn - Shawiya (Latin script)
si - Sinhala
simple - Simple English
sjd - Kildin Sami
sje - Pite Sami
sk - Slovak
skr - Saraiki
skr-arab - Saraiki (Arabic script)
sl - Slovenian
sli - Lower Silesian
sm - Samoan
sma - Southern Sami
smn - Inari Sami
sn - Shona
so - Somali
sq - Albanian
sr - Serbian
sr-ec - Serbian (Cyrillic script)
sr-el - Serbian (Latin script)
srn - Sranan Tongo
ss - Swati
st - Southern Sotho
stq - Saterland Frisian
sty - себертатар
su - Sundanese
sv - Swedish
sw - Swahili
szl - Silesian
szy - Sakizaya
ta - Tamil
tay - Tayal
tcy - Tulu
te - Telugu
tet - Tetum
tg - Tajik
tg-cyrl - Tajik (Cyrillic script)
tg-latn - Tajik (Latin script)
th - Thai
ti - Tigrinya
tk - Turkmen
tl - Tagalog
tly - Talysh
tly-cyrl - толыши
tn - Tswana
to - Tongan
tpi - Tok Pisin
tr - Turkish
tru - Turoyo
trv - Taroko
ts - Tsonga
tt - Tatar
tt-cyrl - Tatar (Cyrillic script)
tt-latn - Tatar (Latin script)
tum - Tumbuka
tw - Twi
ty - Tahitian
tyv - Tuvinian
tzm - Central Atlas Tamazight
udm - Udmurt
ug - Uyghur
ug-arab - Uyghur (Arabic script)
ug-latn - Uyghur (Latin script)
uk - Ukrainian
ur - Urdu
uz - Uzbek
uz-cyrl - Uzbek (Cyrillic script)
uz-latn - Uzbek (Latin script)
ve - Venda
vec - Venetian
vep - Veps
vi - Vietnamese
vls - West Flemish
vmf - Main-Franconian
vo - Volapük
vot - Votic
vro - Võro
wa - Walloon
war - Waray
wls - Wallisian
wo - Wolof
wuu - Wu Chinese
xal - Kalmyk
xh - Xhosa
xmf - Mingrelian
xsy - Saisiyat
yi - Yiddish
yo - Yoruba
yue - Cantonese
za - Zhuang
zea - Zeelandic
zgh - Standard Moroccan Tamazight
zh - Chinese
zh-cn - Chinese (China)
zh-hans - Simplified Chinese
zh-hant - Traditional Chinese
zh-hk - Chinese (Hong Kong)
zh-mo - Chinese (Macau)
zh-my - Chinese (Malaysia)
zh-sg - Chinese (Singapore)
zh-tw - Chinese (Taiwan)
zu - Zulu
Формат
Экспорт для оффлайнового перевода
Экспорт в родном формате
Вывести
<languages/> <div lang="ru" dir="ltr" class="mw-content-ltr"> {{DISPLAYTITLE: Примеры правил}} </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Слежение за контролом === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Это простейшее правило следит за контролом и устанавливает другой контрол в такое же состояние. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Например правило может включать сирену и лампу, если датчик движения заметил движение. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> В примере датчик движения подключен к входу «сухой контакт», контрол типа «switch». Сирена подключена к встроеному реле Wiren Board, а лампа - через релейный блок по Modbus. Когда вход типа "сухой контакт" (выход датчика движения) замкнут, то на лампу и реле подаётся «1», когда выключен - «0». </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Правило срабатывает каждый раз при изменении значения контрола «D1_IN» у устройства «wb-gpio». В код правила передаётся новое значение этого контрола в виде переменной newValue. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule({ whenChanged: "wb-gpio/D1_IN", then: function (newValue, devName, cellName) { dev["wb-gpio/Relay_2"] = newValue; dev["wb-mrm2_6/Relay 1"] = newValue; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> То же самое, но с виртуальным девайсом в качестве источника событий. Пример использования: сценарная кнопка, которая включает/выключает сирену и лампочку. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineVirtualDevice("simple_test", { title: "Simple switch", cells: { enabled: { type: "switch", value: false }, } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("simple_switch", { whenChanged: "simple_test/enabled", then: function (newValue, devName, cellName) { dev["wb-gpio/Relay_2"] = newValue; dev["wb-mrm2_6/"Relay 1"] = newValue; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> } }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Детектор движения c таймаутом === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> На вход D2 подключен детектор движения с выходом «сухой контакт». При обнаружении движения он замыкает D2 и GND, и на соответствующем канале <code>wb-gpio/D2_IN</code> появляется статус «1». </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Освещение подключено через встроенное реле, соответствующий канал <code>wb-gpio/Relay_1</code>. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Правило работает так: * когда движение появляется, свет включается. Если ранее был запущен тридцатисекундный таймер «на выключение», этот таймер отключается; * когда движение пропадает, запускается тридцатисекундный таймер «на выключение». Если ему удаётся дойти до конца, свет выключается. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> var motion_timer_1_timeout_ms = 30 * 1000; var motion_timer_1_id = null; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("motion_detector_1", { whenChanged: "wb-gpio/D2_IN", then: function (newValue, devName, cellName) { if (newValue) { dev["wb-gpio/Relay_1"] = true; if (motion_timer_1_id) { clearTimeout(motion_timer_1_id); } motion_timer_1_id = setTimeout(function () { dev["wb-gpio/Relay_1"] = false; motion_timer_1_id = null; }, motion_timer_1_timeout_ms); } }, }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Создание однотипных правил === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Если таких детекторов движения нужно несколько, то, чтобы не копировать код, можно обернуть создание правила и переменных в функцию: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> function makeMotionDetector(name, timeout_ms, detector_control, relay_control) { var motion_timer_id = null; defineRule(name, { whenChanged: "wb-gpio/" + detector_control, then: function(newValue, devName, cellName) { if (!newValue) { dev["wb-gpio/relay_control"] = true; if (motion_timer_id) { clearTimeout(motion_timer_id); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> motion_timer_id = setTimeout(function() { dev["wb-gpio/relay_control"] = false; motion_timer_id = null; }, timeout_ms); } } }); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> makeMotionDetector("motion_detector_1", 20000, "EXT1_DR1", "EXT2_R3A1"); makeMotionDetector("motion_detector_2", 10000, "EXT1_DR2", "EXT2_R3A2"); makeMotionDetector("motion_detector_3", 10000, "EXT1_DR3", "EXT2_R3A3"); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Активация правила только в определённое время === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Правило как в предыдущем разделе, но выполняется только с 9:30 до 17:10 по UTC. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> var motion_timer_1_timeout_ms = 5 * 1000; var motion_timer_1_id = null; defineRule("motion_detector_1", { whenChanged: "wb-gpio/A1_IN", then: function (newValue, devName, cellName) { var date = new Date(); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // time point marking the beginning of the interval // i.e. "today, at HH:MM". All dates are in UTC! var date_start = new Date(date); date_start.setHours(9); date_start.setMinutes(30); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // time point marking the end of the interval var date_end = new Date(date); date_end.setHours(17); date_end.setMinutes(10); // if time is between 09:30 and 17:10 UTC if ((date > date_start) && (date < date_end)) { if (newValue) { dev["wb-gpio/EXT1_R3A1"] = 1; if (motion_timer_1_id) { clearTimeout(motion_timer_1_id); } motion_timer_1_id = setTimeout(function () { dev["wb-gpio/EXT1_R3A1"] = 0; motion_timer_1_id = null; }, motion_timer_1_timeout_ms); } } } }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Роллеты === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Одно реле включает двигатель, поднимающий шторы, второе реле - включает двигатель, опускающий шторы. Правило следит за тем, чтобы оба реле не были включены одновременно. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Кроме этого, правило отключает двигатели спустя заданное время после включения. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> (function() { //don't touch this line var suffix = "1"; // must be different in different JS files var relay_up_device = "lc103_4"; var relay_up_control = "Relay 1"; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> var relay_down_device = "lc103_4"; var relay_down_control = "Relay 2"; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> var timeout_s = 15; // End of settings var relay_up_timer_id = null; var relay_down_timer_id = null; defineRule( "roller_shutter_up_on" + suffix, { asSoonAs: function() { return dev["relay_up_device/relay_up_control"]; }, then: function () { if (relay_up_timer_id) { relay_up_timer_id = clearTimeout(relay_up_timer_id); }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> relay_up_timer_id = setTimeout(function() { return dev["relay_up_device/relay_up_control"] = 0; }, timeout_s * 1000); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("roller_shutter_down_on" + suffix, { asSoonAs: function() { return dev["relay_down_device/relay_down_control"]; }, then: function () { if (relay_down_timer_id) { relay_down_timer_id = clearTimeout(relay_down_timer_id); }; relay_down_timer_id = setTimeout(function() { dev["relay_down_device/relay_down_control"] = 0; }, timeout_s * 1000); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("roller_shutter_both_on" + suffix, { asSoonAs: function() { return dev["relay_up_device/relay_up_control"] && dev["relay_down_device/relay_down_control"]; }, then: function () { if (relay_up_timer_id) { relay_up_timer_id = clearTimeout(relay_up_timer_id); }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (relay_down_timer_id) { relay_down_timer_id = clearTimeout(relay_down_timer_id); }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> dev[relay_up_device][relay_up_control] = 0; dev["relay_down_device/relay_down_control"] = 0; log("Both roller shutter relays on, switching them off"); } }); })(); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Более старая версия того же сценария демонстрирует использование alias-ов: <syntaxhighlight lang="ecmascript"> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> (function() { defineAlias("relay_up_1", "lc103_4/Relay 1"); defineAlias("relay_down_1", "lc103_4/Relay 2"); var timeout_s = 15; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("roller_shutter_1_up_on", { asSoonAs: function() { return relay_up_1; }, then: function () { setTimeout(function() { relay_up_1 = 0; }, timeout_s * 1000); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("roller_shutter_1_down_on", { asSoonAs: function() { return relay_down_1; }, then: function () { setTimeout(function() { relay_down_1 = 0; }, timeout_s * 1000); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("roller_shutter_1_both_on", { asSoonAs: function() { return relay_up_1 && relay_down_1; }, then: function () { relay_up_1 = 0; relay_down_1 = 0; log("Both roller shutter relays on, switching them off"); } }); })(); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> == Импульсные счетчики == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Импульсный счетчик подключен к WB-MCM8. Выдает 1 импульс на 10 литров воды. При подключении на счетчике были показания 123.120 м³, что равно 123120 литрам воды. У WB-MCM8 при подключении было насчитано 7 импульсов. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> var meterCorrection = 123120 // Корректировочное значение счетчика в литрах var counterCorrection = 7 // Корректировочное значение WB-MCM8 в импульсах var inpulseValue = 10 // Количество литров на один импульс </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineVirtualDevice("water_meters", { // Создаем виртуальный девайс для отображения в веб интерфейсе. title: "Счетчики воды", cells: { water_meter_1: { type: "value", value: 0 }, } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("water_meter_1", { whenChanged: "wb-mcm8_29/Input 1 counter", then: function(newValue, devName, cellName) { if(newValue){ dev["water_meters/water_meter_1"] = ((parseInt(newValue) - counterCorrection) * inpulseValue) + meterCorrection; // Умножаем значение счетчика на количество литров/импульс и прибавляем корректировочное значение. } } }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Обработка счётчиков нажатий == {{Anchor|press-actions}} === Описание === Последние версии прошивок устройств Wiren Board могут распознавать типы нажатий подключённых к входам кнопок и транслировать их по [[Modbus]] на контроллер Wiren Board. О том, как устройство распознаёт типы нажатий, читайте в его документации. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Для обработки нажатий нужно отслеживать на контроллере состояние счётчика нужного типа нажатия и, при его изменении, выполнять действие. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Обработку счётчиков удобно делать на [[wb-rules]], но вы можете использовать любой инструмент для автоматизации, например, [[Node-RED]]. Чтобы ускорить опрос счетчиков, настройте [[RS-485:Configuration via Web Interface#poll-period |период опроса]]. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Примеры === {{YouTube |link=https://youtu.be/C60KB7TCeKg |text= Пример работы правила }} В примере мы используем модуль [[WB-MCM8 Modbus Count Inputs | WB-MCM8]] для управления первым каналом диммера [[WB-MDM3 230V Modbus Dimmer | WB-MDM3]]: # Короткое нажатие включает канал. # Двойное — выключает канал. # Длинное — увеличивает яркость. # Короткое, а затем длинное — уменьшает яркость. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Так как изменение яркости требует растянутое во времени действие, то мы используем таймер. Также мы контролируем состояние входа с кнопкой и прекращаем действие при отпускании кнопки. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="js"> /* ---------------------------- */ /* 1. Single Press Counter: On action*/ /* ---------------------------- */ </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule({ whenChanged: "wb-mcm8_20/Input 1 Single Press Counter", then: function (newValue, devName, cellName) { dev["wb-mdm3_58/K1"] = true; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> /* ---------------------------- */ /* 2. Double Press Counter: Off action*/ /* ---------------------------- */ </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule({ whenChanged: "wb-mcm8_20/Input 1 Double Press Counter", then: function (newValue, devName, cellName) { dev["wb-mdm3_58/K1"] = false; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> /* --------------------------------------- */ /* 3. Long Press Counter: Increase brightness */ /* --------------------------------------- */ </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule({ whenChanged: "wb-mcm8_20/Input 1 Long Press Counter", then: function (newValue, devName, cellName) { // Start a timer that will increase the value of the control startTicker("input1_long_press", 75); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // A rule that will increase the brightness on a timer defineRule({ when: function () { return timers["input1_long_press"].firing; }, then: function () { var i = dev["wb-mdm3_58/Channel 1"]; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (i < 100 && dev["wb-mcm8_20/Input 1"]) { i++ dev["wb-mdm3_58/Channel 1"] = i } else { timers["input1_long_press"].stop(); } } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> /* -------------------------------------------- */ /* 4. Shortlong Press Counter: Decrease brightness */ /* -------------------------------------------- */ </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule({ whenChanged: "wb-mcm8_20/Input 1 Shortlong Press Counter", then: function (newValue, devName, cellName) { // Start a timer that will decrease the value of the control startTicker("input1_shortlong_press", 75); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // A rule that will decrease the brightness on a timer defineRule({ when: function () { return timers["input1_shortlong_press"].firing; }, then: function () { var i = dev["wb-mdm3_58/Channel 1"]; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (i > 0 && dev["wb-mcm8_20/Input 1"]) { i-- dev["wb-mdm3_58/Channel 1"] = i } else { timers["input1_shortlong_press"].stop(); } } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Универсальный модуль для wb-rules === Мы написали модуль для wb-rules [https://github.com/wirenboard/wb-community/tree/main/wb-press-actions wb-press-actions], который облегчает обработку нажатий в ваших скриптах. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Датчик MSW v.3 == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При подключении датчика WB-MSW v.3 к контроллеру Wiren Board есть возможность создавать интересные сценарии, используя данные с датчика. На пример Включать свет по движению, сигнализировать светодиодами о превышении значения СО2 или VOC, Включать Кондиционер, если жарко или увлажнитель воздуха, если воздух слишком сухой. Правила создаются индивидуально под задачи. Здесь мы приведем несколько примеров для понимания принципа работы с датчиком. Больше примеров написания правил можно найти в документации '''[[Движок правил wb-rules]]'''. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === CO2 === При концентрации CO2 меньше 650 - раз в 10 секунд мигаем зеленым. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При концентрации CO2 свыше 651, но меньше 1000 - раз в 5 секунд мигаем желтым. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При концентрации CO2 свыше 1001 - раз в секунду мигаем красным. <div class="mw-collapsible mw-collapsed"; style="width:600px; overflow: hidden;"> <syntaxhighlight lang="ecmascript"> defineRule("msw3_co2", { whenChanged: "wb-msw-v3_97/CO2", then: function(newValue, devName, cellName) { var co2_good = newValue < 650; var co2_middle = newValue < 1000 && newValue > 651; var co2_bad = newValue > 1001; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (co2_good) { dev["devName/Green LED"] = true; dev["devName/Red LED"] = false; dev["devName/LED Period (s)"] = 10; } if (co2_middle) { dev["devName/Green LED"] = true; dev["devName/Red LED"] = true; dev["devName/LED Period (s)"] = 5; } if (co2_bad) { dev["devName/Green LED"] = false; dev["devName/Red LED"] = true; dev["devName/LED Period (s)"] = 1; } } }); </syntaxhighlight> </div> === Max Motion === "Max Motion" - максимальное значение датчика движения за N время. Время от 1 до 60 секунд можно выставить в 282 регистре. По умолчанию 10 секунд. При достижении Max Motion значения 50 проверяем достаточно ли освещена комната, если нет - включаем свет. Как только значение Max Motion упадет ниже 50 свет выключаем. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <div class="NavFrame"> <div class="NavContent"> <syntaxhighlight lang="ecmascript"> defineRule("msw3_Motion", { whenChanged: "wb-msw-v3_97/Max Motion", then: function(newValue, devName, cellName) { if (newValue > 50) { if (dev["wb-msw-v3_97/Illuminance"] < 50) { dev["wb-mr3_11/K1"] = true; } } else { dev["wb-mr3_11/K1"] = false; } } }); </syntaxhighlight> </div> </div> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Системные правила == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Многие показания, которые видны в веб-интерфейсе контроллера из коробки, тоже создаются правилами на движке wb-rules. Их код находится здесь: [https://github.com/wirenboard/wb-rules-system https://github.com/wirenboard/wb-rules-system]. Системные правила собраны в пакет <code>wb-rules-system</code>, сами файлы скриптов на контроллере находятся в папке <code>/usr/share/wb-rules-system/</code>. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Несколько примеров системных правил ниже. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Правило для пищалки === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> [https://github.com/contactless/wb-rules-system/blob/master/rules/buzzer.js Правило] создаёт виртуальное устройство buzzer с ползунками для регулировки громкости и частоты, а также кнопкой включения звука. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineVirtualDevice("buzzer", { title: "Buzzer", // </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> cells: { frequency : { type : "range", value : 3000, max : 7000, }, volume : { type : "range", value : 10, max : 100, }, enabled : { type : "switch", value : false, }, } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // setup pwm2 runShellCommand("echo 2 > /sys/class/pwm/pwmchip0/export"); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function _buzzer_set_params() { var period = parseInt(1.0 / dev.buzzer.frequency * 1E9); var duty_cycle = parseInt(dev.buzzer.volume * 1.0 / 100 * period * 0.5); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> runShellCommand("echo " + period + " > /sys/class/pwm/pwmchip0/pwm2/period"); runShellCommand("echo " + duty_cycle + " > /sys/class/pwm/pwmchip0/pwm2/duty_cycle"); }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_system_buzzer_params", { whenChanged: [ "buzzer/frequency", "buzzer/volume", ], </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> then: function (newValue, devName, cellName) { if ( dev.buzzer.enabled) { _buzzer_set_params(); } } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_system_buzzer_onof", { whenChanged: "buzzer/enabled", then: function (newValue, devName, cellName) { if ( dev.buzzer.enabled) { _buzzer_set_params(); runShellCommand("echo 1 > /sys/class/pwm/pwmchip0/pwm2/enable"); } else { runShellCommand("echo 0 > /sys/class/pwm/pwmchip0/pwm2/enable"); } } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> === Правило для статуса питания === </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> [https://github.com/contactless/wb-rules-system/blob/master/rules/power_status.js Правило] создаёт виртуальное устройство, которое сообщает текущий статус питания. В качестве входных данных используется два канала АЦП: измерение напряжения на аккумуляторе и измерение входного напряжения. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Реализована следующая логика: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 1. Если входное напряжение меньше напряжение на аккумуляторе, то значит плата питается от аккумулятора. В этом случае, также отображается 0V в качестве входного напряжения. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 2. Если входное напряжение больше напряжения на аккумуляторе, то плата работает от внешнего источника питания. В качестве входонго напряжения отображается измерение с канала Vin. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Для иллюстрации правила используют два разных способа срабатывания: по изменению значения контрола (правило _system_track_vin) и по изменению значения выражения (два других). </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineVirtualDevice("power_status", { title: "Power status", // </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> cells: { 'working on battery' : { type : "switch", value : false, readonly : true }, 'Vin' : { type : "voltage", value : 0 } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_system_track_vin", { whenChanged: "wb-adc/Vin", then: function() { if (dev["wb-adc"]["Vin"] < dev["wb-adc/BAT"] ) { dev["power_status/Vin"] = 0; } else { dev["power_status/Vin"] = dev["wb-adc/Vin"] ; } } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_system_dc_on", { asSoonAs: function () { return dev["wb-adc/Vin"] > dev["wb-adc/BAT"]; }, then: function () { dev["power_status/working on battery"] = false; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_system_dc_off", { asSoonAs: function () { return dev["wb-adc/Vin"] <= dev["wb-adc/BAT"]; }, then: function () { dev["power_status/working on battery"] = true; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Термостат == Пример простого термостата из [https://support.wirenboard.com/t/novaya-versiya-dvizhka-pravil/4196/158 темы на портале поддержки]. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="js"> defineVirtualDevice("Termostat", { title: "Termostat", cells: { // =============== Прихожая теплый пол "R01-TS16-1-mode": {//режим 0-ручной 1-по расписанию type: "switch", value: false, }, "R01-TS16-1-setpoint": {//уставка type: "range", value: 25, max: 30, readonly: false }, "R01-TS16-1-lock": {//блокировка в визуализации 0-снята 1-заблокирована type: "switch", value: false, },....... </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> var hysteresis = 0.5; function Termostat(name, temp, setpoint, TS, TS_onoff) { defineRule(name, { whenChanged: temp, //при изменении состояния датчика then: function (newValue, devName, cellName) { //выполняй следующие действия if (dev[TS_onoff]) { if ( newValue < dev[setpoint] - hysteresis) { //если температура датчика меньше уставки - гистерезис dev[TS] = true; } if ( newValue > dev[setpoint] + hysteresis) { //если температура датчика больше виртуальной уставки + гистерезис dev[TS] = false; } } else dev[TS] = false; } }); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Termostat("R01-TS16-1", "A60-M1W3/External Sensor 1", "Termostat/R01-TS16-1-setpoint", "wb-gpio/EXT4_R3A1", "Termostat/R01-TS16-1-onoff"); // Прихожая теплый пол </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> == Отправка команд по RS-485 == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Для примера отправим команду устройству на порт ''/dev/ttyNSC0'' (соответствует аппаратному порту RS-485-ISO на [[Special:MyLanguage/Wiren Board 4|Wiren Board 4]]). Для этого будем использовать движок правил и возможность выполнения произвольных shell-команд. Подробнее см. [https://github.com/contactless/wb-rules#%D0%94%D1%80%D1%83%D0%B3%D0%B8%D0%B5-%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-%D0%B8-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5 в документации]. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> С помощью движка правил создадим виртуальное устройство с контролом типа switch (переключатель). </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При включении переключателя будем отправлять команду (уст. Яркость кан. 00=0xff) для Uniel UCH-M141: <pre> FF FF 0A 01 FF 00 00 0A </pre> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При выключении переключателя будем отправлять команду (уст. Яркость кан. 00=0x00) для Uniel UCH-M141: <pre> FF FF 0A 01 00 00 00 0B </pre> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 1. Настройка порта </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Для настройки порта /dev/ttyNSC0 на скорость 9600 надо выполнить следующую команду </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <pre> stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8 </pre> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 2. Отправка команды </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Отправка данных делается следующей шелл-командой: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <pre> /usr/bin/printf '\xFF\xFF\x0A\x01\xD1\x06\x00\xE2' >/dev/ttyNSC0 </pre> где "\xFF\xFF\x0A\x01\xD1\x06\x00\xE2" - это запись команды "FF FF 0A 01 D1 06 00 E2". </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 3. Создадим в движке правил новый файл с правилами <code>/etc/wb-rules/rs485_cmd.js</code> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Файл можно редактировать с помощью vim, nano или mcedit в сеансе ssh на устройстве, либо залить его с помощью SCP. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <pre> root@wirenboard:~# mcedit /etc/wb-rules/rs485_cmd.js </pre> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 4. Описываем в файле виртуальный девайс </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineVirtualDevice("rs485_cmd", { title: "Send custom command to RS-485 port", cells: { enabled: { type: "switch", value: false }, } }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 5. Перезапускаем wb-rules и проверяем работу </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <pre> root@wirenboard:~# /etc/init.d/wb-rules restart root@wirenboard:~# tail -f /var/log/messages </pre> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> В логе не должно быть сообщений об ошибке (выход через control-c) </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> В веб-интерфейсе в разделе Devices должно появиться новое устройство "Send custom command to RS-485 port". </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 6. Добавим функцию для конфигурирования порта. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> function setup_port() { runShellCommand("stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8"); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 7. Опишем правила на включение и выключение переключателя </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineRule("_rs485_switch_on", { asSoonAs: function () { return dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\xff\\x00\\x00\\x0a' > /dev/ttyNSC0"); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_rs485_switch_off", { asSoonAs: function () { return !dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\x00\\x00\\x00\\x0b' >/dev/ttyNSC0"); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Обратите внимание на двойное экранирование. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 7. Собираем всё вместе </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Полное содержимое файла с правилами: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineVirtualDevice("rs485_cmd", { title: "Send custom command to RS-485 port", cells: { enabled: { type: "switch", value: false }, } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function setup_port() { runShellCommand("stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8"); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_rs485_switch_on", { asSoonAs: function () { return dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\xff\\x00\\x00\\x0a' > /dev/ttyNSC0"); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("_rs485_switch_off", { asSoonAs: function () { return !dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\x00\\x00\\x00\\x0b' >/dev/ttyNSC0"); } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> setTimeout(setup_port, 1000); // запланировать выполнение setup_port() через 1 секунду после старта правил. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Отправка сообщения через Telegram-бота == {{Anchor|telegram}} Сообщения отправляются с использованием [https://core.telegram.org/api#telegram-api Telegram API] через <code>curl</code>. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> var message = "Text"; // напишите свой текст сообщения var token = "TOKEN"; // замените на токен бота var chat_id = CHATID; // замените на свой chat_id var command = 'curl -s -X POST https://api.telegram.org/bot{}/sendMessage -d chat_id={} -d text="{}"'.format(token, chat_id, message); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> runShellCommand(command); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Обработка ошибок в работе с serial-устройствами == Реализована через подписку на все топики '''meta/error'''. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> defineVirtualDevice("meta_error_test", { title: "Metaerordisplay", cells: { topic: { type: "text", value: "", readonly: true }, value: { type: "text", value: "", readonly: true }, } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> trackMqtt("/devices/+/controls/+/meta/error", function(message){ log.info("name: {}, value: {}".format(message.topic, message.value)) if (message.value=="r"){ dev["meta_error_test/topic"] = message.topic; dev["meta_error_test/value"] = message.value; } }); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Пользовательские поля в веб-интерфейсе == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> [[File:Sample-custom-config-1.png|300px|thumb|right|Пример конфигурации]] [[File:Sample-custom-config-2.png|300px|thumb|right|Пример скрипта]] Задача - надо в веб-интерфейсе контроллера Wiren Board вводить уставки температуры и влажности. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Простой способ, это сделать в defineVirtualDevice() поле, ему сделать readonly: false. И оно появится в веб-интерфейсе в Devices как редактируемое, а значение будет сохраняться в движке правил. Но сложную настройку с меню и вариантами так не сделать. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Правильный, но сложный способ — создать новую вкладку в разделе Configs с редактируемыми полями параметров установок . </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Потребуются три файла: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 1. Схема вывода html странички в разделе Configs : /usr/share/wb-mqtt-confed/schemas/test-config.schema.json <syntaxhighlight lang="bash"> { "type":"object", "title":"Test configuration", "description":"Long description configuration", </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> "configFile": { "path":"/etc/test-config.conf", "service":"wb-rules" }, </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> "properties": { "temperature_setpoint": { "type":"number", "title":"Temperature Setpoint (Degrees C)", "default": 25, "propertyOrder": 1, "minimum": 5, "maximum": 40 }, </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> "humidity_setpoint": { "type":"number", "title":"Humidity Setpoint (RH, %)", "default": 60, "propertyOrder": 2, "minimum": 10, "maximum": 95 } }, "required": ["temperature_setpoint", "humidity_setpoint"] } </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 2. Описание конфигурации по умолчанию (при сохранении формы в веб интерфейсе, значения запишутся в этот файл) : /etc/test-config.conf <syntaxhighlight lang="bash"> { "temperature_setpoint": 60, "humidity_setpoint": 14 } </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> 3. Скрипт, обновляющий конфиг : /mnt/data/etc/wb-rules/test-config-script.js </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="bash"> var config = readConfig("/etc/test-config.conf"); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> log("temperature setpoint is: {}".format(config.temperature_setpoint)); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Последний файл можно в том числе редактировать из веб-интерфейса на вкладке Scripts. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> В json файлах описаны схемы вывода html странички браузером, по общепринятому стандарту отображения. Описание ключей тут: json-schema.org. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> После создания файлов, нужно выполнить рестарт сервисов </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="bash"> service wb-mqtt-confed restart </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> service wb-rules restart </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> При нажатии кнопки Save в веб-интерфейсе, будет перезапускаться сервис wb-rules, а значения установок - записываться в правила. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> == Сложные правила с расписаниями == </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Объект - продуктовый магазин. Различные системы магазина управляются по обратной связи от датчиков температуры и с учётом расписания работы магазина. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Для расписаний используются не cron-правила, а обёртка над ними. Обёртка включает и выключает правила, которые, в отличие от cron-правил, выполняются постоянно, будучи включенными. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Например, мы хотим, чтобы освещение было включено с 10 до 17ч. Обёртка (libschedule) будет выполнять правило «включить освещение» раз в минуту с 10 утра до 17 вечера. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Это значит, что даже если контроллер работает с перерывами и пропустил время перехода между расписаниями (10 утра), то контроллер всё равно включит освещение при первой возможности. </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> lib_schedules.js: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> <syntaxhighlight lang="ecmascript"> global.__proto__.Schedules = {}; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> (function(Schedules) { // замыкание </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function todayAt(now, hours, minutes) { var date = new Date(now); // i.e. "today, at HH:MM". All dates are in UTC! date.setHours(hours); date.setMinutes(minutes); return date; } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function checkScheduleInterval(now, start_time, end_time) { var start_date = todayAt(now, start_time[0], start_time[1]); var end_date = todayAt(now, end_time[0], end_time[1]); log("checkScheduleInterval {} {} {}".format(now, start_date, end_date)); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (end_date >= start_date) { if ((now >= start_date) && (now < end_date)) { return true; } } else { // end date is less than start date, // assuming they belong to a different days (e.g. today and tomorrow) </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // option 1: what if it's now the day of "end" date? // in this case the following is enough: if (now < end_date) { return true; } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // well, that seems not to be the case. ok, // option 2: it's the day of "start" date: </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> if (now >= start_date) { return true; } } return false; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function checkSchedule(schedule, now) { if (now == undefined) { now = new Date(); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> for (var i = 0; i < schedule.intervals.length; ++i) { var item = schedule.intervals[i]; if (checkScheduleInterval(now, item[0], item[1])) { log("found matching schedule interval at {}".format(item)); return true; } } return false; } function updateSingleScheduleDevStatus(schedule) { log("updateSingleScheduleDevStatus {}".format(schedule.name)); dev["_schedules"][schedule.name] = checkSchedule(schedule); }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function addScheduleDevCronTasks(schedule) { for (var i = 0; i < schedule.intervals.length; ++i) { var interval = schedule.intervals[i]; for (var j = 0; j < 2; ++j) { // either start or end of the interval var hours = interval[j][0]; var minutes = interval[j][1]; log("cron at " + "0 " + minutes + " " + hours + " * * *"); defineRule("_schedule_dev_{}_{}_{}".format(schedule.name, i, j), { when: cron("0 " + minutes + " " + hours + " * * *"), then: function () { log("_schedule_dev_ {}_{}_{}".format(schedule.name, i, j)); updateSingleScheduleDevStatus(schedule); } }); } } } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> function addScheduleAutoUpdCronTask(schedule) { defineRule("_schedule_auto_upd_{}".format(schedule.name), { when: cron("@every " + schedule.autoUpdate), then: function() { dev._schedules[schedule.name] = dev._schedules[schedule.name]; } }); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> var _schedules = {}; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Schedules.registerSchedule = function(schedule) { _schedules[schedule.name] = schedule; }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Schedules.initSchedules = function() { var params = { title: "Schedule Status", cells: {} }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> for (var schedule_name in _schedules) { if (_schedules.hasOwnProperty(schedule_name)) { var schedule = _schedules[schedule_name]; params.cells[schedule_name] = {type: "switch", value: false, readonly: true}; } }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineVirtualDevice("_schedules", params); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> for (var schedule_name in _schedules) { if (_schedules.hasOwnProperty(schedule_name)) { var schedule = _schedules[schedule_name]; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // setup cron tasks which updates the schedule dev status at schedule // interval beginings and ends addScheduleDevCronTasks(schedule); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // if needed, setup periodic task to trigger rules which use this schedule if (schedule.autoUpdate) { addScheduleAutoUpdCronTask(schedule); } </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // set schedule dev status as soon as possible at startup (function(schedule) { setTimeout(function() { updateSingleScheduleDevStatus(schedule); }, 1); })(schedule); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> }; }; }; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> })(Schedules); </syntaxhighlight> </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Пример правил, с использованием Schedules: <syntaxhighlight lang="ecmascript"> (function() { // замыкание </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineAlias("countersTemperature", "wb-msw2_30/Temperature"); defineAlias("vegetablesTemperature", "wb-msw2_31/Temperature"); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineAlias("heater1EnableInverted", "wb-mrm2-old_70/Relay 1"); defineAlias("frontshopVentInverted", "wb-gpio/EXT1_R3A3"); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> Schedules.registerSchedule({ "name" : "signboard", // вывеска "autoUpdate" : "1m", "intervals" : [ [ [12, 30], [20, 30] ], // в UTC, 15:30 - 23:30 MSK [ [3, 30], [5, 20] ], // в UTC, 6:30 - 8:20 MSK ] }); Schedules.registerSchedule({ "name" : "ext_working_hours_15m", "autoUpdate" : "1m", "intervals" : [ [ [4, 45], [20, 15] ], // всё ещё UTC, 7:45 - 23:15 MSK ] }); Schedules.registerSchedule({ "name" : "working_hours", "autoUpdate" : "1m", "intervals" : [ [ [5, 0], [19, 0] ], // всё ещё UTC, 8:00 - 22:00 MSK ] }); Schedules.registerSchedule({ "name" : "working_hours_15m", "autoUpdate" : "1m", "intervals" : [ [ [4, 45], [19, 15] ], // всё ещё UTC, 7:45 - 22:15 MSK ] }); Schedules.registerSchedule({ "name" : "frontshop_lighting", "autoUpdate" : "1m", "intervals" : [ [ [4, 20], [20, 45] ], // всё ещё UTC, 7:20 -23:45 MSK ] }); Schedules.registerSchedule({ "name" : "heaters_schedule", "intervals" : [ [ [4, 0], [17, 0] ], // всё ещё UTC, 07:00 - 20:00 MSK дневной режим ] }); Schedules.initSchedules(); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // Вывеска и фасадное освещение defineRule("signboardOnOff", { when: function() { return dev._schedules.signboard || true; }, then: function (newValue, devName, cellName) { log("signboardOnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); var on = dev._schedules.signboard; // dev["wb-mr6c_80/K2"] = !on; dev["wb-mr6c_80/K1"] = !on; dev["wb-mr6c_80/K3"] = !on; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // Освещение торгового зала defineRule("lightingFrontshopOnOff", { when: function() { return dev._schedules.frontshop_lighting || true; }, then: function (newValue, devName, cellName) { log("lightingFrontshopOnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); dev["wb-gpio/EXT1_R3A1"] = ! dev._schedules.frontshop_lighting; //инвертированный контактор } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // Вентиляция подсобного помещения defineRule("ventBackstoreOnOff", { when: function() { return dev._schedules.ext_working_hours_15m || true; }, then: function (newValue, devName, cellName) { log("ventBackstoreOnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); var on = dev._schedules.ext_working_hours_15m; dev["wb-mr6c_81/K1"] = ! on; //инвертированный контактор dev["wb-mr6c_81/K5"] = ! on; //инвертированный контактор } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // Освещение холодильных горок defineRule("lightingCoolingshelfsOnOff", { when: function() { return dev._schedules.frontshop_lighting || true; }, then: function (newValue, devName, cellName) { log("lightingCoolingshelfsOnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); var on = dev._schedules.working_hours_15m; </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // освещение в горках через нормально-закрытые реле (инвертировано) dev["wb-mrm2-old_60/Relay 1"] = !on; dev["wb-mrm2-old_61/Relay 1"] = !on; dev["wb-mrm2-old_62/Relay 1"] = !on; dev["wb-mrm2-old_63/Relay 1"] = !on; dev["wb-mrm2-old_64/Relay 1"] = !on; dev["wb-mrm2-old_65/Relay 1"] = !on; dev["wb-mrm2-old_66/Relay 1"] = !on; dev["wb-mrm2-old_67/Relay 1"] = !on; } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> //Брендовые холодильники (пиво, лимонады) defineRule("powerBrandFridgesOnOff", { when: function() { return dev._schedules.working_hours || true; }, then: function (newValue, devName, cellName) { log("powerBrandFridgesOnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); var on = dev._schedules.working_hours; dev["wb-gpio/EXT1_R3A5"] = !on; // инвертировано } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // ========= Котлы и приточная вентиляция ТЗ =========== // обратная связь по температуре овощной зоны </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // днём работает позиционный регулятор defineRule("heatersDayOff", { when: function() { return (dev._schedules.heaters_schedule) && (vegetablesTemperature > 17.0); }, then: function (newValue, devName, cellName) { log("heatersDayOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); heater1EnableInverted = !false; // инвертировано } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("heatersDayOn", { when: function() { return (dev._schedules.heaters_schedule) && (vegetablesTemperature < 16.7); }, then: function (newValue, devName, cellName) { log("heatersDayOn newValue={}, devName={}, cellName={}", newValue, devName, cellName); heater1EnableInverted = !true; // инвертировано } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // ночью работает позиционный регулятор defineRule("heatersNightOff", { when: function() { return (!dev._schedules.heaters_schedule) && (vegetablesTemperature > 11.6); }, then: function (newValue, devName, cellName) { log("heatersNightOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); heater1EnableInverted = !false; // инвертировано } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("heatersNightOn", { when: function() { return (!dev._schedules.heaters_schedule) && (vegetablesTemperature < 11.3); }, then: function (newValue, devName, cellName) { log("heatersNightOn newValue={}, devName={}, cellName={}", newValue, devName, cellName); heater1EnableInverted = !true; // инвертировано } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // приточная и вытяжная вентиляция принудительно выключены defineRule("ventFrontshopAlwaysOff", { when: cron("@every 1m"), then: function() { dev["wb-gpio/EXT1_R3A3"] = !false; dev["wb-gpio/EXT1_R3A4"] = !false; } }); // ================== Кассовая зона ================= </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // в кассовой зоне в рабочее время температура поддерживается кондиционерами (позиционный регулятор) </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("countersACOn", { when: function() { return (dev._schedules.working_hours_15m) && (countersTemperature < 17.7); }, then: function (newValue, devName, cellName) { log("countersACOn newValue={}, devName={}, cellName={}", newValue, devName, cellName); dev["wb-mir_75/Play from ROM7"] = true; // кондиционер кассовой зоны на нагрев } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // в нерабочее время кондиционер выключен defineRule("countersACOff", { when: function() { return (!dev._schedules.working_hours_15m) || (countersTemperature > 18.0); }, then: function (newValue, devName, cellName) { log("countersACOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); dev["wb-mir_75/Play from ROM2"] = true; // кондиционер кассовой зоны выключить } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> // =============== Овощная зона ============== // Охлаждение овощей кондиционером только при температуре воздуха выше 18.5C </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("acVegOn", { when: function() { return vegetablesTemperature >= 18.5 }, then: function (newValue, devName, cellName) { log("acVegOn newValue={}, devName={}, cellName={}", newValue, devName, cellName); dev["wb-mir_76/Play from ROM3"] = true; // Охлаждение +18 } }); </div> <div lang="ru" dir="ltr" class="mw-content-ltr"> defineRule("acVegOff", { when: function() { return vegetablesTemperature < 17.8 }, then: function (newValue, devName, cellName) { log("acVegOff newValue={}, devName={}, cellName={}", newValue, devName, cellName); dev["wb-mir_76/Play from ROM2"] = true; // выключить } }); })() </syntaxhighlight> == Полезные ссылки == * [[Wb-rules | Краткое описание wb-rules на wiki]] * [https://github.com/wirenboard/wb-rules Полное описание wb-rules на Github] </div>