mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4769f57f07 | |||
| 2c601b2c03 | |||
| 5294617455 | |||
| d71499442e | |||
| 9989e3db21 | |||
| 53c5748c14 | |||
| 5480412f1b | |||
| 575e05cd84 | |||
| d6768ab594 | |||
| 8754a35cba | |||
| 65c07a1881 | |||
| c2c863b8bd | |||
| 5aec014767 | |||
| c9714ef982 | |||
| 2b5b780586 | |||
| e803d1ae51 | |||
| 6cba90f7dd | |||
| 6019aa41bb | |||
| 891b029501 |
@@ -16,4 +16,5 @@
|
|||||||
|
|
||||||
-DRESTART_LAN_ON_MQTT_ERRORS
|
-DRESTART_LAN_ON_MQTT_ERRORS
|
||||||
-DOTA_PORT=80
|
-DOTA_PORT=80
|
||||||
-DMERCURY_ENABLE
|
-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -58,4 +58,5 @@
|
|||||||
-DMQTT_SOCKET_TIMEOUT=20
|
-DMQTT_SOCKET_TIMEOUT=20
|
||||||
-D CORS=\"*\"
|
-D CORS=\"*\"
|
||||||
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
||||||
#-DMERCURY_ENABLE
|
#-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -46,4 +46,5 @@
|
|||||||
-D PWM_DISABLE
|
-D PWM_DISABLE
|
||||||
|
|
||||||
# WAK for HDC1080 (pin D3 on wemos is IO0)
|
# WAK for HDC1080 (pin D3 on wemos is IO0)
|
||||||
-D WAK_PIN=D3
|
-D WAK_PIN=D3
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -40,4 +40,5 @@
|
|||||||
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
||||||
-D MERCURY_ENABLE
|
-D MERCURY_ENABLE
|
||||||
#-D IPMODBUS
|
#-D IPMODBUS
|
||||||
-D CONFIG_CLEAN_PIN=2
|
-D CONFIG_CLEAN_PIN=2
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -6,13 +6,17 @@
|
|||||||
-DCOUNTER_DISABLE
|
-DCOUNTER_DISABLE
|
||||||
-DSPILED_DISABLE
|
-DSPILED_DISABLE
|
||||||
-DAC_DISABLE
|
-DAC_DISABLE
|
||||||
|
-DHSV_DISABLE
|
||||||
|
-DPWM_DISABLE
|
||||||
-DM5STACK
|
-DM5STACK
|
||||||
#-DSYSLOG_ENABLE
|
#-DSYSLOG_ENABLE
|
||||||
-DUSE_1W_PIN=16
|
-DUSE_1W_PIN=16
|
||||||
#-DPID_DISABLE
|
#-DPID_DISABLE
|
||||||
-DARDUINO_OTA_MDNS_DISABLE
|
-DARDUINO_OTA_MDNS_DISABLE
|
||||||
-DMDNS_ENABLE
|
-DMDNS_ENABLE
|
||||||
-DMCP23017
|
#-DMCP23017
|
||||||
|
-DPID_DISABLE
|
||||||
|
-DNO_HOMIE
|
||||||
|
|
||||||
-DFS_STORAGE
|
-DFS_STORAGE
|
||||||
-DFS_PREPARE
|
-DFS_PREPARE
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
-DWiz5500
|
#-DWiz5500
|
||||||
#-DMODBUS_SERIAL_PARAM=SERIAL_8E1
|
#-DMODBUS_SERIAL_PARAM=SERIAL_8E1
|
||||||
-DAVR_DMXOUT_PIN=18
|
-DAVR_DMXOUT_PIN=18
|
||||||
-DSYSLOG_ENABLE
|
-DSYSLOG_ENABLE
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
-DCSSHDC_DISABLE
|
-DCSSHDC_DISABLE
|
||||||
-DSPILED_DISABLE
|
-DSPILED_DISABLE
|
||||||
-DAC_DISABLE
|
-DAC_DISABLE
|
||||||
|
-DOTA
|
||||||
|
|
||||||
|
|
||||||
-DRESTART_LAN_ON_MQTT_ERRORS
|
-DRESTART_LAN_ON_MQTT_ERRORS
|
||||||
@@ -18,7 +18,10 @@
|
|||||||
-DMULTIVENT_DISABLE
|
-DMULTIVENT_DISABLE
|
||||||
#-DWiz5100
|
#-DWiz5100
|
||||||
-DARDUINO_OTA_MDNS_DISABLE
|
-DARDUINO_OTA_MDNS_DISABLE
|
||||||
-DMDNS_ENABLE
|
#-DMDNS_ENABLE
|
||||||
|
|
||||||
|
-DHSV_DISABLE
|
||||||
|
-DPWM_DISABLE
|
||||||
|
|
||||||
-DRESTART_LAN_ON_MQTT_ERRORS
|
-DRESTART_LAN_ON_MQTT_ERRORS
|
||||||
-D CORS=\"*\"
|
-D CORS=\"*\"
|
||||||
|
|||||||
@@ -16,4 +16,5 @@
|
|||||||
|
|
||||||
-D CORS=\"*\"
|
-D CORS=\"*\"
|
||||||
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
|
||||||
#-DMERCURY_ENABLE
|
#-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
-DENABLE_HWSERIAL1
|
-DENABLE_HWSERIAL1
|
||||||
-DdebugSerialPort=Serial1
|
-DdebugSerialPort=Serial1
|
||||||
|
-D TIMER_INT
|
||||||
|
|
||||||
|
|
||||||
#-DFLASH_BASE_ADDRESS
|
#-DFLASH_BASE_ADDRESS
|
||||||
#-DFLASH_DATA_SECTOR
|
#-DFLASH_DATA_SECTOR
|
||||||
@@ -37,4 +39,5 @@
|
|||||||
#HAL_ETH_MODULE_DISABLED
|
#HAL_ETH_MODULE_DISABLED
|
||||||
#HAL_SD_MODULE_DISABLED
|
#HAL_SD_MODULE_DISABLED
|
||||||
#HAL_DAC_MODULE_DISABLED
|
#HAL_DAC_MODULE_DISABLED
|
||||||
#-DMERCURY_ENABLE
|
#-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
-D THERMOSTAT_CHECK_PERIOD=5000
|
-D THERMOSTAT_CHECK_PERIOD=5000
|
||||||
-D ULTRASONIC
|
-D ULTRASONIC
|
||||||
|
|
||||||
|
-D TIMER_INT
|
||||||
-DENABLE_HWSERIAL1
|
-DENABLE_HWSERIAL1
|
||||||
-DdebugSerialPort=Serial1
|
-DdebugSerialPort=Serial1
|
||||||
|
|
||||||
@@ -45,4 +45,5 @@
|
|||||||
#HAL_ETH_MODULE_DISABLED
|
#HAL_ETH_MODULE_DISABLED
|
||||||
#HAL_SD_MODULE_DISABLED
|
#HAL_SD_MODULE_DISABLED
|
||||||
#HAL_DAC_MODULE_DISABLED
|
#HAL_DAC_MODULE_DISABLED
|
||||||
#-DMERCURY_ENABLE
|
#-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
# usage:
|
|
||||||
# first make your own copy of template
|
|
||||||
# cp build_flags_template.sh my_build_flags.sh
|
|
||||||
# then edit, change or comment something
|
|
||||||
# nano my_build_flags.sh
|
|
||||||
# and source it
|
|
||||||
# source my_build_flags.sh
|
|
||||||
echo "==============================================Custom build flags are:====================================================="
|
|
||||||
export FLAGS="-DMY_CONFIG_SERVER=lazyhome.ru"
|
|
||||||
export FLAGS="$FLAGS -DWATCH_DOG_TICKER_DISABLE"
|
|
||||||
export FLAGS="$FLAGS -DUSE_1W_PIN=12"
|
|
||||||
export FLAGS="$FLAGS -DSD_CARD_INSERTED"
|
|
||||||
export FLAGS="$FLAGS -DSERIAL_BAUD=115200"
|
|
||||||
export FLAGS="$FLAGS -DWiz5500"
|
|
||||||
export FLAGS="$FLAGS -DDISABLE_FREERAM_PRINT"
|
|
||||||
export FLAGS="$FLAGS -DCUSTOM_FIRMWARE_MAC=de:ad:be:ef:fe:00"
|
|
||||||
export FLAGS="$FLAGS -DDMX_DISABLE"
|
|
||||||
export FLAGS="$FLAGS -DMODBUS_DISABLE"
|
|
||||||
export FLAGS="$FLAGS -DOWIRE_DISABLE"
|
|
||||||
export FLAGS="$FLAGS -DAVR_DMXOUT_PIN=18"
|
|
||||||
export FLAGS="$FLAGS -DLAN_INIT_DELAY=2000"
|
|
||||||
export FLAGS="$FLAGS -DCONTROLLINO"
|
|
||||||
export PLATFORMIO_BUILD_FLAGS="$FLAGS"
|
|
||||||
echo PLATFORMIO_BUILD_FLAGS=$PLATFORMIO_BUILD_FLAGS
|
|
||||||
echo "==============================================Custom build flags END====================================================="
|
|
||||||
unset FLAGS
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
export PORT=cu.usbmodem144101
|
export PORT=cu.usbmodem142401
|
||||||
echo . | stty -f /dev/$PORT speed 1200
|
echo . | stty -f /dev/$PORT speed 1200
|
||||||
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R
|
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R
|
||||||
@@ -1 +1 @@
|
|||||||
../tools/mac/arduinoOTA -address 192.168.11.13 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
|
../tools/mac/arduinoOTA -address 192.168.11.200 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -11,5 +11,5 @@ cp ../.pio/build/esp32-wifi/firmware.bin esp32-wifi
|
|||||||
cp ../.pio/build/stm32-enc2860/firmware.bin stm32-enc2860
|
cp ../.pio/build/stm32-enc2860/firmware.bin stm32-enc2860
|
||||||
cp ../.pio/build/esp8266-wifi/firmware.bin esp8266-wifi
|
cp ../.pio/build/esp8266-wifi/firmware.bin esp8266-wifi
|
||||||
cp ../.pio/build/lighthub21/firmware.bin lighthub21
|
cp ../.pio/build/lighthub21/firmware.bin lighthub21
|
||||||
cp ../.pio/build/mega2560-5500/firmware.hex mega2560-5500
|
cp ../.pio/build/mega2560/firmware.hex mega2560
|
||||||
cp ../.pio/build/stm32/firmware.* stm32
|
cp ../.pio/build/stm32/firmware.* stm32
|
||||||
|
|||||||
221
config-examples/lh22-test.json
Normal file
221
config-examples/lh22-test.json
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"dmx":[3,60],
|
||||||
|
"mqtt":["lh22-test","192.168.11.4"],
|
||||||
|
"dmxin":["led5","led6","led7","led8"],
|
||||||
|
"topics":{"root":"test2"},
|
||||||
|
"syslog":["192.168.88.2"],
|
||||||
|
"ow":{
|
||||||
|
"282F7E81E3713C59":{"emit":"t_1"}
|
||||||
|
},
|
||||||
|
"modbus":
|
||||||
|
{
|
||||||
|
"s8":{
|
||||||
|
"poll":{"irs":[[0,3]],"regs":[[0,1],31],"delay":11000},
|
||||||
|
"par":{
|
||||||
|
"co2":{"ir":3},
|
||||||
|
"meterStat":{"ir":0},
|
||||||
|
"alarmStat":{"ir":1},
|
||||||
|
"hr1":{"reg":0},
|
||||||
|
"hr2":{"reg":1},
|
||||||
|
"hr32":{"reg":31}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"term":{
|
||||||
|
"poll":{"regs":[0],"delay":12000},
|
||||||
|
"par":{
|
||||||
|
"t":{"reg":0,"type":"x10"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thmeter":{
|
||||||
|
"serial":"8N1",
|
||||||
|
"baud":4800,
|
||||||
|
"poll":{"regs":[[0,1],[2000,2001],[80,81]],"delay":3000},
|
||||||
|
"par":{
|
||||||
|
"hum" :{"reg":0,"type":"x10"},
|
||||||
|
"temp" :{"reg":1,"type":"x10"},
|
||||||
|
"slaveid" :{"reg":2000},
|
||||||
|
"baud" :{"reg":2001},
|
||||||
|
"tcalib":{"reg":80,"type":"x10"},
|
||||||
|
"hcalib":{"reg":81,"type":"x10"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"panel":{
|
||||||
|
"serial":"8E1",
|
||||||
|
"poll":{"regs":[[39993,40008],[30000,30001]],"delay":5000},
|
||||||
|
"par":{
|
||||||
|
"fanspeed" :{"reg":40000,"prefetch":true,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
|
||||||
|
"settemp" :{"reg":40002,"prefetch":true,"id":12},
|
||||||
|
"alm01":{"reg":40004,"id":13},
|
||||||
|
"alm17":{"reg":40005,"id":14},
|
||||||
|
"alm33":{"reg":40006,"id":15},
|
||||||
|
"sethum" :{"reg":40007,"prefetch":true,"id":16},
|
||||||
|
"setvoc" :{"reg":40008,"prefetch":true,"map":{"val":[400,2000,0,100]},"id":17},
|
||||||
|
"roomtemp" :{"reg":30000,"type":"x10"},
|
||||||
|
"hum" :{"reg":30001},
|
||||||
|
"voc" :{"reg":30002},
|
||||||
|
"ch_temp" :{"reg":40009,"type":"x10","id":3},
|
||||||
|
"ext_temp" :{"reg":40010,"type":"x10","id":18},
|
||||||
|
"out_temp" :{"reg":40011,"type":"x10","id":19},
|
||||||
|
"floor_temp" :{"reg":40012,"type":"x10","id":20},
|
||||||
|
"ch_hum" :{"reg":40013,"id":28},
|
||||||
|
"heat_pwr":{"reg":40014,"id":29},
|
||||||
|
"extvoc":{"reg":40015,"map":{"val":[400,2000,0,100]},"id":27},
|
||||||
|
"actemp":{"reg":40016,"type":"x10","id":25},
|
||||||
|
"fanlvl":{"reg":40017,"id":21},
|
||||||
|
"floormode":{"reg":39995,"prefetch":true,"id":22},
|
||||||
|
"setfloor":{"reg":39996,"prefetch":true,"id":23},
|
||||||
|
"humpwr":{"reg":39998,"prefetch":true,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null},"id":24},
|
||||||
|
"fanauto":{"reg":39999,"prefetch":true,"map":{"cmd":[["ENABLE",1],["DISABLE",0],["AUTO",1]],"val":null},"id":7},
|
||||||
|
"acsettemp":{"reg":39994,"prefetch":true,"id":26},
|
||||||
|
"acon":{"reg":40003,"prefetch":true,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
|
||||||
|
"acmode" :{"reg":40001,"prefetch":true,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
|
||||||
|
"acfanauto":{"reg":39993,"prefetch":true,"map":{"cmd":[0,["AUTO",1]],"val":null,"def":39997},"id":2},
|
||||||
|
"acfan":{"reg":39997,"prefetch":true,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2]]},"id":2},
|
||||||
|
"y":{"reg":65512},
|
||||||
|
"mo":{"reg":65513},
|
||||||
|
"d":{"reg":65514},
|
||||||
|
"dw":{"reg":65515},
|
||||||
|
"h":{"reg":65516},
|
||||||
|
"m":{"reg":65517},
|
||||||
|
"s":{"reg":65518},
|
||||||
|
"blmind":{"reg":50051},
|
||||||
|
"blmaxd":{"reg":50052},
|
||||||
|
"blminn":{"reg":50053},
|
||||||
|
"blmaxn":{"reg":50054}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"items": {
|
||||||
|
"th":[14,[1,"thmeter",
|
||||||
|
{
|
||||||
|
"temp":{"emit":"temp","@S":null},
|
||||||
|
"hum" :{"emit":"zal2hum","@S":null},
|
||||||
|
"slaveid" :{"emit":"slaveid"},
|
||||||
|
"baud" :{"emit":"baud"},
|
||||||
|
"tcalib":{"emit":"tcalib"},
|
||||||
|
"hcalib":{"emit":"hcalib"}
|
||||||
|
}
|
||||||
|
]],
|
||||||
|
|
||||||
|
"pout0":[6,22],
|
||||||
|
"pout1":[6,23],
|
||||||
|
"pout2":[6,24],
|
||||||
|
"pout3":[6,25],
|
||||||
|
"pout4":[3,9],
|
||||||
|
"pout5":[3,8],
|
||||||
|
"pout6":[3,11],
|
||||||
|
"pout7":[3,12],
|
||||||
|
"pwm0" :[3,4],
|
||||||
|
"pwm1" :[3,5],
|
||||||
|
"pwm2" :[3,6],
|
||||||
|
"pwm3" :[3,7],
|
||||||
|
|
||||||
|
"unprot0":[6,33],
|
||||||
|
"unprot1":[6,32],
|
||||||
|
"unprot2":[6,31],
|
||||||
|
"unprot3":[6,30],
|
||||||
|
"unprot4":[6,29],
|
||||||
|
"unprot5":[6,28],
|
||||||
|
"unprot6":[6,27],
|
||||||
|
"unprot7":[6,26],
|
||||||
|
"led": [1,1],
|
||||||
|
"led2":[1,5],
|
||||||
|
"led3":[1,9],
|
||||||
|
"led4":[1,13],
|
||||||
|
"led5":[1,17],
|
||||||
|
"led6":[1,21],
|
||||||
|
"led7":[1,25],
|
||||||
|
"led8":[1,29],
|
||||||
|
"dimmer" :[0,33],
|
||||||
|
"dimmer2":[0,34],
|
||||||
|
"dimmer3":[0,35],
|
||||||
|
"dimmer4":[0,36],
|
||||||
|
"dimmer5":[0,37],
|
||||||
|
"dimmer6":[0,38],
|
||||||
|
"dimmers":[7,["dimmer","dimmer2","dimmer3","dimmer4","dimmer5","dimmer6"]],
|
||||||
|
"leds":[7,["led","led2","led3","led4","led5","led6"]],
|
||||||
|
"mbuses":[7,["mbusdim1","mbusdim2","mbusdim3","mbusdim4"]],
|
||||||
|
"all":[7,["dimmers","uouts","relays","leds"]],
|
||||||
|
"relays":[7,["pout0","pout1","pout2","pout3","pout4","pout5","pout6","pout7"]],
|
||||||
|
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]]
|
||||||
|
},
|
||||||
|
"in":{
|
||||||
|
"42":{"emit":"in0"},
|
||||||
|
"44":{"emit":"in1"},
|
||||||
|
"46":{"emit":"in2"},
|
||||||
|
"49":{"emit":"in3"},
|
||||||
|
"43":{"emit":"in4"},
|
||||||
|
"45":{"emit":"in5"},
|
||||||
|
"47":{"emit":"in6"},
|
||||||
|
"48":{"emit":"in7"},
|
||||||
|
"34":{"emit":"in8"},
|
||||||
|
"36":{"emit":"in9"},
|
||||||
|
"38":{"emit":"in10"},
|
||||||
|
"40":{"emit":"in11"},
|
||||||
|
"35":{"emit":"in12"},
|
||||||
|
"37":{"emit":"in13"},
|
||||||
|
"39":{"emit":"in14"},
|
||||||
|
"41":{"emit":"in15"},
|
||||||
|
|
||||||
|
"54":{"T":64,"emit":"a00","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
|
||||||
|
"55":{"T":64,"emit":"a01","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
|
||||||
|
"56":{"T":64,"emit":"a02","map":[0,1024,0,1024,10]},
|
||||||
|
"57":{"T":64,"emit":"a03","map":[0,1024,0,1024,10]},
|
||||||
|
"58":{"T":64,"emit":"a04","map":[0,1024,0,1024,10]},
|
||||||
|
"59":{"T":64,"emit":"a05","map":[0,1024,0,1024,10]},
|
||||||
|
"60":{"T":64,"emit":"a06"},
|
||||||
|
"61":{"T":64,"emit":"a07","map":[0,1024,0,1024,5]},
|
||||||
|
"62":{"T":64,"emit":"a08","map":[0,1024,0,1024,5]},
|
||||||
|
"63":{"T":64,"emit":"a09","map":[0,1024,0,1024,5]},
|
||||||
|
"64":{"T":64,"emit":"a10","map":[0,1024,0,1024,5]},
|
||||||
|
"65":{"T":64,"emit":"a11","map":[0,1024,0,1024,5]},
|
||||||
|
"66":{"T":2,"emit":"d12"},
|
||||||
|
"67":{
|
||||||
|
"T":2,
|
||||||
|
"scmd":{"emit":"d13","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d13","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d13","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d13","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d13","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d13","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d13","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d13","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d13","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d13","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d13","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d13","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d13","ecmd":"rpcmd3"}
|
||||||
|
},
|
||||||
|
"68":{"T":2,
|
||||||
|
"scmd":{"emit":"d14","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d14","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d14","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d14","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d14","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d14","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d14","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d14","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d14","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d14","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d14","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d14","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d14","ecmd":"rpcmd3"}
|
||||||
|
},
|
||||||
|
"69":{"T":2,
|
||||||
|
"scmd":{"emit":"d15","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d15","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d15","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d15","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d15","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d15","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d15","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d15","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d15","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d15","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d15","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d15","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d15","ecmd":"rpcmd3"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,8 +19,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int publishTopic(const char* topic, long value, const char* subtopic = NULL);
|
int publishTopic(const char* topic, long value, const char* subtopic = NULL);
|
||||||
virtual int publishTopic(const char* topic, float value, const char* subtopic = NULL );
|
int publishTopic(const char* topic, float value, const char* subtopic = NULL );
|
||||||
virtual int publishTopic(const char* topic, const char * value, const char* subtopic = NULL);
|
int publishTopic(const char* topic, const char * value, const char* subtopic = NULL);
|
||||||
//friend Input;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "abstractout.h"
|
#include "abstractout.h"
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "textconst.h"
|
||||||
|
|
||||||
int abstractOut::isActive()
|
int abstractOut::isActive()
|
||||||
|
|
||||||
{itemCmd st;
|
{itemCmd st;
|
||||||
@@ -37,4 +38,39 @@ int abstractOut::Status()
|
|||||||
void abstractOut::setStatus(uint8_t status)
|
void abstractOut::setStatus(uint8_t status)
|
||||||
{
|
{
|
||||||
if (item && item->itemArr) item->itemArr->subtype = status & 0xF;
|
if (item && item->itemArr) item->itemArr->subtype = status & 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int abstractOut::pubAction(bool state)
|
||||||
|
{
|
||||||
|
char subtopic[10]="/";
|
||||||
|
char val[10];
|
||||||
|
|
||||||
|
strcat_P(subtopic,action_P);
|
||||||
|
short cmd=item->getCmd();
|
||||||
|
if (state)
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case CMD_COOL:
|
||||||
|
strcpy_P(val,cooling_P);
|
||||||
|
break;
|
||||||
|
//case CMD_AUTO:
|
||||||
|
//case CMD_HEAT:
|
||||||
|
//case CMD_ON:
|
||||||
|
//
|
||||||
|
// break;
|
||||||
|
case CMD_DRY:
|
||||||
|
strcpy_P(val,drying_P);
|
||||||
|
break;
|
||||||
|
case CMD_FAN:
|
||||||
|
strcpy_P(val,fan_P);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy_P(val,heating_P);
|
||||||
|
}
|
||||||
|
else //turned off
|
||||||
|
if (cmd==CMD_OFF) strcpy_P(val,off_P);
|
||||||
|
else strcpy_P(val,idle_P);
|
||||||
|
return publishTopic(item->itemArr->name,val,subtopic);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,9 @@ class Item;
|
|||||||
class chPersistent {};
|
class chPersistent {};
|
||||||
class abstractOut : public abstractCh{
|
class abstractOut : public abstractCh{
|
||||||
public:
|
public:
|
||||||
abstractOut(Item * _item):abstractCh(){item=_item;};
|
//abstractOut(Item * _item):abstractCh(){item=_item;};
|
||||||
|
abstractOut():item(NULL){};
|
||||||
|
virtual void link(Item * _item){item=_item;};
|
||||||
virtual int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) =0;
|
virtual int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) =0;
|
||||||
virtual int isActive();
|
virtual int isActive();
|
||||||
virtual bool isAllowed(itemCmd cmd){return true;};
|
virtual bool isAllowed(itemCmd cmd){return true;};
|
||||||
@@ -16,7 +18,11 @@ public:
|
|||||||
// virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead
|
// virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead
|
||||||
virtual int Status() override;
|
virtual int Status() override;
|
||||||
virtual void setStatus(uint8_t status) override;
|
virtual void setStatus(uint8_t status) override;
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
|
Item * getItem() {return item;}
|
||||||
protected:
|
protected:
|
||||||
|
int pubAction(bool state);
|
||||||
|
|
||||||
Item * item;
|
Item * item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ extern volatile int8_t configLocked;
|
|||||||
extern bool configLoaded;
|
extern bool configLoaded;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints the data contained in a CAN frame.
|
||||||
|
*
|
||||||
|
* @param frame Pointer to the datagram_t structure containing the CAN frame.
|
||||||
|
* @param len Length of the data to print.
|
||||||
|
*/
|
||||||
void printFrame(datagram_t * frame, uint8_t len ) {
|
void printFrame(datagram_t * frame, uint8_t len ) {
|
||||||
|
|
||||||
debugSerial.print(" Data:");
|
debugSerial.print(" Data:");
|
||||||
@@ -38,6 +44,12 @@ void printFrame(datagram_t * frame, uint8_t len ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the uptime metric to the CAN bus.
|
||||||
|
*
|
||||||
|
* @param ut Uptime value to send.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::upTime(uint32_t ut)
|
bool canDriver::upTime(uint32_t ut)
|
||||||
{
|
{
|
||||||
if (!controllerId) return false;
|
if (!controllerId) return false;
|
||||||
@@ -57,6 +69,12 @@ bool canDriver::upTime(uint32_t ut)
|
|||||||
return write (id.id, &packet, 4);
|
return write (id.id, &packet, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the salt metric to the CAN bus.
|
||||||
|
*
|
||||||
|
* @param salt Salt value to send.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::salt(uint32_t salt)
|
bool canDriver::salt(uint32_t salt)
|
||||||
{
|
{
|
||||||
if (!controllerId) return false;
|
if (!controllerId) return false;
|
||||||
@@ -77,6 +95,11 @@ bool canDriver::salt(uint32_t salt)
|
|||||||
return write (id.id, &packet, 4);
|
return write (id.id, &packet, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Looks up the MAC address and sends it over the CAN bus.
|
||||||
|
*
|
||||||
|
* @return true if the MAC address was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::lookupMAC()
|
bool canDriver::lookupMAC()
|
||||||
{
|
{
|
||||||
// return 0;
|
// return 0;
|
||||||
@@ -102,6 +125,14 @@ bool canDriver::lookupMAC()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Requests a frame from the specified device on the CAN bus.
|
||||||
|
*
|
||||||
|
* @param devId Device ID to request the frame from.
|
||||||
|
* @param _payloadType Type of payload to request.
|
||||||
|
* @param seqNo Sequence number for the request.
|
||||||
|
* @return true if the request was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
|
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -127,6 +158,12 @@ packet.metric1 =0;
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the remote ID of a device identified by its MAC address.
|
||||||
|
*
|
||||||
|
* @param mac MAC address of the device.
|
||||||
|
* @return true if the remote ID was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendRemoteID(macAddress mac)
|
bool canDriver::sendRemoteID(macAddress mac)
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -154,6 +191,11 @@ return res;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the CAN driver and sets up the CAN bus.
|
||||||
|
*
|
||||||
|
* @return true if initialization was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::begin()
|
bool canDriver::begin()
|
||||||
{
|
{
|
||||||
if (root)
|
if (root)
|
||||||
@@ -207,6 +249,11 @@ bool canDriver::begin()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a frame from the CAN bus.
|
||||||
|
*
|
||||||
|
* @return Length of the received frame, or -1 if no frame was received.
|
||||||
|
*/
|
||||||
int canDriver::readFrame()
|
int canDriver::readFrame()
|
||||||
{
|
{
|
||||||
if (!ready) return -1;
|
if (!ready) return -1;
|
||||||
@@ -284,6 +331,9 @@ int canDriver::readFrame()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Polls the CAN bus for incoming frames and processes them.
|
||||||
|
*/
|
||||||
void canDriver::Poll()
|
void canDriver::Poll()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -355,13 +405,22 @@ switch (state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes a received CAN packet.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the CAN packet.
|
||||||
|
* @param packet Pointer to the received datagram_t structure.
|
||||||
|
* @param len Length of the received packet.
|
||||||
|
* @param rtr Indicates if the packet is a remote transmission request.
|
||||||
|
* @return true if the packet was processed successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
||||||
{
|
{
|
||||||
|
|
||||||
debugSerial.print("CAN: Rcvd ");
|
traceSerial.print("CAN: Rcvd ");
|
||||||
debugSerial.print(len);
|
traceSerial.print(len);
|
||||||
debugSerial.print(" bytes id:");
|
traceSerial.print(" bytes id:");
|
||||||
debugSerial.println(id.id,HEX);
|
traceSerial.println(id.id,HEX);
|
||||||
|
|
||||||
//if (id.deviceId && (id.deviceId != controllerId) && !id.status) return false;
|
//if (id.deviceId && (id.deviceId != controllerId) && !id.status) return false;
|
||||||
|
|
||||||
@@ -522,16 +581,14 @@ else //Requests
|
|||||||
if ((id.payloadType == payloadType::itemCommand) && (len ==8))
|
if ((id.payloadType == payloadType::itemCommand) && (len ==8))
|
||||||
{
|
{
|
||||||
Item it(id.itemId,id.subItemId);
|
Item it(id.itemId,id.subItemId);
|
||||||
if (it.isValid())
|
if (!it.isValid()) return false;
|
||||||
{
|
|
||||||
itemCmd ic;
|
itemCmd ic;
|
||||||
ic.cmd = packet->cmd;
|
ic.cmd = packet->cmd;
|
||||||
ic.param = packet->param;
|
ic.param = packet->param;
|
||||||
//debugSerial<<F("CAN: itemCmd: ");
|
//debugSerial<<F("CAN: itemCmd: ");
|
||||||
//ic.debugOut();
|
//ic.debugOut();
|
||||||
return it.Ctrl(ic,it.getSubItemStrById(id.subItemId));
|
return it.Ctrl(ic,it.getSubItemStrById(id.subItemId));
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
else if ((id.payloadType == payloadType::lookupMAC) && (len>=6))
|
else if ((id.payloadType == payloadType::lookupMAC) && (len>=6))
|
||||||
{
|
{
|
||||||
@@ -559,6 +616,11 @@ else //Requests
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the device ID of this CAN driver.
|
||||||
|
*
|
||||||
|
* @return The device ID, or 0 if not set.
|
||||||
|
*/
|
||||||
uint8_t canDriver::getMyId()
|
uint8_t canDriver::getMyId()
|
||||||
{
|
{
|
||||||
if (!canConfigObj) return 0;
|
if (!canConfigObj) return 0;
|
||||||
@@ -567,6 +629,12 @@ if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the configuration object for a device by its ID.
|
||||||
|
*
|
||||||
|
* @param devId Device ID to look up.
|
||||||
|
* @return Pointer to the configuration object, or NULL if not found.
|
||||||
|
*/
|
||||||
aJsonObject * canDriver::getConfbyID(uint8_t devId)
|
aJsonObject * canDriver::getConfbyID(uint8_t devId)
|
||||||
{
|
{
|
||||||
if (!canConfigObj) return NULL;
|
if (!canConfigObj) return NULL;
|
||||||
@@ -585,6 +653,13 @@ while (remoteConfObj)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a configuration object by device name.
|
||||||
|
*
|
||||||
|
* @param devName Name of the device to look for.
|
||||||
|
* @param devAddr Pointer to store the device address if found.
|
||||||
|
* @return Pointer to the configuration object, or NULL if not found.
|
||||||
|
*/
|
||||||
aJsonObject * canDriver::findConfbyName(char* devName, int * devAddr)
|
aJsonObject * canDriver::findConfbyName(char* devName, int * devAddr)
|
||||||
{
|
{
|
||||||
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object || !devName ) return NULL;
|
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object || !devName ) return NULL;
|
||||||
@@ -613,6 +688,13 @@ return NULL;
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
extern PubSubClient mqttClient;
|
extern PubSubClient mqttClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subscribes to MQTT topics based on the CAN configuration.
|
||||||
|
*
|
||||||
|
* @param root Pointer to the root topic string.
|
||||||
|
* @param buflen Length of the buffer for the topic string.
|
||||||
|
* @return true if subscription was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::subscribeTopics(char * root, size_t buflen)
|
bool canDriver::subscribeTopics(char * root, size_t buflen)
|
||||||
{
|
{
|
||||||
if (!root) return false;
|
if (!root) return false;
|
||||||
@@ -632,15 +714,25 @@ while (remoteConfObj)
|
|||||||
strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1);
|
strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1);
|
||||||
strncat(root+rootLen, "/", buflen-rootLen-1);
|
strncat(root+rootLen, "/", buflen-rootLen-1);
|
||||||
strncat(root+rootLen, "#", buflen-rootLen-1);
|
strncat(root+rootLen, "#", buflen-rootLen-1);
|
||||||
|
debugSerial.print("CAN: subscribe ");
|
||||||
debugSerial.println(root);
|
debugSerial.println(root);
|
||||||
mqttClient.subscribe(root);
|
mqttClient.subscribe(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remoteConfObj=remoteConfObj->next;
|
remoteConfObj=remoteConfObj->next;
|
||||||
}
|
}
|
||||||
|
//debugSerial<<"Subscribed"<<endl;
|
||||||
|
//delay(100);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the device ID associated with a given MAC address.
|
||||||
|
*
|
||||||
|
* @param mac MAC address to look up.
|
||||||
|
* @return The device ID, or 0 if not found.
|
||||||
|
*/
|
||||||
uint8_t canDriver::getIdByMac(macAddress mac)
|
uint8_t canDriver::getIdByMac(macAddress mac)
|
||||||
{
|
{
|
||||||
char macStr[19];
|
char macStr[19];
|
||||||
@@ -673,6 +765,14 @@ if (addrObj && (addrObj->type == aJson_Int))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a message over the CAN bus.
|
||||||
|
*
|
||||||
|
* @param msg_id Identifier for the message.
|
||||||
|
* @param buf Pointer to the datagram_t structure containing the message data.
|
||||||
|
* @param size Size of the message data.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
||||||
{ //
|
{ //
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
@@ -689,7 +789,7 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
CAN_TX_msg.id = msg_id;
|
CAN_TX_msg.id = msg_id;
|
||||||
CAN_TX_msg.flags.extended = 1; // To enable extended ID
|
CAN_TX_msg.flags.extended = 1; // To enable extended ID
|
||||||
CAN_TX_msg.len=size;
|
CAN_TX_msg.len=size;
|
||||||
if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
if (res=STMCan.write(CAN_TX_msg)) {traceSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;}
|
||||||
else debugSerial.println("CAN: Write error");
|
else debugSerial.println("CAN: Write error");
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
@@ -699,7 +799,7 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
CAN.beginExtendedPacket(msg_id,size);
|
CAN.beginExtendedPacket(msg_id,size);
|
||||||
CAN.write(buf->data,size);
|
CAN.write(buf->data,size);
|
||||||
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
|
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
|
||||||
if (res=CAN.endPacket()) debugSerial<< ("CAN: Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;
|
if (res=CAN.endPacket()) {traceSerial<< ("CAN: Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;}
|
||||||
else debugSerial.println("CAN: Write error");
|
else debugSerial.println("CAN: Write error");
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
@@ -712,8 +812,8 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
//outgoing.priority = 4; //0-15 lower is higher priority
|
//outgoing.priority = 4; //0-15 lower is higher priority
|
||||||
if (buf) for(uint8_t i=0;i<size; i++) CAN_TX_msg.data.bytes[i]=buf->data[i];
|
if (buf) for(uint8_t i=0;i<size; i++) CAN_TX_msg.data.bytes[i]=buf->data[i];
|
||||||
res=Can0.sendFrame(CAN_TX_msg);
|
res=Can0.sendFrame(CAN_TX_msg);
|
||||||
if (res) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
if (res) {traceSerial<<F("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;}
|
||||||
else debugSerial.println("CAN: Write error");
|
else errorSerial.println("CAN: Write error");
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -722,12 +822,28 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the status of a specified item.
|
||||||
|
*
|
||||||
|
* @param itemNum Item number to send the status for.
|
||||||
|
* @param cmd Command structure containing the status information.
|
||||||
|
* @param subItem Sub-item identifier.
|
||||||
|
* @return true if the status was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendStatus(uint16_t itemNum, itemCmd cmd, int subItem)
|
bool canDriver::sendStatus(uint16_t itemNum, itemCmd cmd, int subItem)
|
||||||
{
|
{
|
||||||
if (!itemNum) return false;
|
if (!itemNum || !controllerId) return false;
|
||||||
return sendCommand(controllerId, itemNum, cmd, true, subItem);
|
return sendCommand(controllerId, itemNum, cmd, true, subItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command to a specified CAN device.
|
||||||
|
*
|
||||||
|
* @param can Pointer to the configuration object for the device.
|
||||||
|
* @param cmd Command structure containing the command information.
|
||||||
|
* @param status Indicates if the command is a status update.
|
||||||
|
* @return true if the command was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
||||||
{
|
{
|
||||||
if (can && (can->type == aJson_Array))
|
if (can && (can->type == aJson_Array))
|
||||||
@@ -746,7 +862,17 @@ bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
|||||||
int suffix=txt2subItem(sfx->valuestring);
|
int suffix=txt2subItem(sfx->valuestring);
|
||||||
if (suffix) cmd.setSuffix(suffix);
|
if (suffix) cmd.setSuffix(suffix);
|
||||||
}
|
}
|
||||||
if (subItemObj && subItemObj->type==aJson_Int && subItemObj->valueint>=0 && subItemObj->valueint<63) subItem=subItemObj->valueint;
|
|
||||||
|
if (subItemObj)
|
||||||
|
switch (subItemObj->type)
|
||||||
|
{
|
||||||
|
case aJson_Int:
|
||||||
|
if (subItemObj->valueint>=0 && subItemObj->valueint<SUBITEM_IS_COMMAND) subItem=subItemObj->valueint;
|
||||||
|
break;
|
||||||
|
case aJson_String:
|
||||||
|
int suffix=txt2cmd(subItemObj->valuestring);
|
||||||
|
if (suffix) subItem = suffix | SUBITEM_IS_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev && it && dev->type == aJson_Int && it->type == aJson_Int)
|
if (dev && it && dev->type == aJson_Int && it->type == aJson_Int)
|
||||||
return sendCommand(dev->valueint, it->valueint, cmd, status,subItem);
|
return sendCommand(dev->valueint, it->valueint, cmd, status,subItem);
|
||||||
@@ -754,6 +880,16 @@ bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command to a specified device by ID.
|
||||||
|
*
|
||||||
|
* @param devID Device ID to send the command to.
|
||||||
|
* @param itemID Item ID to send the command for.
|
||||||
|
* @param cmd Command structure containing the command information.
|
||||||
|
* @param status Indicates if the command is a status update.
|
||||||
|
* @param subItemID Sub-item identifier.
|
||||||
|
* @return true if the command was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool status,int subItemID )
|
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool status,int subItemID )
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -771,7 +907,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
packet.cmd = cmd.cmd;
|
packet.cmd = cmd.cmd;
|
||||||
packet.param = cmd.param;
|
packet.param = cmd.param;
|
||||||
|
|
||||||
debugSerial << ((status)?"CAN: send Status":"CAN: send Command");
|
debugSerial << ((status)?"CAN: Send Status":"CAN: Send Command");
|
||||||
debugSerial<<F(" ->[")<<devID<<":"<<itemID<<"] ";
|
debugSerial<<F(" ->[")<<devID<<":"<<itemID<<"] ";
|
||||||
if (subItemID!=NO_SUBITEM) debugSerial<<F("Subitem:")<<subItemID<<" ";
|
if (subItemID!=NO_SUBITEM) debugSerial<<F("Subitem:")<<subItemID<<" ";
|
||||||
cmd.debugOut();
|
cmd.debugOut();
|
||||||
@@ -789,6 +925,13 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
////////////////////////////// Steream //////////////////////////
|
////////////////////////////// Steream //////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends data over the CAN stream.
|
||||||
|
*
|
||||||
|
* @param len Length of the data to send.
|
||||||
|
* @param _seqNo Sequence number for the data.
|
||||||
|
* @return 1 if the data was sent successfully, 0 otherwise.
|
||||||
|
*/
|
||||||
int canStream::send(uint8_t len, uint16_t _seqNo)
|
int canStream::send(uint8_t len, uint16_t _seqNo)
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -811,6 +954,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks the state of the CAN stream and processes any incoming data.
|
||||||
|
*
|
||||||
|
* @return -1 on error, or the number of bytes available for reading.
|
||||||
|
*/
|
||||||
int canStream::checkState()
|
int canStream::checkState()
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
@@ -906,6 +1054,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
|
|
||||||
|
|
||||||
// Stream methods
|
// Stream methods
|
||||||
|
/**
|
||||||
|
* @brief Checks how many bytes are available for reading from the CAN stream.
|
||||||
|
*
|
||||||
|
* @return Number of bytes available, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::available()
|
int canStream::available()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -913,6 +1066,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
return avail;
|
return avail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a byte from the CAN stream.
|
||||||
|
*
|
||||||
|
* @return The byte read, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::read()
|
int canStream::read()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -927,6 +1085,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
else return -1;
|
else return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Peeks at the next byte in the CAN stream without removing it.
|
||||||
|
*
|
||||||
|
* @return The next byte, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::peek()
|
int canStream::peek()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -942,6 +1105,12 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a byte to the CAN stream.
|
||||||
|
*
|
||||||
|
* @param c The byte to write.
|
||||||
|
* @return The number of bytes written, or -1 on error.
|
||||||
|
*/
|
||||||
size_t canStream::write(uint8_t c)
|
size_t canStream::write(uint8_t c)
|
||||||
{
|
{
|
||||||
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
|
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
|
||||||
@@ -972,12 +1141,20 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
}
|
}
|
||||||
return 1; };
|
return 1; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes the CAN stream, sending any buffered data.
|
||||||
|
*/
|
||||||
void canStream::flush()
|
void canStream::flush()
|
||||||
{
|
{
|
||||||
send(writePos,seqNo);
|
send(writePos,seqNo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the CAN stream is available for writing.
|
||||||
|
*
|
||||||
|
* @return 1 if available, 0 if waiting for confirmation.
|
||||||
|
*/
|
||||||
int canStream::availableForWrite()
|
int canStream::availableForWrite()
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define NO_SUBITEM 63
|
#define NO_SUBITEM 63
|
||||||
|
#define SUBITEM_IS_COMMAND 0x20
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_STM32)
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
class colorChannel : public abstractOut {
|
class colorChannel : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
colorChannel(Item * _item):abstractOut(_item) {
|
colorChannel():iaddr(0),numArgs(0) {};
|
||||||
|
void link (Item * _item) {
|
||||||
|
abstractOut::link(_item);
|
||||||
iaddr = item->getArg(); //Once retrieve and store base address
|
iaddr = item->getArg(); //Once retrieve and store base address
|
||||||
if (iaddr<0) iaddr=-iaddr;
|
if (iaddr<0) iaddr=-iaddr;
|
||||||
numArgs = item->getArgCount(); // and how many addresses is configured
|
numArgs = item->getArgCount(); // and how many addresses is configured
|
||||||
};
|
};
|
||||||
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized=false) override;
|
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized=false) override;
|
||||||
//int getDefaultStorageType()override;
|
//int getDefaultStorageType()override;
|
||||||
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) =0;
|
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) =0;
|
||||||
|
|||||||
@@ -272,10 +272,11 @@ for (short rgbwChan=0; rgbwChan < RGBWChannels; rgbwChan++)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef _dmxout
|
#ifdef _dmxout
|
||||||
//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
|
debugSerial.print(F("DMXIN:"));
|
||||||
//debugSerial.println();
|
for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
|
||||||
//#endif
|
debugSerial.println();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -302,6 +303,7 @@ void DMXinSetup(int channels)
|
|||||||
if (channels>(32*4)) channels = 32*4;
|
if (channels>(32*4)) channels = 32*4;
|
||||||
DMXin = new uint8_t [channels];
|
DMXin = new uint8_t [channels];
|
||||||
DMXINChannels=channels;
|
DMXINChannels=channels;
|
||||||
|
// debugSerial<<F("DMXIN: init chans:")<<channels<<endl;
|
||||||
#if defined(ARDUINO_ARCH_AVR)
|
#if defined(ARDUINO_ARCH_AVR)
|
||||||
DMXSerial.init(DMXReceiver,0,channels);
|
DMXSerial.init(DMXReceiver,0,channels);
|
||||||
if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err"));
|
if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err"));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
|
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -139,23 +139,30 @@ void Input::Parse(aJsonObject * configObj)
|
|||||||
{
|
{
|
||||||
pin = static_cast<uint8_t>(itemBuffer->child->valueint);
|
pin = static_cast<uint8_t>(itemBuffer->child->valueint);
|
||||||
if ((itemBuffer->child->child) && (itemBuffer->child->child->type == aJson_Int))
|
if ((itemBuffer->child->child) && (itemBuffer->child->child->type == aJson_Int))
|
||||||
pin = static_cast<uint8_t>(itemBuffer->child->child->valueint);
|
pin2 = static_cast<uint8_t>(itemBuffer->child->child->valueint);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //switch
|
} //switch
|
||||||
else pin = static_cast<uint8_t>(atoi(configObj->name));
|
else pin = static_cast<uint8_t>(atoi(configObj->name));
|
||||||
|
|
||||||
|
store = (inStore *) &inputObj->valueint;
|
||||||
}
|
}
|
||||||
// Persistant storage
|
|
||||||
itemBuffer = aJson.getObjectItem(inputObj, "@S");
|
|
||||||
if (!itemBuffer) {
|
|
||||||
debugSerial<<F("In: ")<<pin<<F("/")<<inType<<endl;
|
|
||||||
aJson.addNumberToObject(inputObj, "@S", (long int) 0);
|
|
||||||
itemBuffer = aJson.getObjectItem(inputObj, "@S");
|
|
||||||
}
|
|
||||||
if (itemBuffer) store = (inStore *) &itemBuffer->valueint;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
void Input::stop()
|
||||||
|
{
|
||||||
|
if (!inputObj || !root || inputObj->type != aJson_Object) return;
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
aJsonObject *itemBuffer;
|
||||||
|
itemBuffer = aJson.getObjectItem(inputObj, "#");
|
||||||
|
if (inType == IN_RE && itemBuffer && itemBuffer->valuestring && itemBuffer->type == aJson_Array)
|
||||||
|
{
|
||||||
|
delete (RotaryEncoder *) itemBuffer->valuestring;
|
||||||
|
itemBuffer->valuestring = NULL;
|
||||||
|
debugSerial<<F("RE: deleted")<<endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void cleanStore(aJsonObject * input)
|
void cleanStore(aJsonObject * input)
|
||||||
{
|
{
|
||||||
@@ -164,7 +171,7 @@ if (input && (input->type == aJson_Object)) {
|
|||||||
Input in(input);
|
Input in(input);
|
||||||
in.store->aslong = 0;
|
in.store->aslong = 0;
|
||||||
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
||||||
if (inputArray && (inputArray->type == aJson_Array))
|
if (inputArray && (inputArray->type == aJson_Array || inputArray->type == aJson_Object))
|
||||||
{
|
{
|
||||||
aJsonObject *inputObj = inputArray->child;
|
aJsonObject *inputObj = inputArray->child;
|
||||||
|
|
||||||
@@ -185,15 +192,37 @@ if (input && (input->type == aJson_Object)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Input::setupRotaryEncoder()
|
||||||
|
{
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
aJsonObject *itemBuffer;
|
||||||
|
if (!inputObj || !root || inputObj->type != aJson_Object) return;
|
||||||
|
itemBuffer = aJson.getObjectItem(inputObj, "#");
|
||||||
|
if (itemBuffer && !itemBuffer->valuestring && itemBuffer->type == aJson_Array)
|
||||||
|
{
|
||||||
|
int pin1 = getIntFromJson(itemBuffer,1,-1);
|
||||||
|
int pin2 = getIntFromJson(itemBuffer,2,-1);
|
||||||
|
int mode = getIntFromJson(itemBuffer,3,(int)RotaryEncoder::LatchMode::FOUR3);
|
||||||
|
if (pin1>=0 && pin2>=0)
|
||||||
|
{
|
||||||
|
itemBuffer->valuestring = ( char *) new RotaryEncoder(pin1, pin2, (RotaryEncoder::LatchMode)mode);
|
||||||
|
debugSerial<<F("RE: configured on pins ")<<pin1<<","<<pin2<< F(" Mode:")<<mode <<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Input::setup()
|
void Input::setup()
|
||||||
{
|
{
|
||||||
if (!isValid() || (!root)) return;
|
if (!isValid() || (!root)) return;
|
||||||
cleanStore(inputObj);
|
cleanStore(inputObj);
|
||||||
|
debugSerial<<F("In: ")<<pin<<F("/")<<inType<<endl;
|
||||||
store->aslong=0;
|
store->aslong=0;
|
||||||
uint8_t inputPinMode = INPUT; //if IN_ACTIVE_HIGH
|
uint8_t inputPinMode = INPUT; //if IN_ACTIVE_HIGH
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
|
case IN_RE:
|
||||||
|
setupRotaryEncoder();
|
||||||
case IN_PUSH_ON:
|
case IN_PUSH_ON:
|
||||||
case IN_PUSH_TOGGLE :
|
case IN_PUSH_TOGGLE :
|
||||||
inputPinMode = INPUT_PULLUP;
|
inputPinMode = INPUT_PULLUP;
|
||||||
@@ -201,7 +230,7 @@ switch (inType)
|
|||||||
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
||||||
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
||||||
pinMode(pin, inputPinMode);
|
pinMode(pin, inputPinMode);
|
||||||
|
|
||||||
store->state=IS_IDLE;
|
store->state=IS_IDLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -256,14 +285,14 @@ switch (inType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Input::Poll(short cause) {
|
int Input::Poll(short cause) {
|
||||||
|
aJsonObject * itemBuffer;
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
#ifndef CSSHDC_DISABLE
|
#ifndef CSSHDC_DISABLE
|
||||||
in_ccs811 _ccs811(this);
|
in_ccs811 _ccs811(this);
|
||||||
in_hdc1080 _hdc1080(this);
|
in_hdc1080 _hdc1080(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case CHECK_INPUT: //Fast polling
|
case CHECK_INPUT: //Fast polling
|
||||||
case CHECK_INTERRUPT: //Realtime polling
|
case CHECK_INTERRUPT: //Realtime polling
|
||||||
switch (inType)
|
switch (inType)
|
||||||
@@ -290,16 +319,27 @@ switch (cause) {
|
|||||||
case IN_CCS811:
|
case IN_CCS811:
|
||||||
case IN_HDC1080:
|
case IN_HDC1080:
|
||||||
break;
|
break;
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
case IN_RE:
|
||||||
|
itemBuffer = aJson.getObjectItem(inputObj, "#");
|
||||||
|
if (inputObj && inputObj->type == aJson_Object && itemBuffer && itemBuffer->type == aJson_Array && itemBuffer->valuestring)
|
||||||
|
{
|
||||||
|
((RotaryEncoder *) itemBuffer->valuestring) ->tick();
|
||||||
|
contactPoll(cause, ((RotaryEncoder *) itemBuffer->valuestring));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef ULTRASONIC
|
||||||
case CHECK_ULTRASONIC:
|
case CHECK_ULTRASONIC:
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
case IN_ULTRASONIC:
|
case IN_ULTRASONIC:
|
||||||
analogPoll(cause);
|
analogPoll(cause);
|
||||||
contactPoll(cause);
|
contactPoll(cause);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case CHECK_SENSOR: //Slow polling
|
case CHECK_SENSOR: //Slow polling
|
||||||
switch (inType)
|
switch (inType)
|
||||||
{
|
{
|
||||||
@@ -559,10 +599,91 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
|
|||||||
setNextPollTime(millis());
|
setNextPollTime(millis());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// To Be Refactored - move to Execute after class Input inheritation on abstract chan
|
||||||
|
bool Input::checkInstructions(aJsonObject * obj)
|
||||||
|
{
|
||||||
|
aJsonObject *gotoObj = aJson.getObjectItem(obj, "activate");
|
||||||
|
if (gotoObj)
|
||||||
|
switch (gotoObj->type)
|
||||||
|
{ case aJson_Array:
|
||||||
|
{
|
||||||
|
char * name = getStringFromJson(gotoObj,0);
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
Input in (name);
|
||||||
|
debugSerial<<"IN: "<<name<< " is "<<in.isValid()<<endl;
|
||||||
|
if (in.isValid()) return in.setCurrentInput(aJson.getArrayItem(gotoObj,1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case aJson_Int:
|
||||||
|
case aJson_String:
|
||||||
|
return setCurrentInput(gotoObj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aJsonObject * Input::getCurrentInput()
|
||||||
|
{
|
||||||
|
if (!inputObj) return NULL;
|
||||||
|
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
|
||||||
|
if (act && (act->type == aJson_Array || act->type == aJson_Object) && act->valuestring) return (aJsonObject * ) act->valuestring;
|
||||||
|
return inputObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Input::setCurrentInput(aJsonObject * obj)
|
||||||
|
{
|
||||||
|
if (!obj) return false;
|
||||||
|
switch (obj->type)
|
||||||
|
{
|
||||||
|
case aJson_Int:
|
||||||
|
debugSerial<<F("Activate in ")<<pin <<" to "<< obj->valueint <<endl;
|
||||||
|
return setCurrentInput(obj->valueint);
|
||||||
|
break;
|
||||||
|
case aJson_String:
|
||||||
|
debugSerial<<F("Activate in ")<<pin <<" to "<< obj->valuestring <<endl;
|
||||||
|
return setCurrentInput(obj->valuestring);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Input::setCurrentInput(int n)
|
||||||
|
{
|
||||||
|
if (!inputObj) return false;
|
||||||
|
aJsonObject * curInput = NULL;
|
||||||
|
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
|
||||||
|
if (act && (act->type == aJson_Array || act->type ==aJson_Object))
|
||||||
|
{
|
||||||
|
if (n)
|
||||||
|
curInput = aJson.getArrayItem(act,n-1);
|
||||||
|
else curInput = inputObj;
|
||||||
|
act->valuestring = (char *) curInput;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Input::setCurrentInput(char * name)
|
||||||
|
{
|
||||||
|
if (!inputObj) return false;
|
||||||
|
aJsonObject * curInput = NULL;
|
||||||
|
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
|
||||||
|
if (act && act->type == aJson_Object)
|
||||||
|
{
|
||||||
|
if (name && *name)
|
||||||
|
curInput = aJson.getObjectItem(act,name);
|
||||||
|
else curInput = inputObj;
|
||||||
|
act->valuestring = (char *) curInput;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
|
||||||
bool Input::
|
bool Input::
|
||||||
changeState(uint8_t newState, short cause)
|
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer)
|
||||||
{
|
{
|
||||||
if (!inputObj || !store) return false;
|
if (!inputObj || !store) return false;
|
||||||
|
|
||||||
@@ -572,6 +693,7 @@ if (newState == IS_REQSTATE)
|
|||||||
// Requested delayed change State and safe moment
|
// Requested delayed change State and safe moment
|
||||||
newState=store->reqState; //Retrieve requested state
|
newState=store->reqState; //Retrieve requested state
|
||||||
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
|
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
|
||||||
|
contactState = store->lastValue;
|
||||||
if (store->state == newState)
|
if (store->state == newState)
|
||||||
{
|
{
|
||||||
store->delayedState = false;
|
store->delayedState = false;
|
||||||
@@ -593,37 +715,37 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
switch (store->state)
|
switch (store->state)
|
||||||
{
|
{
|
||||||
case IS_RELEASED: //click
|
case IS_RELEASED: //click
|
||||||
cmd = aJson.getObjectItem(inputObj, "click");
|
cmd = aJson.getObjectItem(currentInputObject, "click");
|
||||||
toggle=store->toggle1;
|
toggle=store->toggle1;
|
||||||
break;
|
break;
|
||||||
case IS_RELEASED2: //doubleclick
|
case IS_RELEASED2: //doubleclick
|
||||||
cmd = aJson.getObjectItem(inputObj, "dclick");
|
cmd = aJson.getObjectItem(currentInputObject, "dclick");
|
||||||
toggle=store->toggle2;
|
toggle=store->toggle2;
|
||||||
break;
|
break;
|
||||||
case IS_PRESSED3: //tripple click
|
case IS_PRESSED3: //tripple click
|
||||||
cmd = aJson.getObjectItem(inputObj, "tclick");
|
cmd = aJson.getObjectItem(currentInputObject, "tclick");
|
||||||
toggle=store->toggle3;
|
toggle=store->toggle3;
|
||||||
break;
|
break;
|
||||||
case IS_WAITPRESS: //do nothing
|
case IS_WAITPRESS: //do nothing
|
||||||
break;
|
break;
|
||||||
default: //rcmd
|
default: //rcmd
|
||||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
cmd = aJson.getObjectItem(currentInputObject, "rcmd");
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IS_PRESSED: //scmd
|
case IS_PRESSED: //scmd
|
||||||
cmd = aJson.getObjectItem(inputObj, "scmd");
|
cmd = aJson.getObjectItem(currentInputObject, "scmd");
|
||||||
toggle=store->toggle1;
|
toggle=store->toggle1;
|
||||||
store->toggle1 = !store->toggle1;
|
store->toggle1 = !store->toggle1;
|
||||||
if (!cmd) defCmd.Cmd(CMD_ON);
|
if (!cmd) defCmd.Cmd(CMD_ON);
|
||||||
break;
|
break;
|
||||||
case IS_PRESSED2: //scmd2
|
case IS_PRESSED2: //scmd2
|
||||||
cmd = aJson.getObjectItem(inputObj, "scmd2");
|
cmd = aJson.getObjectItem(currentInputObject, "scmd2");
|
||||||
toggle=store->toggle2;
|
toggle=store->toggle2;
|
||||||
store->toggle2 = !store->toggle2;
|
store->toggle2 = !store->toggle2;
|
||||||
break;
|
break;
|
||||||
case IS_PRESSED3: //scmd3
|
case IS_PRESSED3: //scmd3
|
||||||
cmd = aJson.getObjectItem(inputObj, "scmd3");
|
cmd = aJson.getObjectItem(currentInputObject, "scmd3");
|
||||||
toggle=store->toggle3;
|
toggle=store->toggle3;
|
||||||
store->toggle3 = !store->toggle3;
|
store->toggle3 = !store->toggle3;
|
||||||
break;
|
break;
|
||||||
@@ -631,47 +753,69 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
case IS_RELEASED: //rcmd
|
case IS_RELEASED: //rcmd
|
||||||
case IS_WAITPRESS:
|
case IS_WAITPRESS:
|
||||||
case IS_RELEASED2:
|
case IS_RELEASED2:
|
||||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
cmd = aJson.getObjectItem(currentInputObject, "rcmd");
|
||||||
if (!cmd) defCmd.Cmd(CMD_OFF);
|
if (!cmd) defCmd.Cmd(CMD_OFF);
|
||||||
// toggle=state->toggle1;
|
// toggle=state->toggle1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case IS_LONG: //lcmd
|
case IS_LONG: //lcmd
|
||||||
cmd = aJson.getObjectItem(inputObj, "lcmd");
|
cmd = aJson.getObjectItem(currentInputObject, "lcmd");
|
||||||
toggle=store->toggle1;
|
toggle=store->toggle1;
|
||||||
break;
|
break;
|
||||||
case IS_REPEAT: //rpcmd
|
case IS_REPEAT: //rpcmd
|
||||||
cmd = aJson.getObjectItem(inputObj, "rpcmd");
|
cmd = aJson.getObjectItem(currentInputObject, "rpcmd");
|
||||||
toggle=store->toggle1;
|
toggle=store->toggle1;
|
||||||
break;
|
break;
|
||||||
case IS_LONG2: //lcmd2
|
case IS_LONG2: //lcmd2
|
||||||
cmd = aJson.getObjectItem(inputObj, "lcmd2");
|
cmd = aJson.getObjectItem(currentInputObject, "lcmd2");
|
||||||
toggle=store->toggle2;
|
toggle=store->toggle2;
|
||||||
break;
|
break;
|
||||||
case IS_REPEAT2: //rpcmd2
|
case IS_REPEAT2: //rpcmd2
|
||||||
cmd = aJson.getObjectItem(inputObj, "rpcmd2");
|
cmd = aJson.getObjectItem(currentInputObject, "rpcmd2");
|
||||||
toggle=store->toggle2;
|
toggle=store->toggle2;
|
||||||
break;
|
break;
|
||||||
case IS_LONG3: //lcmd3
|
case IS_LONG3: //lcmd3
|
||||||
cmd = aJson.getObjectItem(inputObj, "lcmd3");
|
cmd = aJson.getObjectItem(currentInputObject, "lcmd3");
|
||||||
toggle=store->toggle3;
|
toggle=store->toggle3;
|
||||||
break;
|
break;
|
||||||
case IS_REPEAT3: //rpcmd3
|
case IS_REPEAT3: //rpcmd3
|
||||||
cmd = aJson.getObjectItem(inputObj, "rpcmd3");
|
cmd = aJson.getObjectItem(currentInputObject, "rpcmd3");
|
||||||
toggle=store->toggle3;
|
toggle=store->toggle3;
|
||||||
break;
|
break;
|
||||||
|
case IS_NOP:
|
||||||
|
if (!calledOnTimer) break;
|
||||||
|
if (contactState)
|
||||||
|
cmd = aJson.getObjectItem(currentInputObject, "scmd");
|
||||||
|
else cmd = aJson.getObjectItem(currentInputObject, "rcmd");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
aJsonObject *defaultItem = aJson.getObjectItem(inputObj, "item");
|
if (!calledOnTimer || newState == IS_NOP)
|
||||||
aJsonObject *defaultEmit = aJson.getObjectItem(inputObj, "emit");
|
{
|
||||||
aJsonObject *defaultCan = aJson.getObjectItem(inputObj, "can");
|
if (cause != CHECK_INTERRUPT)
|
||||||
|
{
|
||||||
|
onContactChanged(contactState);
|
||||||
|
store->delayedState=false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
store->delayedState=true;
|
||||||
|
store->lastValue = contactState;
|
||||||
|
store->reqState=newState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((newState == IS_NOP) && !calledOnTimer) return true;
|
||||||
|
|
||||||
|
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
|
||||||
|
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
|
||||||
|
aJsonObject *defaultCan = aJson.getObjectItem(currentInputObject, "can");
|
||||||
|
|
||||||
if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID);
|
if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID);
|
||||||
|
|
||||||
if (!cmd && !defCmd.isCommand())
|
if (!cmd && !defCmd.isCommand())
|
||||||
{
|
{
|
||||||
store->state=newState;
|
if (newState !=IS_NOP) store->state=newState;
|
||||||
store->delayedState=false;
|
store->delayedState=false;
|
||||||
return true; //nothing to do
|
return true; //nothing to do
|
||||||
}
|
}
|
||||||
@@ -679,15 +823,16 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
|
|
||||||
if (cause != CHECK_INTERRUPT)
|
if (cause != CHECK_INTERRUPT)
|
||||||
{
|
{
|
||||||
store->state=newState;
|
if (newState !=IS_NOP) store->state=newState;
|
||||||
store->delayedState=false;
|
store->delayedState=false;
|
||||||
|
checkInstructions(cmd);
|
||||||
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
|
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Postpone actual execution
|
//Postpone actual execution
|
||||||
if (newState != store->state)
|
if ((newState != store->state) && (newState !=IS_NOP))
|
||||||
{
|
{
|
||||||
store->reqState=newState;
|
store->reqState=newState;
|
||||||
store->delayedState=true;
|
store->delayedState=true;
|
||||||
@@ -698,16 +843,22 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
}
|
}
|
||||||
|
|
||||||
static volatile uint8_t contactPollBusy = 0;
|
static volatile uint8_t contactPollBusy = 0;
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
void Input::contactPoll(short cause, RotaryEncoder * re)
|
||||||
|
#else
|
||||||
|
void Input::contactPoll(short cause)
|
||||||
|
#endif
|
||||||
|
|
||||||
void Input::contactPoll(short cause) {
|
|
||||||
|
{
|
||||||
bool currentInputState;
|
bool currentInputState;
|
||||||
|
|
||||||
if (!store /*|| contactPollBusy*/) return;
|
if (!store /*|| contactPollBusy*/) return;
|
||||||
if ((inType == IN_ULTRASONIC) && (cause!=CHECK_ULTRASONIC)) return;
|
if ((inType == IN_ULTRASONIC) && (cause!=CHECK_ULTRASONIC)) return;
|
||||||
|
|
||||||
contactPollBusy++;
|
contactPollBusy++;
|
||||||
|
aJsonObject * currentInputObject = getCurrentInput();
|
||||||
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
|
changeState(IS_REQSTATE,cause,currentInputObject,false); //Check for postponed states transitions
|
||||||
|
|
||||||
|
|
||||||
uint8_t inputOnLevel;
|
uint8_t inputOnLevel;
|
||||||
@@ -730,20 +881,22 @@ else
|
|||||||
}
|
}
|
||||||
else currentInputState = (digitalRead(pin) == inputOnLevel);
|
else currentInputState = (digitalRead(pin) == inputOnLevel);
|
||||||
|
|
||||||
if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
if (cause != CHECK_INTERRUPT)
|
||||||
|
{
|
||||||
|
switch (store->state) //Timer based transitions
|
||||||
{
|
{
|
||||||
case IS_PRESSED:
|
case IS_PRESSED:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(inputObj, "rpcmd")) changeState(IS_WAITRELEASE, cause);
|
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
|
||||||
else changeState(IS_LONG, cause);
|
else changeState(IS_LONG, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -751,7 +904,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT:
|
case IS_REPEAT:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -759,15 +912,15 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED2:
|
case IS_PRESSED2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(inputObj, "lcmd2") && !aJson.getObjectItem(inputObj, "rpcmd2")) changeState(IS_WAITRELEASE, cause);
|
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
|
||||||
else changeState(IS_LONG2, cause);
|
else changeState(IS_LONG2, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG2:
|
case IS_LONG2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -775,7 +928,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT2:
|
case IS_REPEAT2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -783,19 +936,19 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED3:
|
case IS_PRESSED3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(inputObj, "lcmd3") && !aJson.getObjectItem(inputObj, "rpcmd3")) //No longpress handlers
|
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
|
||||||
{
|
{
|
||||||
if (aJson.getObjectItem(inputObj, "scmd3")) changeState(IS_WAITRELEASE, cause); //was used
|
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true); //was used
|
||||||
else changeState(IS_PRESSED2, cause); // completely empty trippleClick section - fallback to first click handler
|
else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState,true); // completely empty trippleClick section - fallback to first click handler
|
||||||
}
|
}
|
||||||
else changeState(IS_LONG3, cause);
|
else changeState(IS_LONG3, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG3:
|
case IS_LONG3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -803,7 +956,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT3:
|
case IS_REPEAT3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -813,11 +966,28 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_WAITPRESS:
|
case IS_WAITPRESS:
|
||||||
|
|
||||||
|
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause);
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState,true);
|
||||||
break;
|
break;
|
||||||
|
} //switch
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
if (re)
|
||||||
|
{
|
||||||
|
aJsonObject * bufferItem;
|
||||||
|
switch (re->getDirection())
|
||||||
|
{
|
||||||
|
case RotaryEncoder::Direction::CLOCKWISE:
|
||||||
|
if (bufferItem=aJson.getObjectItem(currentInputObject, "+-")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
|
||||||
|
if (bufferItem=aJson.getObjectItem(currentInputObject, "+")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
|
||||||
|
break;
|
||||||
|
case RotaryEncoder::Direction::COUNTERCLOCKWISE:
|
||||||
|
if (bufferItem=aJson.getObjectItem(currentInputObject, "+-")) {checkInstructions(bufferItem);executeCommand(bufferItem,1);};
|
||||||
|
if (bufferItem=aJson.getObjectItem(currentInputObject, "-")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (currentInputState != store->lastValue) // value changed
|
} //if not INTERRUPT
|
||||||
|
if ((currentInputState != store->lastValue) || // value changed
|
||||||
|
(isTimeOver(store->timestamp16,millis() & 0xFFFF,T_REPEAT,0xFFFF) && getIntFromJson(currentInputObject,"repeat")))
|
||||||
{
|
{
|
||||||
if (store->bounce) store->bounce = store->bounce - 1;
|
if (store->bounce) store->bounce = store->bounce - 1;
|
||||||
else //confirmed change
|
else //confirmed change
|
||||||
@@ -835,7 +1005,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
} else */
|
} else */
|
||||||
|
|
||||||
{
|
{
|
||||||
// onContactChanged(currentInputState); //Legacy input - to remove later
|
////// onContactChanged(currentInputState); //Legacy input - to remove later // wrong place - INTERRUPTS
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
if (currentInputState) //Button pressed state transitions
|
if (currentInputState) //Button pressed state transitions
|
||||||
@@ -843,52 +1013,55 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
switch (store->state)
|
switch (store->state)
|
||||||
{
|
{
|
||||||
case IS_IDLE:
|
case IS_IDLE:
|
||||||
res = changeState(IS_PRESSED, cause);
|
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_RELEASED:
|
case IS_RELEASED:
|
||||||
case IS_WAITPRESS:
|
case IS_WAITPRESS:
|
||||||
if ( //No future
|
if ( //No future
|
||||||
!aJson.getObjectItem(inputObj, "scmd2") &&
|
!aJson.getObjectItem(currentInputObject, "scmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "lcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "rpcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "dclick")
|
!aJson.getObjectItem(currentInputObject, "dclick")
|
||||||
)
|
)
|
||||||
res = changeState(IS_PRESSED, cause);
|
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
else res = changeState(IS_PRESSED2, cause);
|
else res = changeState(IS_PRESSED2, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_RELEASED2:
|
case IS_RELEASED2:
|
||||||
|
|
||||||
res = changeState(IS_PRESSED3, cause);
|
res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState,(currentInputState == store->lastValue));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
switch (store->state) //Button released state transitions
|
switch (store->state) //Button released state transitions
|
||||||
{
|
{
|
||||||
case IS_PRESSED:
|
case IS_PRESSED:
|
||||||
|
|
||||||
res = changeState(IS_RELEASED, cause);
|
res = changeState(IS_RELEASED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
case IS_REPEAT:
|
case IS_REPEAT:
|
||||||
case IS_WAITRELEASE:
|
case IS_WAITRELEASE:
|
||||||
res = changeState(IS_WAITPRESS, cause);
|
res = changeState(IS_WAITPRESS, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_PRESSED2:
|
case IS_PRESSED2:
|
||||||
if ( //No future
|
if ( //No future
|
||||||
!aJson.getObjectItem(inputObj, "scmd2") &&
|
!aJson.getObjectItem(currentInputObject, "scmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "lcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "rpcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
||||||
!aJson.getObjectItem(inputObj, "dclick")
|
!aJson.getObjectItem(currentInputObject, "dclick")
|
||||||
) res = changeState(IS_IDLE, cause);
|
) res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
else res = changeState(IS_RELEASED2, cause);
|
else res = changeState(IS_RELEASED2, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG2:
|
case IS_LONG2:
|
||||||
@@ -896,8 +1069,10 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
|||||||
case IS_LONG3:
|
case IS_LONG3:
|
||||||
case IS_REPEAT3:
|
case IS_REPEAT3:
|
||||||
case IS_PRESSED3:
|
case IS_PRESSED3:
|
||||||
res = changeState(IS_IDLE, cause);
|
res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState, (currentInputState == store->lastValue));
|
||||||
}
|
}
|
||||||
if (res) { //State changed or postponed
|
if (res) { //State changed or postponed
|
||||||
// store->logicState = currentInputState;
|
// store->logicState = currentInputState;
|
||||||
@@ -1019,13 +1194,14 @@ strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
|||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||||
|
|
||||||
if (newValue) { //send set command
|
if (newValue) { //send set command
|
||||||
if (!scmd || scmd->type != aJson_String) mqttClient.publish(addrstr, "ON", true);
|
if (!scmd) {mqttClient.publish(addrstr, "ON", true); debugSerial<<F("Emit:")<<addrstr<< F("->") << "ON"<<endl;}
|
||||||
else if (strlen(scmd->valuestring))
|
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
|
||||||
mqttClient.publish(addrstr, scmd->valuestring, true);
|
{mqttClient.publish(addrstr, scmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << scmd->valuestring<<endl;}
|
||||||
} else { //send reset command
|
} else { //send reset command
|
||||||
if (!rcmd || rcmd->type != aJson_String) mqttClient.publish(addrstr, "OFF", true);
|
if (!rcmd) {mqttClient.publish(addrstr, "OFF", true);debugSerial<<F("Emit:")<<addrstr<< F("->") << "OFF"<<endl;}
|
||||||
else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true);
|
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring)) {mqttClient.publish(addrstr, rcmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << rcmd->valuestring<<endl;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //NOIP
|
#endif //NOIP
|
||||||
@@ -1036,12 +1212,12 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
|
|||||||
Item it(item->valuestring);
|
Item it(item->valuestring);
|
||||||
if (it.isValid()) {
|
if (it.isValid()) {
|
||||||
if (newValue) { //send set command
|
if (newValue) { //send set command
|
||||||
if (!scmd || scmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
|
if (!scmd ) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
|
||||||
else if (strlen(scmd->valuestring))
|
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
|
||||||
it.Ctrl(scmd->valuestring);
|
it.Ctrl(scmd->valuestring);
|
||||||
} else { //send reset command
|
} else { //send reset command
|
||||||
if (!rcmd || rcmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
|
if (!rcmd ) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
|
||||||
else if (strlen(rcmd->valuestring))
|
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring))
|
||||||
it.Ctrl(rcmd->valuestring);
|
it.Ctrl(rcmd->valuestring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1070,6 +1246,7 @@ void Input::onAnalogChanged(itemCmd newValue) {
|
|||||||
|
|
||||||
// New tyle unified activities
|
// New tyle unified activities
|
||||||
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
|
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
|
||||||
|
//checkInstructions(act);
|
||||||
executeCommand(act,-1,newValue);
|
executeCommand(act,-1,newValue);
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
|
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,6 +21,9 @@ e-mail anklimov@gmail.com
|
|||||||
#include <aJSON.h>
|
#include <aJSON.h>
|
||||||
#include "modules/in_ccs811_hdc1080.h"
|
#include "modules/in_ccs811_hdc1080.h"
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
#include "RotaryEncoder.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IN_ACTIVE_HIGH 2 // High level = PUSHED/ CLOSED/ ON othervise :Low Level. Use INPUT mode instead of INPUT_PULLUP for digital pin
|
#define IN_ACTIVE_HIGH 2 // High level = PUSHED/ CLOSED/ ON othervise :Low Level. Use INPUT mode instead of INPUT_PULLUP for digital pin
|
||||||
#define IN_ANALOG 64 // Analog input
|
#define IN_ANALOG 64 // Analog input
|
||||||
@@ -53,6 +56,7 @@ e-mail anklimov@gmail.com
|
|||||||
#define IS_REPEAT3 12u
|
#define IS_REPEAT3 12u
|
||||||
#define IS_WAITRELEASE 13u
|
#define IS_WAITRELEASE 13u
|
||||||
#define IS_REQSTATE 0xFF
|
#define IS_REQSTATE 0xFF
|
||||||
|
#define IS_NOP 0xF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -70,6 +74,7 @@ e-mail anklimov@gmail.com
|
|||||||
#define T_IDLE 600
|
#define T_IDLE 600
|
||||||
#define T_RPT 300
|
#define T_RPT 300
|
||||||
#define T_RPT_PULSE 150
|
#define T_RPT_PULSE 150
|
||||||
|
#define T_REPEAT 30000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -149,6 +154,7 @@ public:
|
|||||||
|
|
||||||
int Poll(short cause);
|
int Poll(short cause);
|
||||||
void setup();
|
void setup();
|
||||||
|
void stop();
|
||||||
|
|
||||||
static void inline onCounterChanged(int i);
|
static void inline onCounterChanged(int i);
|
||||||
static void onCounterChanged0();
|
static void onCounterChanged0();
|
||||||
@@ -163,7 +169,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void Parse(aJsonObject * configObj = NULL);
|
void Parse(aJsonObject * configObj = NULL);
|
||||||
|
|
||||||
|
#ifdef ROTARYENCODER
|
||||||
|
void contactPoll(short cause, RotaryEncoder * re = NULL);
|
||||||
|
#else
|
||||||
void contactPoll(short cause);
|
void contactPoll(short cause);
|
||||||
|
#endif
|
||||||
|
|
||||||
void analogPoll(short cause);
|
void analogPoll(short cause);
|
||||||
|
|
||||||
void dht22Poll();
|
void dht22Poll();
|
||||||
@@ -182,7 +193,16 @@ protected:
|
|||||||
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
||||||
|
|
||||||
char* getIdxField();
|
char* getIdxField();
|
||||||
bool changeState(uint8_t newState, short cause);
|
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer = false);
|
||||||
|
void setupRotaryEncoder();
|
||||||
|
|
||||||
|
aJsonObject * getCurrentInput();
|
||||||
|
|
||||||
|
bool setCurrentInput(aJsonObject * obj);
|
||||||
|
bool setCurrentInput(int n);
|
||||||
|
bool setCurrentInput(char * name);
|
||||||
|
bool checkInstructions(aJsonObject * obj);
|
||||||
|
|
||||||
//bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL);
|
//bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ extern PubSubClient mqttClient;
|
|||||||
extern int8_t ethernetIdleCount;
|
extern int8_t ethernetIdleCount;
|
||||||
extern int8_t configLocked;
|
extern int8_t configLocked;
|
||||||
extern lan_status lanStatus;
|
extern lan_status lanStatus;
|
||||||
|
driverFactory df;
|
||||||
|
|
||||||
int retrieveCode(char **psubItem);
|
int retrieveCode(char **psubItem);
|
||||||
|
|
||||||
@@ -105,6 +106,7 @@ int subitem2cmd(char *payload) {
|
|||||||
else if (strcmp_P(payload, AUTO_P) == 0) cmd = CMD_AUTO;
|
else if (strcmp_P(payload, AUTO_P) == 0) cmd = CMD_AUTO;
|
||||||
else if (strcmp_P(payload, FAN_ONLY_P) == 0) cmd = CMD_FAN;
|
else if (strcmp_P(payload, FAN_ONLY_P) == 0) cmd = CMD_FAN;
|
||||||
else if (strcmp_P(payload, DRY_P) == 0) cmd = CMD_DRY;
|
else if (strcmp_P(payload, DRY_P) == 0) cmd = CMD_DRY;
|
||||||
|
else if (strcmp_P(payload, HEATCOOL_P) == 0) cmd = CMD_HEATCOOL;
|
||||||
//else if (strcmp_P(payload, HIGH_P) == 0) cmd = CMD_HIGH;
|
//else if (strcmp_P(payload, HIGH_P) == 0) cmd = CMD_HIGH;
|
||||||
//else if (strcmp_P(payload, MED_P) == 0) cmd = CMD_MED;
|
//else if (strcmp_P(payload, MED_P) == 0) cmd = CMD_MED;
|
||||||
//else if (strcmp_P(payload, LOW_P) == 0) cmd = CMD_LOW;
|
//else if (strcmp_P(payload, LOW_P) == 0) cmd = CMD_LOW;
|
||||||
@@ -172,7 +174,8 @@ void Item::Parse() {
|
|||||||
if (cmdObj) itemExt = cmdObj->next;
|
if (cmdObj) itemExt = cmdObj->next;
|
||||||
|
|
||||||
itemType = replaceTypeToInt (itemTypeObj);
|
itemType = replaceTypeToInt (itemTypeObj);
|
||||||
|
driver=df.getDriver(this);
|
||||||
|
/*
|
||||||
switch (itemType)
|
switch (itemType)
|
||||||
{
|
{
|
||||||
#ifndef PWM_DISABLE
|
#ifndef PWM_DISABLE
|
||||||
@@ -265,14 +268,13 @@ void Item::Parse() {
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: ;
|
default: ;
|
||||||
}
|
} */
|
||||||
// debugSerial << F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << endl;
|
// debugSerial << F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean Item::Setup()
|
boolean Item::Setup()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (driver)
|
if (driver)
|
||||||
{
|
{
|
||||||
if (driver->Status()) driver->Stop();
|
if (driver->Status()) driver->Stop();
|
||||||
@@ -287,7 +289,7 @@ else return false;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Item::Stop()
|
void Item::Stop()
|
||||||
{
|
{
|
||||||
if (driver)
|
if (driver)
|
||||||
{
|
{
|
||||||
driver->Stop();
|
driver->Stop();
|
||||||
@@ -299,7 +301,7 @@ Item::~Item()
|
|||||||
{
|
{
|
||||||
if (driver)
|
if (driver)
|
||||||
{
|
{
|
||||||
delete driver;
|
df.freeDriver (this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +358,7 @@ uint16_t getCanNum(aJsonObject* verb)
|
|||||||
|
|
||||||
char * Item::getSubItemStrById(uint8_t subItem)
|
char * Item::getSubItemStrById(uint8_t subItem)
|
||||||
{
|
{
|
||||||
if (subItem == NO_SUBITEM) return NULL;
|
if (subItem == NO_SUBITEM || (subItem & SUBITEM_IS_COMMAND)) return NULL;
|
||||||
if (!itemArg) return NULL;
|
if (!itemArg) return NULL;
|
||||||
aJsonObject * i = itemArg;
|
aJsonObject * i = itemArg;
|
||||||
if (i->type == aJson_Array) i=i->child;
|
if (i->type == aJson_Array) i=i->child;
|
||||||
@@ -419,10 +421,20 @@ return NO_SUBITEM;
|
|||||||
{
|
{
|
||||||
if (getCanNum(itemArr->child) == num)
|
if (getCanNum(itemArr->child) == num)
|
||||||
{
|
{
|
||||||
debugSerial<<"Find item: "<< itemArr->name << " addr:" << num << endl;
|
debugSerial<<"CAN: Find item: "<< itemArr->name << " id:" << num << "sub:" << subItem;
|
||||||
Parse();
|
Parse();
|
||||||
char * subItemStr = getSubItemStrById(subItem);
|
if (subItem & SUBITEM_IS_COMMAND)
|
||||||
if (subItemStr) strncpy(defaultSubItem,subItemStr,sizeof(defaultSubItem));
|
{
|
||||||
|
subItem &=~ SUBITEM_IS_COMMAND;
|
||||||
|
if (subItem<commandsNum) strncpy_P(defaultSubItem, commands_P[subItem], sizeof(defaultSubItem));
|
||||||
|
debugSerial<<" subcmd:"<<defaultSubItem<<endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char * subItemStr = getSubItemStrById(subItem);
|
||||||
|
if (subItemStr) strncpy(defaultSubItem,subItemStr,sizeof(defaultSubItem));
|
||||||
|
debugSerial<<" subname:"<<defaultSubItem<<endl;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
itemArr = itemArr->next;
|
itemArr = itemArr->next;
|
||||||
@@ -796,7 +808,7 @@ st.setSuffix(suffixCode);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (remoteID) return remoteCtrl(st,remoteID,subItem,authToken);
|
if (remoteID) return remoteCtrl(st,remoteID,subItem,authToken);
|
||||||
return Ctrl(st,subItem,true,authorized);
|
return Ctrl(st,subItem,0,authorized);
|
||||||
} //Void command
|
} //Void command
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -829,14 +841,14 @@ st.setSuffix(suffixCode);
|
|||||||
Par0.Cmd(cmd);
|
Par0.Cmd(cmd);
|
||||||
Par0.setSuffix(suffixCode);
|
Par0.setSuffix(suffixCode);
|
||||||
if (remoteID) return remoteCtrl(Par0,remoteID,subItem,authToken);
|
if (remoteID) return remoteCtrl(Par0,remoteID,subItem,authToken);
|
||||||
return Ctrl(Par0, subItem,true,authorized);
|
return Ctrl(Par0, subItem,0,authorized);
|
||||||
}
|
}
|
||||||
default: //some known command
|
default: //some known command
|
||||||
{
|
{
|
||||||
int32_t intParam = getIntFromStr((char **) &payload);
|
int32_t intParam = getIntFromStr((char **) &payload);
|
||||||
if (intParam) st.Int(intParam);
|
if (intParam) st.Int(intParam);
|
||||||
if (remoteID) return remoteCtrl(st,remoteID,NULL,authToken);
|
if (remoteID) return remoteCtrl(st,remoteID,NULL,authToken);
|
||||||
return Ctrl(st,NULL, true, authorized);
|
return Ctrl(st,NULL, 0, authorized);
|
||||||
}
|
}
|
||||||
} //ctrl
|
} //ctrl
|
||||||
return 0;
|
return 0;
|
||||||
@@ -865,7 +877,7 @@ int Item::remoteCtrl(itemCmd cmd, int remoteID, char* subItem, char * authToken)
|
|||||||
// Recursive function with small stack consumption
|
// Recursive function with small stack consumption
|
||||||
// if cmd defined - execute Ctrl for any group members recursively
|
// if cmd defined - execute Ctrl for any group members recursively
|
||||||
// else performs Activity check for group members and return true if any member is active
|
// else performs Activity check for group members and return true if any member is active
|
||||||
bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized)
|
bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized, uint8_t ctrlFlags)
|
||||||
{ if (!itemArr || itemArr->type!=aJson_Array) return false;
|
{ if (!itemArr || itemArr->type!=aJson_Array) return false;
|
||||||
// Iterate across array of names
|
// Iterate across array of names
|
||||||
aJsonObject *i = itemArr->child;
|
aJsonObject *i = itemArr->child;
|
||||||
@@ -879,14 +891,12 @@ bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool aut
|
|||||||
if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item
|
if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item
|
||||||
{
|
{
|
||||||
Item it(nextItem);
|
Item it(nextItem);
|
||||||
if (cmd && it.isValid()) it.Ctrl(*cmd,subItem,false,authorized); //Execute (non recursive)
|
if (cmd && it.isValid() ) it.Ctrl(*cmd,subItem,CTRL_DISABLE_RECURSION | ctrlFlags, authorized); //Execute (non recursive)
|
||||||
//Retrieve itemType
|
//Retrieve itemType
|
||||||
//aJsonObject * itemtype = aJson.getArrayItem(nextItem,0);
|
|
||||||
//if (itemtype && itemtype->type == aJson_Int && itemtype->valueint == CH_GROUP)
|
|
||||||
if (it.itemType == CH_GROUP)
|
if (it.itemType == CH_GROUP)
|
||||||
{ //is Group
|
{ //is Group
|
||||||
aJsonObject * itemSubArray = aJson.getArrayItem(nextItem,1);
|
aJsonObject * itemSubArray = aJson.getArrayItem(nextItem,1);
|
||||||
short res = digGroup(itemSubArray,cmd,subItem,authorized);
|
short res = digGroup(itemSubArray,cmd,subItem,authorized, ctrlFlags);
|
||||||
if (!cmd && res)
|
if (!cmd && res)
|
||||||
{
|
{
|
||||||
configLocked--;
|
configLocked--;
|
||||||
@@ -899,8 +909,8 @@ bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool aut
|
|||||||
configLocked--;
|
configLocked--;
|
||||||
return true; //Not execution, just activity check. If any channel is active - return true
|
return true; //Not execution, just activity check. If any channel is active - return true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case aJson_Object:
|
case aJson_Object:
|
||||||
case aJson_Array:
|
case aJson_Array:
|
||||||
@@ -923,25 +933,25 @@ aJsonObject *timestampObj = aJson.getArrayItem(itemArr, I_TIMESTAMP);
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Item::scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized)
|
int Item::scheduleOppositeCommand(itemCmd cmd,short isActiveNow,bool authorized)
|
||||||
{
|
{
|
||||||
itemCmd nextCmd=cmd;
|
itemCmd nextCmd=cmd;
|
||||||
|
|
||||||
switch (cmd.getCmd()){
|
switch (cmd.getCmd()){
|
||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
if (isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 1) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_XOFF);
|
nextCmd.Cmd(CMD_XOFF);
|
||||||
break;
|
break;
|
||||||
case CMD_XOFF:
|
case CMD_XOFF:
|
||||||
if (!isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 0) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_XON);
|
nextCmd.Cmd(CMD_XON);
|
||||||
break;
|
break;
|
||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
if (isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 1) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_OFF);
|
nextCmd.Cmd(CMD_OFF);
|
||||||
break;
|
break;
|
||||||
case CMD_OFF:
|
case CMD_OFF:
|
||||||
if (!isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 0) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_ON);
|
nextCmd.Cmd(CMD_ON);
|
||||||
break;
|
break;
|
||||||
case CMD_ENABLE:
|
case CMD_ENABLE:
|
||||||
@@ -953,19 +963,19 @@ int Item::scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized)
|
|||||||
nextCmd.Cmd(CMD_ENABLE);
|
nextCmd.Cmd(CMD_ENABLE);
|
||||||
break;
|
break;
|
||||||
case CMD_FREEZE:
|
case CMD_FREEZE:
|
||||||
if (getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
|
if ((getFlag(FLAG_FREEZED) == FLAG_FREEZED) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_UNFREEZE);
|
nextCmd.Cmd(CMD_UNFREEZE);
|
||||||
break;
|
break;
|
||||||
case CMD_UNFREEZE:
|
case CMD_UNFREEZE:
|
||||||
if (!getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
|
if (!(getFlag(FLAG_FREEZED) == FLAG_FREEZED) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_FREEZE);
|
nextCmd.Cmd(CMD_FREEZE);
|
||||||
break;
|
break;
|
||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
if (!isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 0) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_RESTORE);
|
nextCmd.Cmd(CMD_RESTORE);
|
||||||
break;
|
break;
|
||||||
case CMD_RESTORE:
|
case CMD_RESTORE:
|
||||||
if (isActiveNow && !isScheduled()) return 0;
|
if ((isActiveNow == 1) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_HALT);
|
nextCmd.Cmd(CMD_HALT);
|
||||||
break;
|
break;
|
||||||
case CMD_TOGGLE: nextCmd.Cmd(CMD_TOGGLE);
|
case CMD_TOGGLE: nextCmd.Cmd(CMD_TOGGLE);
|
||||||
@@ -994,12 +1004,12 @@ int Item::scheduleCommand(itemCmd cmd,bool authorized)
|
|||||||
timestampObj->type = (authorized?aJson_Reserved:aJson_Int);
|
timestampObj->type = (authorized?aJson_Reserved:aJson_Int);
|
||||||
timestampObj->subtype=(cmd.getCmd() & 0xF);
|
timestampObj->subtype=(cmd.getCmd() & 0xF);
|
||||||
|
|
||||||
debugSerial<<F( "Armed for ")<< cmd.getInt() << F(" ms :")<<timestampObj->valueint<<endl;
|
debugSerial<<F( "CTRL: Armed ")<<itemArr->name <<F(" for ")<< cmd.getInt() << F(" ms")<<endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timestampObj->subtype=0;
|
timestampObj->subtype=0;
|
||||||
debugSerial<<F( " Disarmed")<<endl;
|
debugSerial<<F( "CTRL: ")<<itemArr->name << F( " Disarmed")<<endl;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1014,7 +1024,8 @@ int Item::scheduleCommand(itemCmd cmd,bool authorized)
|
|||||||
// -1 system error
|
// -1 system error
|
||||||
// -4 invalid argument
|
// -4 invalid argument
|
||||||
// -5 unauthorized
|
// -5 unauthorized
|
||||||
int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized)
|
// -6 disabled
|
||||||
|
int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized)
|
||||||
{
|
{
|
||||||
int fr = freeRam();
|
int fr = freeRam();
|
||||||
if (fr < minimalMemory)
|
if (fr < minimalMemory)
|
||||||
@@ -1050,6 +1061,33 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
//debugSerial<<endl;
|
//debugSerial<<endl;
|
||||||
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
|
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
|
||||||
if (!itemArr) return -1;
|
if (!itemArr) return -1;
|
||||||
|
|
||||||
|
bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
||||||
|
if (!suffixCode && cmd.isCommand() && cmd.getCmd()!=CMD_UP && cmd.getCmd()!=CMD_DN) suffixCode=S_CMD;
|
||||||
|
|
||||||
|
switch (suffixCode)
|
||||||
|
{
|
||||||
|
case S_CMD:
|
||||||
|
case S_CTRL:
|
||||||
|
case S_DELAYED:
|
||||||
|
if (cmd.isCommand() && getFlag(FLAG_LOCKED_CMD) && cmd.getCmd()!=CMD_UNFREEZE)
|
||||||
|
{
|
||||||
|
errorSerial<<F("CTRL: channel frozen")<<endl;
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_VAL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (cmd.isValue() && getFlag(FLAG_LOCKED_SET))
|
||||||
|
{
|
||||||
|
errorSerial<<F("CTRL: channel frozen")<<endl;
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// DELAYED COMMANDS processing
|
/// DELAYED COMMANDS processing
|
||||||
if (suffixCode == S_DELAYED)
|
if (suffixCode == S_DELAYED)
|
||||||
@@ -1057,15 +1095,24 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
return scheduleCommand(cmd,authorized);
|
return scheduleCommand(cmd,authorized);
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
|
|
||||||
|
if (((flags & CTRL_SCHEDULED_CALL_RECURSION) == CTRL_SCHEDULED_CALL_RECURSION && itemType == CH_GROUP))
|
||||||
|
// if (((flags & CTRL_SCHEDULED_CALL_RECURSION) == CTRL_SCHEDULED_CALL_RECURSION && itemType != CH_GROUP))
|
||||||
|
{
|
||||||
|
debugSerial<<F("Skipping scheduled group exec")<<endl;
|
||||||
|
return -7;
|
||||||
|
}
|
||||||
|
///
|
||||||
int8_t chActive = -1;
|
int8_t chActive = -1;
|
||||||
bool toExecute = false;
|
bool toExecute = false;
|
||||||
bool scale100 = false;
|
bool scale100 = false;
|
||||||
bool invalidArgument = false;
|
bool invalidArgument = false;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
uint16_t status2Send = 0;
|
long status2Send = 0;
|
||||||
uint8_t command2Set = 0;
|
uint8_t command2Set = 0;
|
||||||
itemCmd originalCmd = cmd;
|
itemCmd originalCmd = cmd;
|
||||||
|
int subitemCmd = subitem2cmd(subItem);
|
||||||
|
//bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
||||||
/// Common (GRP & NO GRP) commands
|
/// Common (GRP & NO GRP) commands
|
||||||
switch (cmd.getCmd())
|
switch (cmd.getCmd())
|
||||||
{
|
{
|
||||||
@@ -1080,7 +1127,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
toExecute=true;
|
toExecute=true;
|
||||||
scale100=true; //openHab topic format
|
scale100=true; //openHab topic format
|
||||||
chActive=(isActive()>0);
|
chActive=(isActive()>0);
|
||||||
debugSerial<<chActive<<" "<<cmd.getInt()<<endl;
|
// debugSerial<<chActive<<" "<<cmd.getInt()<<endl;
|
||||||
if (chActive>0 && !cmd.getInt()) {cmd.Cmd(CMD_OFF);status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;}
|
if (chActive>0 && !cmd.getInt()) {cmd.Cmd(CMD_OFF);status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;}
|
||||||
if (chActive==0 && cmd.getInt()) {cmd.Cmd(CMD_ON);status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;}
|
if (chActive==0 && cmd.getInt()) {cmd.Cmd(CMD_ON);status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;}
|
||||||
|
|
||||||
@@ -1096,6 +1143,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
|
|
||||||
//Convert value to most approptiate type for channel
|
//Convert value to most approptiate type for channel
|
||||||
stored.assignFrom(cmd,getChanType());
|
stored.assignFrom(cmd,getChanType());
|
||||||
|
//stored.cmd.cmdCode=0; ///////
|
||||||
stored.debugOut();
|
stored.debugOut();
|
||||||
|
|
||||||
if ((scale100 || SCALE_VOLUME_100) && (cmd.getArgType()==ST_HSV255 || cmd.getArgType()==ST_PERCENTS255 || cmd.getArgType()==ST_INT32 || cmd.getArgType()==ST_UINT32))
|
if ((scale100 || SCALE_VOLUME_100) && (cmd.getArgType()==ST_HSV255 || cmd.getArgType()==ST_PERCENTS255 || cmd.getArgType()==ST_INT32 || cmd.getArgType()==ST_UINT32))
|
||||||
@@ -1174,6 +1222,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
switch (suffixCode)
|
switch (suffixCode)
|
||||||
{
|
{
|
||||||
case S_NOTFOUND:
|
case S_NOTFOUND:
|
||||||
|
// case S_CMD:
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
case S_SET:
|
case S_SET:
|
||||||
{
|
{
|
||||||
@@ -1181,6 +1230,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
//if (limit && suffixCode==S_NOTFOUND) limit = 100;
|
//if (limit && suffixCode==S_NOTFOUND) limit = 100;
|
||||||
if (cmd.incrementPercents(step,limit))
|
if (cmd.incrementPercents(step,limit))
|
||||||
{
|
{
|
||||||
|
debugSerial<<"INCREASED: ";
|
||||||
|
cmd.debugOut();
|
||||||
status2Send |= FLAG_PARAMETERS | FLAG_SEND_DEFFERED;
|
status2Send |= FLAG_PARAMETERS | FLAG_SEND_DEFFERED;
|
||||||
} else {cmd=fallbackCmd;invalidArgument=true;}
|
} else {cmd=fallbackCmd;invalidArgument=true;}
|
||||||
}
|
}
|
||||||
@@ -1199,6 +1250,13 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
status2Send |= FLAG_PARAMETERS | FLAG_SEND_DEFFERED;
|
status2Send |= FLAG_PARAMETERS | FLAG_SEND_DEFFERED;
|
||||||
cmd.setSuffix(S_SET);
|
cmd.setSuffix(S_SET);
|
||||||
} else {cmd=fallbackCmd;invalidArgument=true; errorSerial << F("Invalid arg")<<endl;}
|
} else {cmd=fallbackCmd;invalidArgument=true; errorSerial << F("Invalid arg")<<endl;}
|
||||||
|
break;
|
||||||
|
case S_TEMP:
|
||||||
|
if (cmd.incrementTemp(step))
|
||||||
|
{
|
||||||
|
status2Send |= FLAG_PARAMETERS | FLAG_SEND_DEFFERED;
|
||||||
|
cmd.setSuffix(S_SET);
|
||||||
|
} else {cmd=fallbackCmd;invalidArgument=true; errorSerial << F("Invalid arg")<<endl;}
|
||||||
} //switch suffix
|
} //switch suffix
|
||||||
|
|
||||||
} //Case UP/DOWN
|
} //Case UP/DOWN
|
||||||
@@ -1213,19 +1271,50 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
errorSerial<<F("CTRL: Not enough memory for group operation")<<endl;
|
errorSerial<<F("CTRL: Not enough memory for group operation")<<endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (allowRecursion && itemArg->type == aJson_Array && operation)
|
if (!(flags & CTRL_DISABLE_RECURSION) && itemArg->type == aJson_Array && operation)
|
||||||
{
|
{
|
||||||
chActive=(isActive()>0);
|
if ((suffixCode==S_CMD) && ((cmd.getCmd() == CMD_ENABLE) || (cmd.getCmd() == CMD_DISABLE)))
|
||||||
digGroup(itemArg,&cmd,subItem,authorized);
|
{
|
||||||
|
debugSerial<<F("CTRL: command just for ")<<itemArr->name<<endl;
|
||||||
if ((suffixCode==S_CMD) && cmd.isValue())
|
|
||||||
{
|
switch (cmd.getCmd())
|
||||||
scheduleOppositeCommand(originalCmd,chActive,authorized);
|
{
|
||||||
scheduledOppositeCommand = true;
|
case CMD_ENABLE:
|
||||||
}
|
clearFlag(FLAG_DISABLED);
|
||||||
|
setCmd(CMD_ENABLE);
|
||||||
|
break;
|
||||||
|
case CMD_DISABLE:
|
||||||
|
if (!authorized)
|
||||||
|
{
|
||||||
|
errorSerial<<F("Disarming not authorized")<<endl;
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
setFlag(FLAG_DISABLED);
|
||||||
|
setCmd(CMD_DISABLE);
|
||||||
|
}
|
||||||
|
status2Send = FLAG_FLAGS;
|
||||||
|
if (operation) SendStatus(status2Send);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (chActive == -1) chActive=(isActive()>0); //need! because activities status will be changed
|
||||||
|
if ((suffixCode!=S_CMD) || (cmd.getCmd() != CMD_XON) || !getFlag(FLAG_DISABLED))
|
||||||
|
{
|
||||||
|
digGroup(itemArg,&cmd,subItem,authorized,flags);
|
||||||
|
|
||||||
|
if (oppositeCommandToBeSchedulled)//((suffixCode==S_CMD) && cmd.isValue())
|
||||||
|
{
|
||||||
|
scheduleOppositeCommand(originalCmd,-1,authorized);
|
||||||
|
scheduledOppositeCommand = true;
|
||||||
|
}
|
||||||
|
if (subItem && !subitemCmd) status2Send |= FLAG_SEND_IMMEDIATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res=1;
|
res=1;
|
||||||
|
if (subitemCmd) subItem = NULL;
|
||||||
|
|
||||||
// Post-processing of group command - converting HALT,REST,XON,XOFF to conventional ON/OFF for status
|
// Post-processing of group command - converting HALT,REST,XON,XOFF to conventional ON/OFF for status
|
||||||
switch (cmd.getCmd()) {
|
switch (cmd.getCmd()) {
|
||||||
@@ -1233,7 +1322,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_RESTORE: // individual for group members
|
case CMD_RESTORE: // individual for group members
|
||||||
switch (t = getCmd()) {
|
switch (t = getCmd()) {
|
||||||
case CMD_HALT: //previous command was HALT ?
|
case CMD_HALT: //previous command was HALT ?
|
||||||
///if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
|
|
||||||
debugSerial << F("CTRL: Restored from:") << t << endl;
|
debugSerial << F("CTRL: Restored from:") << t << endl;
|
||||||
cmd.loadItemDef(this);
|
cmd.loadItemDef(this);
|
||||||
cmd.Cmd(CMD_ON); //turning on
|
cmd.Cmd(CMD_ON); //turning on
|
||||||
@@ -1247,7 +1335,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_XOFF: // individual for group members
|
case CMD_XOFF: // individual for group members
|
||||||
switch (t = getCmd()) {
|
switch (t = getCmd()) {
|
||||||
case CMD_XON: //previous command was CMD_XON ?
|
case CMD_XON: //previous command was CMD_XON ?
|
||||||
///if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
|
|
||||||
debugSerial << F("CTRL: Turned off from:") << t << endl;
|
debugSerial << F("CTRL: Turned off from:") << t << endl;
|
||||||
cmd.Cmd(CMD_OFF); //turning Off
|
cmd.Cmd(CMD_OFF); //turning Off
|
||||||
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
|
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
|
||||||
@@ -1263,14 +1350,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
if (!getFlag(FLAG_DISABLED))
|
if (!getFlag(FLAG_DISABLED))
|
||||||
{
|
{
|
||||||
if (chActive == -1) chActive=(isActive()>0);
|
if (chActive == -1) chActive=(isActive()>0);
|
||||||
|
|
||||||
///if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
|
|
||||||
|
|
||||||
|
|
||||||
if (!chActive) //if channel was'nt active before CMD_XON
|
if (!chActive) //if channel was'nt active before CMD_XON
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
cmd.loadItemDef(this);
|
cmd.loadItemDef(this);
|
||||||
cmd.Cmd(CMD_ON);
|
cmd.Cmd(CMD_ON);
|
||||||
command2Set=CMD_XON;
|
command2Set=CMD_XON;
|
||||||
@@ -1291,7 +1372,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
break;
|
break;
|
||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
if (chActive == -1) chActive=(isActive()>0);
|
if (chActive == -1) chActive=(isActive()>0);
|
||||||
///if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
|
|
||||||
if (chActive) //if channel was active before CMD_HALT /// HERE bug - if cmd == On but 0 = active
|
if (chActive) //if channel was active before CMD_HALT /// HERE bug - if cmd == On but 0 = active
|
||||||
{
|
{
|
||||||
cmd.Cmd(CMD_OFF);
|
cmd.Cmd(CMD_OFF);
|
||||||
@@ -1324,7 +1405,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
if (subItem)
|
if (subItem)
|
||||||
{
|
{
|
||||||
//Check if subitem is some sort of command
|
//Check if subitem is some sort of command
|
||||||
int subitemCmd = subitem2cmd(subItem);
|
|
||||||
short prevCmd = getCmd();
|
short prevCmd = getCmd();
|
||||||
if (!prevCmd && chActive) prevCmd=CMD_ON;
|
if (!prevCmd && chActive) prevCmd=CMD_ON;
|
||||||
|
|
||||||
@@ -1343,7 +1424,10 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
///// return 0;
|
///// return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue();
|
|
||||||
|
/// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue();
|
||||||
|
|
||||||
|
// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
||||||
// Commands for NON GROUP
|
// Commands for NON GROUP
|
||||||
//threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values
|
//threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values
|
||||||
switch (cmd.getCmd()) {
|
switch (cmd.getCmd()) {
|
||||||
@@ -1351,9 +1435,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_RESTORE: // individual for group members
|
case CMD_RESTORE: // individual for group members
|
||||||
switch (t = getCmd()) {
|
switch (t = getCmd()) {
|
||||||
case CMD_HALT: //previous command was HALT ?
|
case CMD_HALT: //previous command was HALT ?
|
||||||
// if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
|
|
||||||
debugSerial << F("CTRL: Restored from:") << t << endl;
|
debugSerial << F("CTRL: Restored from:") << t << endl;
|
||||||
cmd.loadItemDef(this);
|
cmd.loadItemDef(this);
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
@@ -1369,8 +1450,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_XOFF: // individual for group members
|
case CMD_XOFF: // individual for group members
|
||||||
switch (t = getCmd()) {
|
switch (t = getCmd()) {
|
||||||
case CMD_XON: //previous command was CMD_XON ?
|
case CMD_XON: //previous command was CMD_XON ?
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
debugSerial << F("CTRL: Turned off from:") << t << endl;
|
debugSerial << F("CTRL: Turned off from:") << t << endl;
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
cmd.Cmd(CMD_OFF); //turning Off
|
cmd.Cmd(CMD_OFF); //turning Off
|
||||||
@@ -1386,9 +1465,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
if (!getFlag(FLAG_DISABLED))
|
if (!getFlag(FLAG_DISABLED))
|
||||||
{
|
{
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
|
|
||||||
if (!chActive) //if channel was'nt active before CMD_XON
|
if (!chActive) //if channel was'nt active before CMD_XON
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1413,8 +1489,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
if (chActive) //if channel was active before CMD_HALT
|
if (chActive) //if channel was active before CMD_HALT
|
||||||
{
|
{
|
||||||
cmd.Cmd(CMD_OFF);
|
cmd.Cmd(CMD_OFF);
|
||||||
@@ -1437,18 +1511,11 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getCmd() == CMD_HALT) return 3; //Halted, ignore OFF
|
if (getCmd() == CMD_HALT) return 3; //Halted, ignore OFF
|
||||||
|
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
|
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
|
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
|
|
||||||
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
|
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
|
||||||
{
|
{
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
@@ -1458,7 +1525,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
{
|
{
|
||||||
debugSerial<<F("CTRL: ON:Already Active\n");
|
debugSerial<<F("CTRL: ON:Already Active\n");
|
||||||
setCmd(CMD_ON);
|
setCmd(CMD_ON);
|
||||||
SendStatus(FLAG_COMMAND | FLAG_SEND_DEFFERED);
|
SendStatus(FLAG_COMMAND | FLAG_SEND_DEFFERED,subItem);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,6 +1535,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
case CMD_FAN:
|
case CMD_FAN:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
|
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
|
||||||
{
|
{
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
@@ -1485,30 +1553,16 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_ENABLE:
|
case CMD_ENABLE:
|
||||||
|
case CMD_DISABLE:
|
||||||
//clearFlag(FLAG_DISABLED); //saveItem have this
|
//clearFlag(FLAG_DISABLED); //saveItem have this
|
||||||
status2Send |= FLAG_FLAGS;
|
status2Send |= FLAG_FLAGS;
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
|
|
||||||
//if (allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_DISABLE:
|
|
||||||
//setFlag(FLAG_DISABLED); //saveItem have this
|
|
||||||
status2Send |= FLAG_FLAGS;
|
|
||||||
toExecute=true;
|
|
||||||
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
|
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_UNFREEZE:
|
case CMD_UNFREEZE:
|
||||||
//clearFlag(FLAG_DISABLED); //saveItem have this
|
//clearFlag(FLAG_DISABLED); //saveItem have this
|
||||||
status2Send = FLAG_FLAGS;
|
status2Send = FLAG_FLAGS;
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
|
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_FREEZE:
|
case CMD_FREEZE:
|
||||||
@@ -1516,9 +1570,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
status2Send = FLAG_FLAGS;
|
status2Send = FLAG_FLAGS;
|
||||||
command2Set = 0;
|
command2Set = 0;
|
||||||
toExecute=true;
|
toExecute=true;
|
||||||
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
|
|
||||||
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
|
|
||||||
// scheduleOppositeCommand(cmd,chActive,authorized);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1535,13 +1586,21 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
} // NO GROUP
|
} // NO GROUP
|
||||||
if (invalidArgument) return -4;
|
if (invalidArgument) return -4;
|
||||||
|
|
||||||
if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
if ((!driver || driver->isAllowed(cmd))
|
||||||
|
// && (
|
||||||
|
// //!getFlag(FLAG_FREEZED)
|
||||||
|
// (suffixCode == S_VAL)
|
||||||
|
// || (cmd.isCommand() && !getFlag(FLAG_LOCKED_CMD))
|
||||||
|
// || (cmd.isValue() && !getFlag(FLAG_LOCKED_SET))
|
||||||
|
// )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (driver) //New style modular code
|
if (driver) //New style modular code
|
||||||
{
|
{
|
||||||
// UPDATE internal variables
|
// UPDATE internal variables
|
||||||
if (status2Send) cmd.saveItem(this,status2Send);
|
if (status2Send) cmd.saveItem(this,status2Send);
|
||||||
|
else debugSerial<<"NOT SAVED"<<endl;
|
||||||
|
|
||||||
res = driver->Ctrl(cmd, subItem, toExecute,authorized);
|
res = driver->Ctrl(cmd, subItem, toExecute,authorized);
|
||||||
if (driver->getChanType() == CH_THERMO) status2Send |= FLAG_SEND_IMMEDIATE;
|
if (driver->getChanType() == CH_THERMO) status2Send |= FLAG_SEND_IMMEDIATE;
|
||||||
@@ -1579,6 +1638,7 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
|||||||
|
|
||||||
switch (icmd){
|
switch (icmd){
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
case CMD_COOL:
|
case CMD_COOL:
|
||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
@@ -1590,6 +1650,9 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
|||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
case CMD_XOFF:
|
case CMD_XOFF:
|
||||||
digitalWrite(iaddr, k = (inverse) ? HIGH : LOW);
|
digitalWrite(iaddr, k = (inverse) ? HIGH : LOW);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
k = -1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if (inverse)
|
if (inverse)
|
||||||
@@ -1620,13 +1683,13 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
|||||||
tStore.asint=getExt();
|
tStore.asint=getExt();
|
||||||
if (!tStore.timestamp16)
|
if (!tStore.timestamp16)
|
||||||
{
|
{
|
||||||
infoSerial<<F("Cleaning alarm ")<<itemArr->name<<endl;
|
infoSerial<<F("Cleaning alarm ")<<itemArr->name<<" Ext:"<<tStore.asint<<endl;
|
||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
mqttClient.publish("/alarmoff/snsr", itemArr->name);
|
mqttClient.publish("/alarmoff/snsr", itemArr->name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
tStore.tempX100=cmd.getFloat()*100.; //Save measurement
|
tStore.tempX100=cmd.getFloat()*100.; //Save measurement
|
||||||
tStore.timestamp16=millisNZ(8) & 0xFFFF; //And timestamp
|
tStore.timestamp16=millisNZ(8,0xFFFFU); //And timestamp
|
||||||
debugSerial<<F("THERM:")<<itemArr->name<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl;
|
debugSerial<<F("THERM:")<<itemArr->name<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl;
|
||||||
setExt(tStore.asint);
|
setExt(tStore.asint);
|
||||||
res=1;
|
res=1;
|
||||||
@@ -1680,11 +1743,18 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
|||||||
|
|
||||||
//update command for HALT & XON and send MQTT status
|
//update command for HALT & XON and send MQTT status
|
||||||
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
|
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
|
||||||
if (operation) SendStatus(status2Send);
|
if (operation) {
|
||||||
|
SendStatus(status2Send);//,subItem);
|
||||||
|
if (oppositeCommandToBeSchedulled && subItem)
|
||||||
|
{
|
||||||
|
debugSerial<<F("CTRL: momentary event")<<endl;
|
||||||
|
SendStatusImmediate(originalCmd,status2Send,subItem,false); //XON -> OFF scheduled
|
||||||
|
}
|
||||||
|
}
|
||||||
} //alowed cmd
|
} //alowed cmd
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorSerial<<F("CTRL: Command blocked by driver or channel frozen")<<endl;
|
errorSerial<<F("CTRL: Command blocked by driver")<<endl;
|
||||||
if ((status2Send & FLAG_FLAGS) && operation)
|
if ((status2Send & FLAG_FLAGS) && operation)
|
||||||
{
|
{
|
||||||
cmd.saveItem(this,FLAG_FLAGS);
|
cmd.saveItem(this,FLAG_FLAGS);
|
||||||
@@ -1713,7 +1783,6 @@ int Item::isActive() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int cmd = getCmd();
|
int cmd = getCmd();
|
||||||
|
|
||||||
if (driver) {
|
if (driver) {
|
||||||
short active = driver->isActive();
|
short active = driver->isActive();
|
||||||
if (active >= 0)
|
if (active >= 0)
|
||||||
@@ -1730,6 +1799,8 @@ int Item::isActive() {
|
|||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
|
case CMD_DRY:
|
||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
case CMD_COOL:
|
case CMD_COOL:
|
||||||
printActiveStatus(true);
|
printActiveStatus(true);
|
||||||
@@ -1811,7 +1882,7 @@ if (timestampObj)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
timestampObj->subtype=0;
|
timestampObj->subtype=0;
|
||||||
Ctrl(itemCmd(ST_VOID,cmd),NULL,true,authorized);
|
Ctrl(itemCmd(ST_VOID,cmd),NULL,CTRL_DISABLE_NON_GRP,authorized);
|
||||||
//timestampObj->subtype=0; ////
|
//timestampObj->subtype=0; ////
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1838,7 +1909,6 @@ switch (cause)
|
|||||||
sendDelayedStatus();
|
sendDelayedStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver && driver->Status())
|
if (driver && driver->Status())
|
||||||
{
|
{
|
||||||
return driver->Poll(cause);
|
return driver->Poll(cause);
|
||||||
@@ -1858,7 +1928,7 @@ void Item::sendDelayedStatus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Item::SendStatus(int sendFlags) {
|
int Item::SendStatus(long sendFlags, char * subItem) {
|
||||||
if (sendFlags & FLAG_SEND_IMMEDIATE) sendFlags &= ~ (FLAG_SEND_IMMEDIATE | FLAG_SEND_DEFFERED);
|
if (sendFlags & FLAG_SEND_IMMEDIATE) sendFlags &= ~ (FLAG_SEND_IMMEDIATE | FLAG_SEND_DEFFERED);
|
||||||
if ((sendFlags & FLAG_SEND_DEFFERED) || freeRam()<150 || (!isNotRetainingStatus() )) {
|
if ((sendFlags & FLAG_SEND_DEFFERED) || freeRam()<150 || (!isNotRetainingStatus() )) {
|
||||||
setFlag(sendFlags & (FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS));
|
setFlag(sendFlags & (FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS));
|
||||||
@@ -1870,17 +1940,17 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
itemCmd st(ST_VOID,CMD_VOID);
|
itemCmd st(ST_VOID,CMD_VOID);
|
||||||
st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
|
st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
|
||||||
sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS); //if some delayed status is pending
|
sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS); //if some delayed status is pending
|
||||||
return SendStatusImmediate(st,sendFlags);
|
return SendStatusImmediate(st,sendFlags,subItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Item::SendStatusImmediate(itemCmd st, int sendFlags, char * subItem) {
|
int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem, bool retain) {
|
||||||
{
|
{
|
||||||
char addrstr[64];
|
char addrstr[64];
|
||||||
char valstr[20] = "";
|
char valstr[20] = "";
|
||||||
char cmdstr[9] = "";
|
char cmdstr[16] = "";
|
||||||
|
|
||||||
debugSerial<<"SENDSTATUS: "<<subItem;
|
debugSerial<<"SENDSTATUS: "<<subItem<<" ";
|
||||||
st.debugOut();
|
st.debugOut();
|
||||||
|
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
@@ -1895,6 +1965,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
case CMD_COOL:
|
case CMD_COOL:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
@@ -1936,12 +2007,12 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
(st.getArgType() == ST_PERCENTS255 || st.getArgType() == ST_HSV255 || st.getArgType() == ST_FLOAT_CELSIUS))
|
(st.getArgType() == ST_PERCENTS255 || st.getArgType() == ST_HSV255 || st.getArgType() == ST_FLOAT_CELSIUS))
|
||||||
{
|
{
|
||||||
st.toString(valstr, sizeof(valstr), FLAG_PARAMETERS,true);
|
st.toString(valstr, sizeof(valstr), FLAG_PARAMETERS,true);
|
||||||
mqttClient.publish(addrstr, valstr, true);
|
mqttClient.publish(addrstr, valstr, retain);
|
||||||
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
|
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
|
||||||
}
|
}
|
||||||
else if ((sendFlags & FLAG_COMMAND) && (strlen(cmdstr)))
|
else if ((sendFlags & FLAG_COMMAND) && (strlen(cmdstr)))
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr, true);
|
mqttClient.publish(addrstr, cmdstr, retain);
|
||||||
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
|
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1977,7 +2048,15 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
|
|
||||||
if (sendFlags & FLAG_SEND_DELAYED)
|
if (sendFlags & FLAG_SEND_DELAYED)
|
||||||
strncat_P(addrstr, suffix_P[S_DELAYED], sizeof(addrstr)-1);
|
strncat_P(addrstr, suffix_P[S_DELAYED], sizeof(addrstr)-1);
|
||||||
else strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
|
else
|
||||||
|
switch (st.getSuffix())
|
||||||
|
{
|
||||||
|
case S_FAN:
|
||||||
|
strncat_P(addrstr, suffix_P[S_FAN], sizeof(addrstr)-1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Preparing parameters payload //////////
|
// Preparing parameters payload //////////
|
||||||
@@ -1999,7 +2078,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, valstr,true);
|
mqttClient.publish(addrstr, valstr,retain);
|
||||||
clearFlag(FLAG_PARAMETERS);
|
clearFlag(FLAG_PARAMETERS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2013,11 +2092,15 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
|
|
||||||
if (sendFlags & FLAG_COMMAND)
|
if (sendFlags & FLAG_COMMAND)
|
||||||
{
|
{
|
||||||
|
if (!subItem)
|
||||||
// Some additional preparing for extended set of commands:
|
// Some additional preparing for extended set of commands:
|
||||||
switch (st.getCmd()) {
|
switch (st.getCmd()) {
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
strcpy_P(cmdstr, AUTO_P);
|
strcpy_P(cmdstr, AUTO_P);
|
||||||
break;
|
break;
|
||||||
|
case CMD_HEATCOOL:
|
||||||
|
strcpy_P(cmdstr, HEATCOOL_P);
|
||||||
|
break;
|
||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
strcpy_P(cmdstr, HEAT_P);
|
strcpy_P(cmdstr, HEAT_P);
|
||||||
break;
|
break;
|
||||||
@@ -2040,6 +2123,8 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P);
|
if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P);
|
||||||
}
|
}
|
||||||
|
else //for subItems - transpatent print
|
||||||
|
st.toString(cmdstr,sizeof(cmdstr),FLAG_COMMAND | FLAG_PARAMETERS);
|
||||||
|
|
||||||
setTopic(addrstr,sizeof(addrstr),T_OUT);
|
setTopic(addrstr,sizeof(addrstr),T_OUT);
|
||||||
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);
|
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);
|
||||||
@@ -2056,7 +2141,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr,true);
|
mqttClient.publish(addrstr, cmdstr,retain);
|
||||||
clearFlag(FLAG_COMMAND);
|
clearFlag(FLAG_COMMAND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2072,7 +2157,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
if (getFlag(FLAG_DISABLED))
|
if (getFlag(FLAG_DISABLED))
|
||||||
strcpy_P(cmdstr, DISABLE_P);
|
strcpy_P(cmdstr, DISABLE_P);
|
||||||
|
|
||||||
else if (getFlag(FLAG_FREEZED))
|
else if (getFlag(FLAG_FREEZED) == FLAG_FREEZED)
|
||||||
strcpy_P(cmdstr, FREEZE_P);
|
strcpy_P(cmdstr, FREEZE_P);
|
||||||
|
|
||||||
else strcpy_P(cmdstr, ENABLE_P);
|
else strcpy_P(cmdstr, ENABLE_P);
|
||||||
@@ -2096,7 +2181,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr,true);
|
mqttClient.publish(addrstr, cmdstr,retain);
|
||||||
clearFlag(FLAG_FLAGS);
|
clearFlag(FLAG_FLAGS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2111,7 +2196,7 @@ int Item::SendStatus(int sendFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Item::getChanType()
|
int Item::getChanType()
|
||||||
{
|
{
|
||||||
if (driver) return driver->getChanType();
|
if (driver) return driver->getChanType();
|
||||||
return itemType;
|
return itemType;
|
||||||
}
|
}
|
||||||
@@ -2143,7 +2228,6 @@ int Item::checkRetry() {
|
|||||||
{ // if last sending attempt of command was failed
|
{ // if last sending attempt of command was failed
|
||||||
itemCmd val(ST_VOID,CMD_VOID);
|
itemCmd val(ST_VOID,CMD_VOID);
|
||||||
val.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
|
val.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
|
||||||
|
|
||||||
if (driver)
|
if (driver)
|
||||||
{
|
{
|
||||||
clearFlag(FLAG_SEND_RETRY); // Clean retry flag
|
clearFlag(FLAG_SEND_RETRY); // Clean retry flag
|
||||||
@@ -2646,5 +2730,158 @@ int Item::checkModbusDimmer(int data) {
|
|||||||
} //if data changed
|
} //if data changed
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Item * driverFactory::getItem(Item * item)
|
||||||
|
{
|
||||||
|
abstractOut * driver = findDriver(item);
|
||||||
|
if (driver) return driver->getItem();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstractOut * driverFactory::findDriver(Item * item)
|
||||||
|
{
|
||||||
|
if (!item || !item->isValid()) return NULL;
|
||||||
|
uint8_t itemType = item->itemType;
|
||||||
|
if (itemType>CH_MAX) return NULL;
|
||||||
|
|
||||||
|
switch (itemType)
|
||||||
|
{
|
||||||
|
case CH_RGBW:
|
||||||
|
case CH_RGB:
|
||||||
|
case CH_RGBWW:
|
||||||
|
itemType = CH_DIMMER;
|
||||||
|
}
|
||||||
|
return drivers[itemType];
|
||||||
|
}
|
||||||
|
|
||||||
|
void driverFactory::freeDriver(Item * item)
|
||||||
|
{
|
||||||
|
if (item && item->driver)
|
||||||
|
{
|
||||||
|
abstractOut * driver = findDriver(item);
|
||||||
|
if (driver)
|
||||||
|
{
|
||||||
|
if (driver->getItem() == item)
|
||||||
|
item->driver->link(NULL);
|
||||||
|
else delete item->driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstractOut * driverFactory::getDriver(Item * item)
|
||||||
|
{
|
||||||
|
if (!item || !item->isValid()) return NULL;
|
||||||
|
abstractOut * driver = findDriver(item);
|
||||||
|
if (driver)
|
||||||
|
{
|
||||||
|
if (driver->getItem()) driver = newDriver(item->itemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
driver = newDriver(item->itemType);
|
||||||
|
if (driver) drivers[item->itemType]=driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (driver) driver->link(item);
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstractOut * driverFactory::newDriver(uint8_t itemType)
|
||||||
|
{
|
||||||
|
abstractOut * driver = NULL;
|
||||||
|
switch (itemType)
|
||||||
|
{
|
||||||
|
#ifndef PWM_DISABLE
|
||||||
|
case CH_PWM:
|
||||||
|
driver = new out_pwm ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DMX_DISABLE
|
||||||
|
case CH_DIMMER:
|
||||||
|
driver = new out_dmx ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifndef SPILED_DISABLE
|
||||||
|
case CH_SPILED:
|
||||||
|
driver = new out_SPILed ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AC_DISABLE
|
||||||
|
case CH_AC:
|
||||||
|
driver = new out_AC ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MOTOR_DISABLE
|
||||||
|
case CH_MOTOR:
|
||||||
|
driver = new out_Motor ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MBUS_DISABLE
|
||||||
|
case CH_MBUS:
|
||||||
|
driver = new out_Modbus ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PID_DISABLE
|
||||||
|
case CH_PID:
|
||||||
|
driver = new out_pid ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RELAY_DISABLE
|
||||||
|
case CH_RELAYX:
|
||||||
|
driver = new out_relay ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MULTIVENT_DISABLE
|
||||||
|
case CH_MULTIVENT:
|
||||||
|
driver = new out_Multivent ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UARTBRIDGE_ENABLE
|
||||||
|
case CH_UARTBRIDGE:
|
||||||
|
driver = new out_UARTbridge ;
|
||||||
|
// debugSerial<<F("AC driver created")<<endl;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ELEVATOR_ENABLE
|
||||||
|
case CH_ELEVATOR:
|
||||||
|
driver = new out_elevator ;
|
||||||
|
// debugSerial<<F("AC driver created")<<endl;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HUMIDIFIER_ENABLE
|
||||||
|
case CH_HUMIDIFIER:
|
||||||
|
driver = new out_humidifier ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MERCURY_ENABLE
|
||||||
|
case CH_MERCURY:
|
||||||
|
driver = new out_Mercury ;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef COUNTER_DISABLE
|
||||||
|
case CH_COUNTER:
|
||||||
|
driver = new out_counter ;
|
||||||
|
// debugSerial<<F("AC driver created")<<endl;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright © 2017-2020 Andrey Klimov. All rights reserved.
|
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -22,6 +22,7 @@ e-mail anklimov@gmail.com
|
|||||||
#include "abstractout.h"
|
#include "abstractout.h"
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
|
||||||
|
|
||||||
#define S_NOTFOUND 0
|
#define S_NOTFOUND 0
|
||||||
#define S_CMD 1
|
#define S_CMD 1
|
||||||
#define S_SET 2
|
#define S_SET 2
|
||||||
@@ -67,12 +68,17 @@ const suffixstr suffix_P[] PROGMEM =
|
|||||||
#define CH_COUNTER 20
|
#define CH_COUNTER 20
|
||||||
#define CH_HUMIDIFIER 21
|
#define CH_HUMIDIFIER 21
|
||||||
#define CH_MERCURY 22
|
#define CH_MERCURY 22
|
||||||
|
#define CH_MAX 22
|
||||||
|
|
||||||
#define POLLING_SLOW 1
|
#define POLLING_SLOW 1
|
||||||
#define POLLING_FAST 2
|
#define POLLING_FAST 2
|
||||||
#define POLLING_INT 3
|
#define POLLING_INT 3
|
||||||
#define POLLING_1S 4
|
#define POLLING_1S 4
|
||||||
|
|
||||||
|
//CTRL Execution flags
|
||||||
|
#define CTRL_DISABLE_RECURSION 1
|
||||||
|
#define CTRL_DISABLE_NON_GRP 2
|
||||||
|
#define CTRL_SCHEDULED_CALL_RECURSION (CTRL_DISABLE_RECURSION | CTRL_DISABLE_NON_GRP)
|
||||||
|
|
||||||
#define I_TYPE 0 //Type of item
|
#define I_TYPE 0 //Type of item
|
||||||
#define I_ARG 1 //Chanel-type depended argument or array of arguments (pin, address etc)
|
#define I_ARG 1 //Chanel-type depended argument or array of arguments (pin, address etc)
|
||||||
@@ -116,7 +122,7 @@ class Item
|
|||||||
boolean Setup();
|
boolean Setup();
|
||||||
void Stop();
|
void Stop();
|
||||||
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL);
|
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL);
|
||||||
int Ctrl(itemCmd cmd, char* subItem=NULL, bool allowRecursion = true, bool authorized=false);
|
int Ctrl(itemCmd cmd, char* subItem=NULL, uint8_t flags = 0, bool authorized=false);
|
||||||
int Ctrl(char * payload, char * subItem=NULL, int remoteID = 0);
|
int Ctrl(char * payload, char * subItem=NULL, int remoteID = 0);
|
||||||
int remoteCtrl(itemCmd cmd, int remoteID, char* subItem=NULL, char * authToken=NULL);
|
int remoteCtrl(itemCmd cmd, int remoteID, char* subItem=NULL, char * authToken=NULL);
|
||||||
int getArg(short n=0);
|
int getArg(short n=0);
|
||||||
@@ -138,21 +144,21 @@ class Item
|
|||||||
void setFloatVal(float par);
|
void setFloatVal(float par);
|
||||||
void setSubtype(uint8_t par);
|
void setSubtype(uint8_t par);
|
||||||
int Poll(int cause);
|
int Poll(int cause);
|
||||||
int SendStatus(int sendFlags);
|
int SendStatus(long sendFlags, char * subItem=NULL);
|
||||||
int SendStatusImmediate(itemCmd st, int sendFlags, char * subItem=NULL);
|
int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL, bool tetain = true);
|
||||||
int isActive();
|
int isActive();
|
||||||
int getChanType();
|
int getChanType();
|
||||||
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
|
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
|
||||||
inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));};
|
inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));};
|
||||||
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
|
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
|
||||||
int scheduleCommand(itemCmd cmd, bool authorized);
|
int scheduleCommand(itemCmd cmd, bool authorized);
|
||||||
int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized);
|
int scheduleOppositeCommand(itemCmd cmd,short isActiveNow,bool authorized);
|
||||||
int isScheduled();
|
int isScheduled();
|
||||||
char * getSubItemStrById(uint8_t subItem);
|
char * getSubItemStrById(uint8_t subItem);
|
||||||
uint8_t getSubitemId(char * subItem);
|
uint8_t getSubitemId(char * subItem);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false);
|
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false, uint8_t ctrlFlags = 0);
|
||||||
long int limitSetValue();
|
long int limitSetValue();
|
||||||
int VacomSetFan (itemCmd st);
|
int VacomSetFan (itemCmd st);
|
||||||
int VacomSetHeat(itemCmd st);
|
int VacomSetHeat(itemCmd st);
|
||||||
@@ -169,6 +175,18 @@ class Item
|
|||||||
int defaultSuffixCode;
|
int defaultSuffixCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class driverFactory {
|
||||||
|
public:
|
||||||
|
driverFactory(){memset(drivers,0,sizeof(drivers));};
|
||||||
|
Item * getItem(Item * item);
|
||||||
|
abstractOut * getDriver(Item * item);
|
||||||
|
abstractOut * findDriver(Item * item);
|
||||||
|
void freeDriver(Item * item);
|
||||||
|
abstractOut * newDriver(uint8_t itemType);
|
||||||
|
private:
|
||||||
|
abstractOut * drivers[CH_MAX+1];
|
||||||
|
};
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
|||||||
@@ -429,6 +429,23 @@ bool itemCmd::incrementS(long int dif)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool itemCmd::incrementTemp(long int dif)
|
||||||
|
{int par=param.colorTemp;
|
||||||
|
switch (cmd.itemArgType)
|
||||||
|
{
|
||||||
|
case ST_HSV255:
|
||||||
|
par+=dif/TENS_BASE;
|
||||||
|
if (par>100) par=100;
|
||||||
|
if (par<1) par=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
param.colorTemp=par;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
|
itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
|
||||||
{
|
{
|
||||||
@@ -1030,7 +1047,7 @@ itemCmd itemCmd::Int(int32_t i)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemCmd itemCmd::Int(uint32_t i)
|
itemCmd itemCmd::uInt(uint32_t i)
|
||||||
{
|
{
|
||||||
cmd.itemArgType=ST_UINT32;
|
cmd.itemArgType=ST_UINT32;
|
||||||
param.asUint32=i;
|
param.asUint32=i;
|
||||||
@@ -1163,7 +1180,7 @@ bool itemCmd::loadItem(Item * item, uint16_t optionsFlag)
|
|||||||
{
|
{
|
||||||
case aJson_Int:
|
case aJson_Int:
|
||||||
|
|
||||||
Int((int32_t)item->itemVal->valueint);
|
Int(item->itemVal->valueint);
|
||||||
//debugSerial<<F("Loaded Int:");
|
//debugSerial<<F("Loaded Int:");
|
||||||
//debugOut();
|
//debugOut();
|
||||||
return true;
|
return true;
|
||||||
@@ -1211,7 +1228,7 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
|
|||||||
|
|
||||||
case CMD_ENABLE:
|
case CMD_ENABLE:
|
||||||
item->clearFlag(FLAG_DISABLED);
|
item->clearFlag(FLAG_DISABLED);
|
||||||
item->clearFlag(FLAG_FREEZED);
|
//? item->clearFlag(FLAG_FREEZED); //?
|
||||||
break;
|
break;
|
||||||
case CMD_FREEZE:
|
case CMD_FREEZE:
|
||||||
item->setFlag(FLAG_FREEZED);
|
item->setFlag(FLAG_FREEZED);
|
||||||
@@ -1351,13 +1368,13 @@ return false;
|
|||||||
return itemCmd().Int((uint32_t)2);
|
return itemCmd().Int((uint32_t)2);
|
||||||
*/
|
*/
|
||||||
case CMD_OFF:
|
case CMD_OFF:
|
||||||
return itemCmd().Int((uint32_t)0);
|
return itemCmd().Int(0);
|
||||||
case CMD_LOW:
|
case CMD_LOW:
|
||||||
return itemCmd().Int((uint32_t)20);
|
return itemCmd().Int(20);
|
||||||
case CMD_MED:
|
case CMD_MED:
|
||||||
return itemCmd().Int((uint32_t)128);
|
return itemCmd().Int(128);
|
||||||
case CMD_HIGH:
|
case CMD_HIGH:
|
||||||
return itemCmd().Int((uint32_t)255);
|
return itemCmd().Int(255);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1367,17 +1384,40 @@ return false;
|
|||||||
|
|
||||||
if (matchedCmd && matchedCmd->type != aJson_NULL)
|
if (matchedCmd && matchedCmd->type != aJson_NULL)
|
||||||
{
|
{
|
||||||
return itemCmd().Int((uint32_t)matchedCmd->valueint);
|
traceSerial<<F("MAP: cmd mapped to ")<<matchedCmd->valueint<<endl;
|
||||||
|
return itemCmd().Int(matchedCmd->valueint);
|
||||||
}
|
}
|
||||||
|
|
||||||
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
||||||
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
|
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
|
||||||
{
|
{ //ПРЯМОЕ
|
||||||
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0);
|
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
|
||||||
return itemCmd().Int((uint32_t)
|
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,4);
|
||||||
map(getInt(),
|
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,6);
|
||||||
|
|
||||||
|
//if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0); было если меньше левой границы то ноль. Неперь для такого поведения надо пятым элементом явно поставить ноль
|
||||||
|
|
||||||
|
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint)
|
||||||
|
{
|
||||||
|
traceSerial<<F("MAP: value ")<<getInt()<<F(" is below left bound ")<<aJson.getArrayItem(valMapping,0)->valueint<<endl;
|
||||||
|
if (leftBoundObj && leftBoundObj->type == aJson_Int )
|
||||||
|
return itemCmd().Int(leftBoundObj->valueint);
|
||||||
|
else return itemCmd(ST_VOID,CMD_VOID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getInt()>aJson.getArrayItem(valMapping,1)->valueint)
|
||||||
|
{
|
||||||
|
traceSerial<<F("MAP: value above right bound ")<<endl;
|
||||||
|
if (rightBoundObj && rightBoundObj->type == aJson_Int )
|
||||||
|
return itemCmd().Int(rightBoundObj->valueint);
|
||||||
|
else return itemCmd(ST_VOID,CMD_VOID);
|
||||||
|
}
|
||||||
|
long res = map(getInt(),
|
||||||
aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint,
|
aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint,
|
||||||
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint));
|
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint);
|
||||||
|
traceSerial<<F("MAP: val mapped to ")<<res<<endl;
|
||||||
|
return itemCmd().Int(res);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (valMapping && valMapping->type == aJson_NULL) return itemCmd(ST_VOID,CMD_VOID);
|
else if (valMapping && valMapping->type == aJson_NULL) return itemCmd(ST_VOID,CMD_VOID);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1445,14 +1485,36 @@ if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArray
|
|||||||
if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint);
|
if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint);
|
||||||
|
|
||||||
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
||||||
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
|
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
|
||||||
{
|
{
|
||||||
|
//ОБРАТНОЕ
|
||||||
|
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
|
||||||
int a = aJson.getArrayItem(valMapping,0)->valueint;
|
int a = aJson.getArrayItem(valMapping,0)->valueint;
|
||||||
int b = aJson.getArrayItem(valMapping,1)->valueint;
|
int b = aJson.getArrayItem(valMapping,1)->valueint;
|
||||||
int c = aJson.getArrayItem(valMapping,2)->valueint;
|
int c = aJson.getArrayItem(valMapping,2)->valueint;
|
||||||
int d = aJson.getArrayItem(valMapping,3)->valueint;
|
int d = aJson.getArrayItem(valMapping,3)->valueint;
|
||||||
|
|
||||||
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
|
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,5);
|
||||||
|
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,7);
|
||||||
|
// Dev to unified
|
||||||
|
//было если меньше левой границы то ноль. Неперь для такого поведения надо 7m элементом явно поставить ноль
|
||||||
|
//if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
|
||||||
|
|
||||||
|
|
||||||
|
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint)
|
||||||
|
{
|
||||||
|
if (leftBoundObj && leftBoundObj->type == aJson_Int )
|
||||||
|
return itemCmd().Int(leftBoundObj->valueint);
|
||||||
|
else return itemCmd(ST_VOID,CMD_VOID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getInt()>aJson.getArrayItem(valMapping,3)->valueint)
|
||||||
|
{
|
||||||
|
if (rightBoundObj && rightBoundObj->type == aJson_Int )
|
||||||
|
return itemCmd().Int(rightBoundObj->valueint);
|
||||||
|
else return itemCmd(ST_VOID,CMD_VOID);
|
||||||
|
}
|
||||||
|
|
||||||
int diff = ((b-a)/(d-c))/2;
|
int diff = ((b-a)/(d-c))/2;
|
||||||
//return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
|
//return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
|
||||||
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,b));
|
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,b));
|
||||||
@@ -1469,7 +1531,7 @@ char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100
|
|||||||
if (!Buffer || !bufLen) return NULL;
|
if (!Buffer || !bufLen) return NULL;
|
||||||
*Buffer=0;
|
*Buffer=0;
|
||||||
char * argPtr=Buffer;
|
char * argPtr=Buffer;
|
||||||
if (isCommand() && (sendFlags & FLAG_COMMAND))
|
if (isCommand() && (sendFlags & FLAG_COMMAND) && cmd.cmdCode<commandsNum)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
strncpy_P(Buffer, commands_P[cmd.cmdCode], bufLen);
|
strncpy_P(Buffer, commands_P[cmd.cmdCode], bufLen);
|
||||||
|
|||||||
@@ -21,15 +21,15 @@ e-mail anklimov@gmail.com
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "aJSON.h"
|
#include "aJSON.h"
|
||||||
|
|
||||||
typedef char cmdstr[9];
|
typedef char cmdstr[10];
|
||||||
|
|
||||||
const cmdstr commands_P[] PROGMEM =
|
const cmdstr commands_P[] PROGMEM =
|
||||||
{
|
{
|
||||||
"","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE",
|
"","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE",
|
||||||
"ENABLE","DISABLE","UNFREEZE","FREEZE",
|
"ENABLE","DISABLE","UNFREEZE","FREEZE",
|
||||||
"AUTO","FAN_ONLY",
|
"AUTO","FAN_ONLY",
|
||||||
"HIGH","MEDIUM","LOW",
|
"HIGH","MEDIUM","LOW","HEAT_COOL",
|
||||||
"HEAT","COOL","DRY","STOP","RGB","HSV"
|
"HEAT","COOL","DRY","RGB","HSV"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define commandsNum sizeof(commands_P)/sizeof(cmdstr)
|
#define commandsNum sizeof(commands_P)/sizeof(cmdstr)
|
||||||
@@ -87,10 +87,10 @@ const ch_type ch_type_P[] PROGMEM =
|
|||||||
#define CMD_MED 0x11 /// AC/Vent fan level MEDIUM
|
#define CMD_MED 0x11 /// AC/Vent fan level MEDIUM
|
||||||
#define CMD_LOW 0x12 /// AC/Vent fan level LOW
|
#define CMD_LOW 0x12 /// AC/Vent fan level LOW
|
||||||
|
|
||||||
#define CMD_HEAT 0x13 /// Thermostat/AC set to HEATing mode
|
#define CMD_HEATCOOL 0x13 ///
|
||||||
#define CMD_COOL 0x14 /// Thermostat/AC set to COOLing mode
|
#define CMD_HEAT 0x14 /// Thermostat/AC set to HEATing mode
|
||||||
#define CMD_DRY 0x15 /// AC set to Dry mode
|
#define CMD_COOL 0x15 /// Thermostat/AC set to COOLing mode
|
||||||
#define CMD_STOP 0x16 /// stop dimming (for further use)
|
#define CMD_DRY 0x16 /// AC set to Dry mode
|
||||||
|
|
||||||
#define CMD_RGB 0x17
|
#define CMD_RGB 0x17
|
||||||
#define CMD_HSV 0x18
|
#define CMD_HSV 0x18
|
||||||
@@ -104,21 +104,40 @@ const ch_type ch_type_P[] PROGMEM =
|
|||||||
#define CMD_JSON -2
|
#define CMD_JSON -2
|
||||||
|
|
||||||
//FLAGS
|
//FLAGS
|
||||||
#define FLAG_SEND_IMMEDIATE 0x1UL
|
|
||||||
#define FLAG_COMMAND 0x100UL
|
|
||||||
#define FLAG_PARAMETERS 0x200UL
|
|
||||||
#define FLAG_FLAGS 0x400UL
|
|
||||||
#define FLAG_SEND_RETRY 0x800UL
|
|
||||||
#define FLAG_SEND_DEFFERED 0x1000UL
|
|
||||||
#define FLAG_SEND_DELAYED 0x2000UL
|
|
||||||
#define FLAG_ACTION_NEEDED 0x4000UL
|
|
||||||
#define FLAG_ACTION_IN_PROCESS 0x8000UL
|
|
||||||
|
|
||||||
#define FLAG_DISABLED 0x10000UL
|
//#define FLAG_COMMAND 0x100UL
|
||||||
#define FLAG_FREEZED 0x20000UL
|
//#define FLAG_PARAMETERS 0x200UL
|
||||||
|
//#define FLAG_FLAGS 0x400UL
|
||||||
|
//#define FLAG_SEND_RETRY 0x800UL
|
||||||
|
//#define FLAG_SEND_DEFFERED 0x1000UL
|
||||||
|
//#define FLAG_SEND_DELAYED 0x2000UL
|
||||||
|
//#define FLAG_ACTION_NEEDED 0x4000UL
|
||||||
|
//#define FLAG_ACTION_IN_PROCESS 0x8000UL
|
||||||
|
//#define FLAG_DISABLED 0x10000UL
|
||||||
|
//#define FLAG_FREEZED 0x20000UL
|
||||||
|
//#define FLAG_HALTED 0x40000UL
|
||||||
|
//#define FLAG_XON 0x80000UL
|
||||||
|
|
||||||
|
#define FLAG_DISABLED 0x100UL
|
||||||
|
#define FLAG_LOCKED_CMD 0x200UL
|
||||||
|
#define FLAG_LOCKED_SET 0x400UL
|
||||||
|
#define FLAG_FREEZED 0x600UL
|
||||||
|
|
||||||
|
#define FLAG_SEND_DEFFERED 0x800UL
|
||||||
|
#define FLAG_COMMAND 0x1000UL
|
||||||
|
#define FLAG_PARAMETERS 0x2000UL
|
||||||
|
#define FLAG_FLAGS 0x4000UL
|
||||||
|
|
||||||
|
#define FLAG_SEND_RETRY 0x8000UL
|
||||||
|
|
||||||
|
#define FLAG_ACTION_NEEDED 0x10000UL
|
||||||
|
#define FLAG_ACTION_IN_PROCESS 0x20000UL
|
||||||
#define FLAG_HALTED 0x40000UL
|
#define FLAG_HALTED 0x40000UL
|
||||||
#define FLAG_XON 0x80000UL
|
#define FLAG_XON 0x80000UL
|
||||||
|
#define FLAG_SEND_DELAYED 0x100000UL
|
||||||
|
|
||||||
|
|
||||||
|
#define FLAG_SEND_IMMEDIATE 0x1UL
|
||||||
#define FLAG_NOT_SEND_CAN 0x2UL
|
#define FLAG_NOT_SEND_CAN 0x2UL
|
||||||
|
|
||||||
int txt2cmd (char * payload);
|
int txt2cmd (char * payload);
|
||||||
@@ -212,7 +231,7 @@ public:
|
|||||||
bool saveItem(Item * item, uint16_t optionsFlag=FLAG_PARAMETERS);
|
bool saveItem(Item * item, uint16_t optionsFlag=FLAG_PARAMETERS);
|
||||||
|
|
||||||
itemCmd Int(int32_t i);
|
itemCmd Int(int32_t i);
|
||||||
itemCmd Int(uint32_t i);
|
itemCmd uInt(uint32_t i);
|
||||||
itemCmd Float(float f);
|
itemCmd Float(float f);
|
||||||
itemCmd Tens(int32_t i);
|
itemCmd Tens(int32_t i);
|
||||||
itemCmd Tens_raw(int32_t i);
|
itemCmd Tens_raw(int32_t i);
|
||||||
@@ -242,6 +261,7 @@ public:
|
|||||||
bool incrementPercents(long int, long int limit);
|
bool incrementPercents(long int, long int limit);
|
||||||
bool incrementH(long int);
|
bool incrementH(long int);
|
||||||
bool incrementS(long int);
|
bool incrementS(long int);
|
||||||
|
bool incrementTemp(long int dif);
|
||||||
|
|
||||||
long int getInt();
|
long int getInt();
|
||||||
long int getTens();
|
long int getTens();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ e-mail anklimov@gmail.com
|
|||||||
#include "flashstream.h"
|
#include "flashstream.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#if defined(__SAM3X8E__)
|
#if defined(TIMER_INT)
|
||||||
#include "TimerInterrupt_Generic.h"
|
#include "TimerInterrupt_Generic.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -192,6 +192,7 @@ if (configLocked>locksAlowed)
|
|||||||
}
|
}
|
||||||
debugSerial<<F("Stopping channels ...")<<endl;
|
debugSerial<<F("Stopping channels ...")<<endl;
|
||||||
timerHandlerBusy++;
|
timerHandlerBusy++;
|
||||||
|
inputStop();
|
||||||
//Stoping the channels
|
//Stoping the channels
|
||||||
if (items)
|
if (items)
|
||||||
{
|
{
|
||||||
@@ -551,28 +552,6 @@ void printMACAddress() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* getStringFromConfig(aJsonObject * a, int i)
|
|
||||||
{
|
|
||||||
aJsonObject * element = NULL;
|
|
||||||
if (!a) return NULL;
|
|
||||||
if (a->type == aJson_Array)
|
|
||||||
element = aJson.getArrayItem(a, i);
|
|
||||||
// TODO - human readable JSON objects as alias
|
|
||||||
|
|
||||||
if (element && element->type == aJson_String) return element->valuestring;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* getStringFromConfig(aJsonObject * a, char * name)
|
|
||||||
{
|
|
||||||
aJsonObject * element = NULL;
|
|
||||||
if (!a) return NULL;
|
|
||||||
if (a->type == aJson_Object)
|
|
||||||
element = aJson.getObjectItem(a, name);
|
|
||||||
if (element && element->type == aJson_String) return element->valuestring;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OTA
|
#ifdef OTA
|
||||||
const char defaultPassword[] PROGMEM = QUOTE(DEFAULT_OTA_PASSWORD);
|
const char defaultPassword[] PROGMEM = QUOTE(DEFAULT_OTA_PASSWORD);
|
||||||
void setupOTA(void)
|
void setupOTA(void)
|
||||||
@@ -608,7 +587,7 @@ void setupSyslog()
|
|||||||
|
|
||||||
udpSyslogArr = aJson.getObjectItem(root, "syslog");
|
udpSyslogArr = aJson.getObjectItem(root, "syslog");
|
||||||
if (udpSyslogArr && (n = aJson.getArraySize(udpSyslogArr))) {
|
if (udpSyslogArr && (n = aJson.getArraySize(udpSyslogArr))) {
|
||||||
char *syslogServer = getStringFromConfig(udpSyslogArr, 0);
|
char *syslogServer = getStringFromJson(udpSyslogArr, 0);
|
||||||
|
|
||||||
if (n>1) syslogPort = aJson.getArrayItem(udpSyslogArr, 1)->valueint;
|
if (n>1) syslogPort = aJson.getArrayItem(udpSyslogArr, 1)->valueint;
|
||||||
|
|
||||||
@@ -619,7 +598,7 @@ void setupSyslog()
|
|||||||
udpSyslog.server(syslogServer, syslogPort);
|
udpSyslog.server(syslogServer, syslogPort);
|
||||||
udpSyslog.deviceHostname(syslogDeviceHostname);
|
udpSyslog.deviceHostname(syslogDeviceHostname);
|
||||||
|
|
||||||
if (mqttArr) deviceName = getStringFromConfig(mqttArr, 0);
|
if (mqttArr) deviceName = getStringFromJson(mqttArr, 0);
|
||||||
if (deviceName) udpSyslog.appName(deviceName);
|
if (deviceName) udpSyslog.appName(deviceName);
|
||||||
else udpSyslog.appName(lighthub);
|
else udpSyslog.appName(lighthub);
|
||||||
udpSyslog.defaultPriority(LOG_KERN);
|
udpSyslog.defaultPriority(LOG_KERN);
|
||||||
@@ -1119,7 +1098,7 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
deviceName = getStringFromConfig(mqttArr, 0);
|
deviceName = getStringFromJson(mqttArr, 0);
|
||||||
if (!deviceName) deviceName = (char*) lighthub;
|
if (!deviceName) deviceName = (char*) lighthub;
|
||||||
|
|
||||||
infoSerial<<F("Device Name:")<<deviceName<<endl;
|
infoSerial<<F("Device Name:")<<deviceName<<endl;
|
||||||
@@ -1132,13 +1111,13 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
|||||||
|
|
||||||
//debugSerial<<F("N:")<<n<<endl;
|
//debugSerial<<F("N:")<<n<<endl;
|
||||||
|
|
||||||
char *servername = getStringFromConfig(mqttArr, 1);
|
char *servername = getStringFromJson(mqttArr, 1);
|
||||||
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
||||||
if (n >= 4) user = getStringFromConfig(mqttArr, 3);
|
if (n >= 4) user = getStringFromJson(mqttArr, 3);
|
||||||
//if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
//if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
||||||
if (!sysConf.getMQTTpwd(passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
if (!sysConf.getMQTTpwd(passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
||||||
{
|
{
|
||||||
password = getStringFromConfig(mqttArr, 4);
|
password = getStringFromJson(mqttArr, 4);
|
||||||
infoSerial<<F("Using MQTT password from config")<<endl;
|
infoSerial<<F("Using MQTT password from config")<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2206,6 +2185,25 @@ int16_t attachTimer(double microseconds, timerCallback callback, const char* Tim
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_STM32) && defined (TIMER_INT)
|
||||||
|
STM32Timer ITimer0(TIM1);
|
||||||
|
|
||||||
|
int16_t attachTimer(double microseconds, timerCallback callback, const char* TimerName)
|
||||||
|
{
|
||||||
|
if (timerNumber!=-1) return timerNumber;
|
||||||
|
// Interval in microsecs
|
||||||
|
if (ITimer0.attachInterruptInterval(microseconds, callback))
|
||||||
|
{
|
||||||
|
debugSerial.print(F("Starting ITimer0 OK"));
|
||||||
|
timerNumber = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debugSerial.println(F("Can't set ITimer0. Select another freq. or timer"));
|
||||||
|
return timerNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__SAM3X8E__) && defined (PULSEPIN12)
|
#if defined(__SAM3X8E__) && defined (PULSEPIN12)
|
||||||
#define MATURA_PULSE 100
|
#define MATURA_PULSE 100
|
||||||
#define MATURA_PERIOD 2500
|
#define MATURA_PERIOD 2500
|
||||||
@@ -3061,7 +3059,7 @@ configLocked++;
|
|||||||
|
|
||||||
// Check for nested inputs
|
// Check for nested inputs
|
||||||
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
||||||
if (inputArray && (inputArray->type == aJson_Array))
|
if (inputArray && (inputArray->type == aJson_Array || inputArray->type == aJson_Object))
|
||||||
{
|
{
|
||||||
aJsonObject *inputObj = inputArray->child;
|
aJsonObject *inputObj = inputArray->child;
|
||||||
|
|
||||||
@@ -3138,6 +3136,32 @@ configLocked++;
|
|||||||
// Interval in microsecs
|
// Interval in microsecs
|
||||||
attachTimer(TIMER_CHECK_INPUT * 1000, TimerHandler, "ITimer");
|
attachTimer(TIMER_CHECK_INPUT * 1000, TimerHandler, "ITimer");
|
||||||
attachMaturaTimer();
|
attachMaturaTimer();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_STM32) && defined (TIMER_INT)
|
||||||
|
// Interval in microsecs
|
||||||
|
attachTimer(TIMER_CHECK_INPUT * 1000, TimerHandler, "ITimer");
|
||||||
|
#endif
|
||||||
|
configLocked--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inputStop(void) {
|
||||||
|
infoSerial<<F("Stopping Inputs")<<endl;
|
||||||
|
if (!inputs) return;
|
||||||
|
configLocked++;
|
||||||
|
aJsonObject *input = inputs->child;
|
||||||
|
while (input) {
|
||||||
|
if ((input->type == aJson_Object)) {
|
||||||
|
Input in(input);
|
||||||
|
in.stop();
|
||||||
|
}
|
||||||
|
yield();
|
||||||
|
input = input->next;
|
||||||
|
}
|
||||||
|
#if defined(__SAM3X8E__) && defined (TIMER_INT)
|
||||||
|
// Interval in microsecs
|
||||||
|
//detachTimer(TIMER_CHECK_INPUT * 1000, TimerHandler, "ITimer");
|
||||||
|
//detachMaturaTimer();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
configLocked--;
|
configLocked--;
|
||||||
@@ -3258,7 +3282,7 @@ publishStat();
|
|||||||
|
|
||||||
if (tStore.timestamp16) //Valid temperature
|
if (tStore.timestamp16) //Valid temperature
|
||||||
{
|
{
|
||||||
if (isTimeOver(tStore.timestamp16,millisNZ(8) & 0xFFFF,PERIOD_THERMOSTAT_FAILED >> 8,0xFFFF))
|
if (isTimeOver(tStore.timestamp16,millisNZ(8,0xFFFF),PERIOD_THERMOSTAT_FAILED >> 8,0xFFFF))
|
||||||
{
|
{
|
||||||
errorSerial<<thermoItem->name<<F(" Alarm Expired\n");
|
errorSerial<<thermoItem->name<<F(" Alarm Expired\n");
|
||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ void inputLoop(short);
|
|||||||
void inputSensorsLoop();
|
void inputSensorsLoop();
|
||||||
|
|
||||||
void inputSetup(void);
|
void inputSetup(void);
|
||||||
|
void inputStop(void);
|
||||||
|
|
||||||
void pollingLoop(void);
|
void pollingLoop(void);
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ if (Status() == AC_SENDING)
|
|||||||
ACSerial->write(getCRC(req, size-1));
|
ACSerial->write(getCRC(req, size-1));
|
||||||
//ACSerial->flush();
|
//ACSerial->flush();
|
||||||
store->timestamp=millisNZ();
|
store->timestamp=millisNZ();
|
||||||
debugSerial<<F("AC: ")<<portNum<<F(" <<");
|
debugSerial<<F("AC:")<<portNum<<F(" << ");
|
||||||
for (int i=0; i < size-1; i++)
|
for (int i=0; i < size-1; i++)
|
||||||
{
|
{
|
||||||
if (req[i] < 10){
|
if (req[i] < 10){
|
||||||
@@ -326,6 +326,9 @@ if (!store)
|
|||||||
return 0;}
|
return 0;}
|
||||||
|
|
||||||
memset(store->data,0,sizeof(acPersistent::data));
|
memset(store->data,0,sizeof(acPersistent::data));
|
||||||
|
store->data[0]=255;
|
||||||
|
store->data[1]=255;
|
||||||
|
store->data[2]=0x22;
|
||||||
store->mode=0;
|
store->mode=0;
|
||||||
store->power=0;
|
store->power=0;
|
||||||
store->inCheck=0;
|
store->inCheck=0;
|
||||||
@@ -436,34 +439,41 @@ case AC_AWAITINGCMD: //Flusing port for 5 sec, poll status
|
|||||||
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
byte tmpdata[sizeof(store->data)];
|
||||||
if(ACSerial->available() >= 37){ //was 0
|
if(ACSerial->available() >= 37){ //was 0
|
||||||
ACSerial->readBytes(store->data, 37);
|
ACSerial->readBytes(tmpdata, 37);
|
||||||
while(ACSerial->available()){
|
while(ACSerial->available()){
|
||||||
delay(2);
|
delay(2);
|
||||||
ACSerial->read();
|
ACSerial->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
debugSerial<<F("AC: ")<<portNum<<F(" >> ");
|
debugSerial<<F("AC:")<<portNum<<F(" >> ");
|
||||||
for (int i=0; i < 37-1; i++)
|
for (int i=0; i < 37-1; i++)
|
||||||
{
|
{
|
||||||
if (store->data[i] < 10){
|
if (tmpdata[i] < 10){
|
||||||
debugSerial.print("0");
|
debugSerial.print("0");
|
||||||
debugSerial.print(store->data[i], HEX);
|
debugSerial.print(tmpdata[i], HEX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debugSerial.print(store->data[i], HEX);
|
debugSerial.print(tmpdata[i], HEX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debugSerial.println('.');
|
||||||
|
|
||||||
|
uint8_t crc=getCRC(tmpdata,36);
|
||||||
|
|
||||||
if (store->data[36] != store->inCheck){
|
if (tmpdata[36] == crc)
|
||||||
store->inCheck = store->data[36];
|
{
|
||||||
InsertData(store->data, 37);
|
debugSerial<<F("AC: OK")<<endl;
|
||||||
debugSerial<<F("AC: OK");
|
if (tmpdata[36] != store->inCheck)
|
||||||
|
{ //Updated
|
||||||
|
store->inCheck = tmpdata[36];
|
||||||
|
memcpy(store->data,tmpdata,sizeof(store->data));
|
||||||
|
InsertData(store->data, 37);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else debugSerial<<F("AC: Bad CRC")<<endl;
|
||||||
debugSerial.println();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ public:
|
|||||||
class out_AC : public abstractOut {
|
class out_AC : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_AC(Item * _item):abstractOut(_item){store = (acPersistent *) item->getPersistent(); getConfig();};
|
out_AC():store(NULL),portNum(0),ACSerial(NULL){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (acPersistent *) item->getPersistent(); getConfig();} else store = NULL;};
|
||||||
void getConfig();
|
void getConfig();
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ case S_CMD:
|
|||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
case CMD_FAN:
|
case CMD_FAN:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
if (!item->getExt())
|
if (!item->getExt())
|
||||||
{
|
{
|
||||||
item->setExt(millisNZ());
|
item->setExt(millisNZ());
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
class out_counter : public abstractOut {
|
class out_counter : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_counter(Item * _item):abstractOut(_item){};
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|||||||
@@ -9,14 +9,10 @@
|
|||||||
|
|
||||||
class out_dmx : public colorChannel {
|
class out_dmx : public colorChannel {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_dmx(Item * _item):colorChannel(_item){};
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|
||||||
int getChanType() override;
|
int getChanType() override;
|
||||||
// int Ctrl(itemCmd cmd, char* subItem=NULL) override;
|
|
||||||
// int PixelCtrl(itemCmd cmd) override;
|
|
||||||
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false) override;
|
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ if (!getConfig()) return 0;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
store->timestamp = millisNZ();
|
||||||
setStatus(CST_INITIALIZED);
|
setStatus(CST_INITIALIZED);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,13 +42,15 @@ public:
|
|||||||
class out_Mercury : public abstractOut {
|
class out_Mercury : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_Mercury(Item * _item):abstractOut(_item){store = (mercuryPersistent *) item->getPersistent();};
|
//out_Mercury(Item * _item):abstractOut(_item){store = (mercuryPersistent *) item->getPersistent();};
|
||||||
|
out_Mercury():store(NULL){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (mercuryPersistent *) item->getPersistent();} else store = NULL;};
|
||||||
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
int getChanType() override;
|
int getChanType() override;
|
||||||
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
|
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
|
||||||
//int getDefaultStorageType(){return ST_INT32;};
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -60,8 +60,18 @@ const reg_t regSize_P[] PROGMEM =
|
|||||||
} ;
|
} ;
|
||||||
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Меняет порядок байтов в 16-битном числе.
|
||||||
|
* @param x Входное число.
|
||||||
|
* @return Число с изменённым порядком байтов.
|
||||||
|
*/
|
||||||
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Преобразует строку в тип регистра.
|
||||||
|
* @param str Строка с типом регистра.
|
||||||
|
* @return Код типа регистра.
|
||||||
|
*/
|
||||||
int str2regSize(char * str)
|
int str2regSize(char * str)
|
||||||
{
|
{
|
||||||
for(uint8_t i=0; i<regSizeNum && str;i++)
|
for(uint8_t i=0; i<regSizeNum && str;i++)
|
||||||
@@ -70,6 +80,62 @@ int str2regSize(char * str)
|
|||||||
return (int) PAR_I16;
|
return (int) PAR_I16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO irs etc
|
||||||
|
/**
|
||||||
|
* @brief Получает имя параметра по номеру регистра.
|
||||||
|
* @param parameters JSON-объект с параметрами.
|
||||||
|
* @param regnum Номер регистра.
|
||||||
|
* @return Имя параметра или NULL.
|
||||||
|
*/
|
||||||
|
char * getParamNameByReg(aJsonObject * parameters, int regnum)
|
||||||
|
{
|
||||||
|
if (!parameters) return NULL;
|
||||||
|
|
||||||
|
aJsonObject * i = parameters->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * regObj = aJson.getObjectItem(i, "reg");
|
||||||
|
if (regObj && regObj->type == aJson_Int && regObj->valueint == regnum)
|
||||||
|
{
|
||||||
|
debugSerial<<F("MBUS: ")<<i->name<<F(" added by num ")<<regnum<<endl;
|
||||||
|
return i->name;
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверяет наличие действия в JSON-объекте.
|
||||||
|
* @param execObj JSON-объект.
|
||||||
|
* @return true, если действие найдено, иначе false.
|
||||||
|
*/
|
||||||
|
bool haveAction(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
aJsonObject * j = execObj->child;
|
||||||
|
switch (execObj->type)
|
||||||
|
{
|
||||||
|
case aJson_Object:
|
||||||
|
while (j)
|
||||||
|
{
|
||||||
|
if (j->name && *j->name && (*j->name != '@')) return true;
|
||||||
|
j=j->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case aJson_Array:
|
||||||
|
while (j)
|
||||||
|
{
|
||||||
|
if (haveAction(j)) return true;
|
||||||
|
j=j->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Загружает и применяет конфигурацию Modbus.
|
||||||
|
* @return true, если конфигурация успешно загружена, иначе false.
|
||||||
|
*/
|
||||||
bool out_Modbus::getConfig()
|
bool out_Modbus::getConfig()
|
||||||
{
|
{
|
||||||
// Retrieve and store template values from global modbus settings
|
// Retrieve and store template values from global modbus settings
|
||||||
@@ -124,11 +190,136 @@ bool out_Modbus::getConfig()
|
|||||||
else {store->pollingRegisters=NULL;store->pollingInterval = 1000;store->pollingIrs=NULL;}
|
else {store->pollingRegisters=NULL;store->pollingInterval = 1000;store->pollingIrs=NULL;}
|
||||||
|
|
||||||
store->parameters=aJson.getObjectItem(templateObj, "par");
|
store->parameters=aJson.getObjectItem(templateObj, "par");
|
||||||
|
|
||||||
|
// initializing @S where needed
|
||||||
|
|
||||||
|
if (store->parameters)
|
||||||
|
{
|
||||||
|
// Creating for parameters where prefetch required
|
||||||
|
debugSerial<<F("Adding prefetch regs:")<<endl;
|
||||||
|
aJsonObject * i = store->parameters->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * prefetchObj = aJson.getObjectItem(i, "prefetch");
|
||||||
|
if (prefetchObj && prefetchObj->type == aJson_Boolean && prefetchObj->valuebool)
|
||||||
|
{
|
||||||
|
createLastMeasured(i->name);
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugSerial<<F("Adding referred regs:")<<endl;
|
||||||
|
i = store->parameters->child;
|
||||||
|
// Creating for parameters used in references from another parameters
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * mapObj = aJson.getObjectItem(i, "map");
|
||||||
|
if (mapObj)
|
||||||
|
{
|
||||||
|
aJsonObject * defObj = aJson.getObjectItem(mapObj, "def");
|
||||||
|
if (defObj && defObj->type == aJson_Int)
|
||||||
|
{
|
||||||
|
createLastMeasured(getParamNameByReg(store->parameters,defObj->valueint));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defObj && defObj->type == aJson_String)
|
||||||
|
{
|
||||||
|
createLastMeasured(defObj->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
debugSerial<<F("Adding regs with actions:")<<endl;
|
||||||
|
// Check - if action configured for object and create
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
if (itemParametersObj)
|
||||||
|
{
|
||||||
|
i = itemParametersObj->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (haveAction(i)) createLastMeasured(i);
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
//store->addr=item->getArg(0);
|
//store->addr=item->getArg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Создаёт поле для хранения последнего измеренного значения по имени параметра.
|
||||||
|
* @param name Имя параметра.
|
||||||
|
* @return true, если успешно, иначе false.
|
||||||
|
*/
|
||||||
|
int out_Modbus::createLastMeasured(char * name)
|
||||||
|
{
|
||||||
|
if (!name) return false;
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
return createLastMeasured(aJson.getObjectItem(itemParametersObj,name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Создаёт поле для хранения последнего измеренного значения по JSON-объекту.
|
||||||
|
* @param execObj JSON-объект параметра.
|
||||||
|
* @return true, если успешно, иначе false.
|
||||||
|
*/
|
||||||
|
int out_Modbus::createLastMeasured(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
if (!execObj) return false;
|
||||||
|
|
||||||
|
aJsonObject * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array)
|
||||||
|
{
|
||||||
|
markObj = execObj->child;
|
||||||
|
//storeLastValue = true;
|
||||||
|
}
|
||||||
|
if (!markObj) return false;
|
||||||
|
|
||||||
|
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
|
||||||
|
if (lastMeasured) return false;
|
||||||
|
|
||||||
|
debugSerial<<F("MBUS: Add @S: ")<<execObj->name<<endl;
|
||||||
|
aJson.addNumberToObject(markObj, "@S", (long) 0);
|
||||||
|
|
||||||
|
lastMeasured = aJson.getObjectItem(markObj,"@S");
|
||||||
|
if (!lastMeasured) return false;
|
||||||
|
lastMeasured->subtype |= MB_VALUE_OUTDATED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает объект последнего измеренного значения по имени параметра.
|
||||||
|
* @param name Имя параметра.
|
||||||
|
* @return JSON-объект или NULL.
|
||||||
|
*/
|
||||||
|
aJsonObject * out_Modbus::getLastMeasured(char * name)
|
||||||
|
{
|
||||||
|
if (!name) return NULL;
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
return getLastMeasured (aJson.getObjectItem(itemParametersObj,name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает объект последнего измеренного значения по JSON-объекту.
|
||||||
|
* @param execObj JSON-объект параметра.
|
||||||
|
* @return JSON-объект или NULL.
|
||||||
|
*/
|
||||||
|
aJsonObject * out_Modbus::getLastMeasured(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
if (!execObj) return NULL;
|
||||||
|
if (execObj->type == aJson_Array) execObj = execObj->child;
|
||||||
|
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S");
|
||||||
|
if (lastMeasured && lastMeasured->type == aJson_Int) return lastMeasured;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует канал Modbus и загружает конфигурацию.
|
||||||
|
* @return 1 при успехе, 0 при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::Setup()
|
int out_Modbus::Setup()
|
||||||
{
|
{
|
||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
@@ -147,11 +338,16 @@ if (getConfig())
|
|||||||
else
|
else
|
||||||
{ errorSerial<<F("MBUS: config error")<<endl;
|
{ errorSerial<<F("MBUS: config error")<<endl;
|
||||||
setStatus(CST_FAILED);
|
setStatus(CST_FAILED);
|
||||||
|
Stop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Останавливает работу канала Modbus и освобождает ресурсы.
|
||||||
|
* @return 1 при успехе.
|
||||||
|
*/
|
||||||
int out_Modbus::Stop()
|
int out_Modbus::Stop()
|
||||||
{
|
{
|
||||||
debugSerial.print("MBUS: De-Init ");
|
debugSerial.print("MBUS: De-Init ");
|
||||||
@@ -166,6 +362,13 @@ return 1;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Читает данные из Modbus-устройства.
|
||||||
|
* @param reg Номер регистра.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
* @param count Количество регистров.
|
||||||
|
* @return true, если чтение успешно, иначе false.
|
||||||
|
*/
|
||||||
bool readModbus(uint16_t reg, int regType, int count)
|
bool readModbus(uint16_t reg, int regType, int count)
|
||||||
{
|
{
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
@@ -193,6 +396,17 @@ return (result == node.ku8MBSuccess);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Находит и обрабатывает регистр Modbus, выполняет сопоставление и действия.
|
||||||
|
* @param registerNum Номер регистра.
|
||||||
|
* @param posInBuffer Позиция в буфере ответа.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
* @param registerFrom Начальный регистр диапазона.
|
||||||
|
* @param registerTo Конечный регистр диапазона.
|
||||||
|
* @param doExecution Выполнять ли действие.
|
||||||
|
* @param submitParam Флаг для подавления повторных действий.
|
||||||
|
* @return Команда itemCmd с результатом.
|
||||||
|
*/
|
||||||
itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution, bool * submitParam)
|
itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution, bool * submitParam)
|
||||||
{
|
{
|
||||||
aJsonObject * paramObj = store->parameters->child;
|
aJsonObject * paramObj = store->parameters->child;
|
||||||
@@ -308,7 +522,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
{
|
{
|
||||||
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
|
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
|
||||||
executeWithoutCheck=true;
|
executeWithoutCheck=true;
|
||||||
debugSerial<<"MBUSD: recurrent check res: "<<"SRO:"<<submitRecurrentOut<<endl;
|
traceSerial<<"MBUSD: recurrent check res: "<<"SRO:"<<submitRecurrentOut<<endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -330,12 +544,9 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
||||||
{
|
{
|
||||||
//Searching item param for nested mapping
|
//Searching item param for nested mapping
|
||||||
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
|
//Retrive previous data
|
||||||
if (itemParObj)
|
aJsonObject *lastMeasured = getLastMeasured(defMappingObj->valuestring);
|
||||||
{
|
if (lastMeasured)
|
||||||
//Retrive previous data
|
|
||||||
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
|
|
||||||
if (lastMeasured && lastMeasured->type ==aJson_Int)
|
|
||||||
{
|
{
|
||||||
traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
|
traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
|
||||||
//Searching template param for nested mapping
|
//Searching template param for nested mapping
|
||||||
@@ -384,8 +595,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} //nested have lastMeasured
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -411,52 +621,31 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
|
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
|
||||||
if (execObj)
|
if (execObj)
|
||||||
{
|
{
|
||||||
|
// if (!doExecution || haveAction(execObj)) //if no action in execObj - do not save last value to avoid confuse further recurrent check
|
||||||
bool storeLastValue = true;
|
// {
|
||||||
if (doExecution)
|
|
||||||
{
|
|
||||||
storeLastValue=false;
|
|
||||||
// Check - if no action configured for object - not need to store last value - let requrent process do it
|
|
||||||
|
|
||||||
aJsonObject * i = execObj->child;
|
|
||||||
while (i && !storeLastValue)
|
|
||||||
{
|
|
||||||
if (i->name && *i->name && (*i->name != '@')) storeLastValue = true;
|
|
||||||
i=i->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aJsonObject * markObj = execObj;
|
|
||||||
if (execObj->type == aJson_Array)
|
|
||||||
{
|
|
||||||
markObj = execObj->child;
|
|
||||||
storeLastValue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storeLastValue)
|
|
||||||
{
|
|
||||||
//Retrive previous data
|
//Retrive previous data
|
||||||
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
|
aJsonObject *lastMeasured = getLastMeasured(execObj);
|
||||||
if (lastMeasured)
|
if (lastMeasured)
|
||||||
{
|
{
|
||||||
if (lastMeasured->type == aJson_Int)
|
|
||||||
{
|
|
||||||
if (lastMeasured->valueint == param)
|
if (lastMeasured->valueint == param)
|
||||||
*submitParam=false; //supress repeating execution for same val
|
{
|
||||||
|
//if recurrent call but value was readed before
|
||||||
|
if (!doExecution && !(lastMeasured->subtype & MB_VALUE_OUTDATED))
|
||||||
|
{
|
||||||
|
*submitParam=true; //never used
|
||||||
|
lastMeasured->subtype|=MB_VALUE_OUTDATED;
|
||||||
|
return mappedParam;
|
||||||
|
}
|
||||||
|
*submitParam=false; //supress repeating execution for same val
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lastMeasured->valueint=param;
|
lastMeasured->valueint=param;
|
||||||
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
|
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
|
||||||
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else //No container to store value yet
|
// }
|
||||||
{
|
|
||||||
debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl;
|
|
||||||
aJson.addNumberToObject(markObj, "@S", (long) param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executeWithoutCheck)
|
if (executeWithoutCheck)
|
||||||
{
|
{
|
||||||
@@ -474,6 +663,12 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (*submitParam && doExecution)
|
if (*submitParam && doExecution)
|
||||||
{
|
{
|
||||||
// Compare with last submitted val (if @V NOT marked as NULL in config)
|
// Compare with last submitted val (if @V NOT marked as NULL in config)
|
||||||
|
aJsonObject * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array)
|
||||||
|
{
|
||||||
|
markObj = execObj->child;
|
||||||
|
//storeLastValue = true;
|
||||||
|
}
|
||||||
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
|
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
|
||||||
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
|
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
|
||||||
{
|
{
|
||||||
@@ -491,19 +686,24 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (settedValue && !(execObj->subtype & MB_NEED_SEND))
|
if (settedValue && !(execObj->subtype & MB_NEED_SEND))
|
||||||
settedValue->valueint=param;
|
settedValue->valueint=param;
|
||||||
}
|
}
|
||||||
}
|
} //to be executed
|
||||||
}
|
} //ExecObj
|
||||||
}
|
} //item Parameters
|
||||||
//if (submitRecurrentOut) *submitParam=true; //if requrrent check has submit smth - report it.
|
|
||||||
return mappedParam;
|
return mappedParam;
|
||||||
}
|
} //reg == regNum
|
||||||
paramObj=paramObj->next;
|
paramObj=paramObj->next;
|
||||||
}
|
} //while
|
||||||
return itemCmd();
|
return itemCmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void out_Modbus::pollModbus(aJsonObject * reg, int regType)
|
/**
|
||||||
|
* @brief Опрос Modbus-устройства по списку регистров.
|
||||||
|
* @param reg JSON-объект с регистрами.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
*/
|
||||||
|
void out_Modbus::pollModbus(aJsonObject * reg, int regType)
|
||||||
{
|
{
|
||||||
if (!reg) return;
|
if (!reg) return;
|
||||||
reg=reg->child;
|
reg=reg->child;
|
||||||
@@ -541,6 +741,9 @@ return itemCmd();
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует линию связи Modbus.
|
||||||
|
*/
|
||||||
void out_Modbus::initLine()
|
void out_Modbus::initLine()
|
||||||
{
|
{
|
||||||
//store->serialParam=(USARTClass::USARTModes) SERIAL_8N1;
|
//store->serialParam=(USARTClass::USARTModes) SERIAL_8N1;
|
||||||
@@ -559,6 +762,12 @@ void out_Modbus::initLine()
|
|||||||
node.begin(item->getArg(0), modbusSerial);
|
node.begin(item->getArg(0), modbusSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет значение в Modbus-устройство.
|
||||||
|
* @param paramName Имя параметра.
|
||||||
|
* @param outValue JSON-объект с отправляемым значением.
|
||||||
|
* @return 0 при успехе, отрицательное значение при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
|
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
|
||||||
{
|
{
|
||||||
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
||||||
@@ -618,14 +827,14 @@ if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valueboo
|
|||||||
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
|
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
|
||||||
if (execObj)
|
if (execObj)
|
||||||
{
|
{
|
||||||
aJsonObject * markObj = execObj;
|
//aJsonObject * markObj = execObj;
|
||||||
if (execObj->type == aJson_Array) markObj = execObj->child;
|
//if (execObj->type == aJson_Array) markObj = execObj->child;
|
||||||
//Retrive previous data
|
//Retrive previous data
|
||||||
lastMeasured = aJson.getObjectItem(markObj,"@S");
|
lastMeasured = getLastMeasured(execObj);// aJson.getObjectItem(markObj,"@S");
|
||||||
if (lastMeasured)
|
if (lastMeasured)
|
||||||
{
|
{
|
||||||
if (lastMeasured->type == aJson_Int)
|
//if (lastMeasured->type == aJson_Int)
|
||||||
{
|
// {
|
||||||
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
|
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
|
||||||
|
|
||||||
if (lastMeasured->valueint != localBuffer)
|
if (lastMeasured->valueint != localBuffer)
|
||||||
@@ -645,7 +854,7 @@ if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valueboo
|
|||||||
|
|
||||||
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,6 +904,11 @@ if ((res ==0) && (outValue->type == aJson_Int) && lastMeasured && (lastMeasured-
|
|||||||
return ( res == 0);
|
return ( res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Осуществляет опрос и отправку команд Modbus.
|
||||||
|
* @param cause Причина вызова (например, медленный опрос).
|
||||||
|
* @return Интервал следующего опроса.
|
||||||
|
*/
|
||||||
int out_Modbus::Poll(short cause)
|
int out_Modbus::Poll(short cause)
|
||||||
{
|
{
|
||||||
if (cause==POLLING_SLOW) return 0;
|
if (cause==POLLING_SLOW) return 0;
|
||||||
@@ -732,7 +946,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
savedValue = outValue->valueint;
|
savedValue = outValue->valueint;
|
||||||
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
|
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<"/"<<execObj->name<<"="<<outValue->valueint<<endl;
|
||||||
sendRes = sendModbus(execObj->name,outValue);
|
sendRes = sendModbus(execObj->name,outValue);
|
||||||
needResend = (savedValue != outValue->valueint);
|
needResend = (savedValue != outValue->valueint);
|
||||||
while(needResend && mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200)) modbusIdle();
|
while(needResend && mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200)) modbusIdle();
|
||||||
@@ -750,18 +964,18 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
break;
|
break;
|
||||||
case 0: //fault
|
case 0: //fault
|
||||||
execObj->subtype |= MB_SEND_ERROR;
|
execObj->subtype |= MB_SEND_ERROR;
|
||||||
errorSerial<<F("MBUS: ")<<execObj->name<<F(" send error. ");
|
errorSerial<<F("MBUS: ")<<item->itemArr->name<<"/"<<execObj->name<<F(" send error. ");
|
||||||
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
|
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
|
||||||
errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl;
|
errorSerial<<F("MBUS: ")<<item->itemArr->name<<"/"<<execObj->name<<" Attempt: "<< (execObj->subtype & 3) <<endl;
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" sending cancelled")<<endl;
|
errorSerial<<F("MBUS: param ")<<item->itemArr->name<<"/"<<execObj->name<<F(" sending cancelled")<<endl;
|
||||||
//outValue->valueint=
|
//outValue->valueint=
|
||||||
//execObj->subtype&=~ MB_NEED_SEND;
|
//execObj->subtype&=~ MB_NEED_SEND;
|
||||||
execObj->subtype = 0;
|
execObj->subtype = 0;
|
||||||
break;
|
break;
|
||||||
default: //param not found
|
default: //param not found
|
||||||
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
|
errorSerial<<F("MBUS: param ")<<item->itemArr->name<<"/"<<execObj->name<<F(" not found")<<endl;
|
||||||
execObj->subtype&=~ MB_NEED_SEND;
|
execObj->subtype&=~ MB_NEED_SEND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -825,11 +1039,21 @@ if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store
|
|||||||
return store->pollingInterval;
|
return store->pollingInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает тип канала.
|
||||||
|
* @return CH_MBUS.
|
||||||
|
*/
|
||||||
int out_Modbus::getChanType()
|
int out_Modbus::getChanType()
|
||||||
{
|
{
|
||||||
return CH_MBUS;
|
return CH_MBUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет команду itemCmd в Modbus по шаблону параметра.
|
||||||
|
* @param templateParamObj JSON-объект шаблона параметра.
|
||||||
|
* @param cmd Команда itemCmd.
|
||||||
|
* @return 1 при успехе, 0 при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd)
|
int out_Modbus::sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd)
|
||||||
{
|
{
|
||||||
if (templateParamObj)
|
if (templateParamObj)
|
||||||
@@ -926,6 +1150,14 @@ else return 0;
|
|||||||
// 2. custom textual subItem
|
// 2. custom textual subItem
|
||||||
// 3. non-standard numeric suffix Code equal param id
|
// 3. non-standard numeric suffix Code equal param id
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Унифицированное управление Modbus-каналом.
|
||||||
|
* @param cmd Команда itemCmd.
|
||||||
|
* @param subItem Имя подэлемента.
|
||||||
|
* @param toExecute Выполнять ли команду.
|
||||||
|
* @param authorized Авторизовано ли выполнение.
|
||||||
|
* @return Результат выполнения.
|
||||||
|
*/
|
||||||
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
|
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
|
||||||
{
|
{
|
||||||
if (!store) return -1;
|
if (!store) return -1;
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ public:
|
|||||||
|
|
||||||
class out_Modbus : public abstractOut {
|
class out_Modbus : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
//out_Modbus(Item * _item):abstractOut(_item){store = (mbPersistent *) item->getPersistent();};
|
||||||
|
out_Modbus():store(NULL){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (mbPersistent *) item->getPersistent(); } else store = NULL;};
|
||||||
|
|
||||||
out_Modbus(Item * _item):abstractOut(_item){store = (mbPersistent *) item->getPersistent();};
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
@@ -49,5 +51,9 @@ protected:
|
|||||||
void initLine();
|
void initLine();
|
||||||
int sendModbus(char * paramName, aJsonObject * outValue);
|
int sendModbus(char * paramName, aJsonObject * outValue);
|
||||||
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
||||||
|
int createLastMeasured(char * name);
|
||||||
|
int createLastMeasured(aJsonObject * execObj);
|
||||||
|
aJsonObject * getLastMeasured(char * name);
|
||||||
|
aJsonObject * getLastMeasured(aJsonObject * execObj);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ static int8_t motorQuote = MOTOR_QUOTE;
|
|||||||
class out_Motor : public abstractOut {
|
class out_Motor : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_Motor(Item * _item):abstractOut(_item){getConfig();};
|
//out_Motor(Item * _item):abstractOut(_item){getConfig();};
|
||||||
|
//out_Motor(){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) getConfig();};
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|||||||
@@ -7,7 +7,19 @@
|
|||||||
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void convert2float(aJsonObject * o)
|
||||||
|
{
|
||||||
|
if (!o) return;
|
||||||
|
switch (o->type)
|
||||||
|
{
|
||||||
|
case aJson_Int:
|
||||||
|
o->valuefloat = o->valueint;
|
||||||
|
o->type = aJson_Float;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void out_Multivent::getConfig()
|
void out_Multivent::getConfig()
|
||||||
{
|
{
|
||||||
@@ -21,30 +33,51 @@ int out_Multivent::Setup()
|
|||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
//getConfig();
|
//getConfig();
|
||||||
|
|
||||||
//Expand Argument storage to 2
|
|
||||||
//for (int i = aJson.getArraySize(item->itemArg); i < 2; i++)
|
|
||||||
// aJson.addItemToArray(item->itemArg, aJson.createItem( (long int) 0));
|
|
||||||
|
|
||||||
//Allocate objects to store persistent data in config tree
|
//Allocate objects to store persistent data in config tree
|
||||||
if (gatesObj /*&& aJson.getArraySize(item->itemArg)>=2*/)
|
if (gatesObj)
|
||||||
{
|
{
|
||||||
aJsonObject * i = gatesObj->child;
|
aJsonObject * i = gatesObj->child;
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
if (i->name && *i->name)
|
if (i->name && *i->name)
|
||||||
{
|
{
|
||||||
aJsonObject * setObj = aJson.getObjectItem(i, "set");
|
getCreateObject(i,"fan",-1L);
|
||||||
if (!setObj) aJson.addNumberToObject(i, "set", (long int) -1);
|
getCreateObject(i,"cmd",(long) CMD_OFF);
|
||||||
|
getCreateObject(i,"out",-1L);
|
||||||
|
//getCreateObject(i,"@C",(long) CMD_OFF);
|
||||||
|
|
||||||
aJsonObject * cmdObj = aJson.getObjectItem(i, "cmd");
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
if (!cmdObj) aJson.addNumberToObject(i, "cmd", (long int) -1);
|
if (pidObj && pidObj->type == aJson_Array && aJson.getArraySize(pidObj)>=3)
|
||||||
|
{
|
||||||
|
aJsonObject * setObj = getCreateObject(i,"set",(float) 20.0);
|
||||||
|
convert2float(setObj);
|
||||||
|
aJsonObject * valObj = getCreateObject(i,"val",(float) 20.0);
|
||||||
|
convert2float(valObj);
|
||||||
|
aJsonObject * poObj = getCreateObject(i,"po", (float) -2.0);
|
||||||
|
convert2float(poObj);
|
||||||
|
|
||||||
|
int direction = DIRECT;
|
||||||
|
float kP=getFloatFromJson(pidObj,0,1.0);
|
||||||
|
if (kP<0)
|
||||||
|
{
|
||||||
|
kP=-kP;
|
||||||
|
direction=REVERSE;
|
||||||
|
}
|
||||||
|
float kI=getFloatFromJson(pidObj,1);
|
||||||
|
float kD=getFloatFromJson(pidObj,2);
|
||||||
|
float dT=getFloatFromJson(pidObj,3,5.0);
|
||||||
|
|
||||||
aJsonObject * outObj = aJson.getObjectItem(i, "out");
|
pidObj->valueint = (long int) new PID (&valObj->valuefloat, &poObj->valuefloat, &setObj->valuefloat, kP, kI, kD, direction);
|
||||||
if (!outObj) aJson.addNumberToObject(i, "out", (long int) -1);
|
|
||||||
|
((PID*) pidObj->valueint)->SetMode (AUTOMATIC);
|
||||||
|
((PID*) pidObj->valueint)->SetSampleTime(dT*1000.0);
|
||||||
|
debugSerial << F ("VENT: PID P=")<<kP<<" I="<<kI<<" D="<<kD<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i=i->next;
|
i=i->next;
|
||||||
}
|
}
|
||||||
debugSerial << F ("VENT: init")<< endl;
|
debugSerial << F ("VENT: init")<< endl;
|
||||||
|
item->setExt(0);
|
||||||
setStatus(CST_INITIALIZED);
|
setStatus(CST_INITIALIZED);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -57,18 +90,171 @@ return 0;
|
|||||||
int out_Multivent::Stop()
|
int out_Multivent::Stop()
|
||||||
{
|
{
|
||||||
debugSerial << F ("VENT: De-Init") << endl;
|
debugSerial << F ("VENT: De-Init") << endl;
|
||||||
|
if (gatesObj)
|
||||||
|
{
|
||||||
|
aJsonObject * i = gatesObj->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (i->name && *i->name)
|
||||||
|
{
|
||||||
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
|
if (pidObj && pidObj->valueint)
|
||||||
|
{
|
||||||
|
delete ((PID *) pidObj->valueint);
|
||||||
|
pidObj->valueint = 0;//NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
setStatus(CST_UNKNOWN);
|
setStatus(CST_UNKNOWN);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int out_Multivent::Poll(short cause)
|
int out_Multivent::Poll(short cause)
|
||||||
{
|
{
|
||||||
return 0;
|
if (cause == POLLING_SLOW && item->getExt() && isTimeOver(item->getExt(),millisNZ(),60000L))
|
||||||
|
{
|
||||||
|
item->setExt(0);
|
||||||
|
//item->setCmd((isActive())?CMD_ON:CMD_OFF); // if AC temp unknown - change state to ON or OFF instead HEAT|COOL|FAN
|
||||||
|
aJsonObject * a = aJson.getObjectItem(aJson.getObjectItem(gatesObj, ""),"val");
|
||||||
|
if (a ) a->type = aJson_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (gatesObj)
|
||||||
|
{
|
||||||
|
// metrics, collected from AC
|
||||||
|
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
|
||||||
|
float acTemp = getFloatFromJson(a,"val",NAN);
|
||||||
|
int actualCmd = getIntFromJson (a,"mode");
|
||||||
|
int actualMode = CMD_FAN;
|
||||||
|
if (acTemp>30.0) actualMode = CMD_HEAT;
|
||||||
|
else if (acTemp<15.0) actualMode = CMD_COOL;
|
||||||
|
|
||||||
|
|
||||||
|
aJsonObject * i = gatesObj->child;
|
||||||
|
int balance = 0;
|
||||||
|
bool ventRequested = false; //At least 1 ch requested FAN mode
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (i->name && *i->name)
|
||||||
|
{
|
||||||
|
int cmd = getIntFromJson(i,"cmd");
|
||||||
|
float set = getIntFromJson(i,"set");
|
||||||
|
float val = getIntFromJson(i,"val");
|
||||||
|
|
||||||
|
int execCmd = 0;
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case CMD_HEATCOOL:
|
||||||
|
{
|
||||||
|
if (set>val) execCmd = CMD_HEAT;
|
||||||
|
if (set<val) execCmd = CMD_COOL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMD_FAN:
|
||||||
|
ventRequested = true;
|
||||||
|
case CMD_AUTO: //Passive regulation mode
|
||||||
|
case CMD_COOL:
|
||||||
|
case CMD_HEAT:
|
||||||
|
case CMD_OFF:
|
||||||
|
//setValToJson(i,"@C",cmd);
|
||||||
|
execCmd = cmd;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
|
if (pidObj && pidObj->valueint)
|
||||||
|
{
|
||||||
|
PID * p = (PID *) pidObj->valueint;
|
||||||
|
if (p->Compute())
|
||||||
|
{
|
||||||
|
aJsonObject * poObj = aJson.getObjectItem(i,"po");
|
||||||
|
if (poObj && poObj->type == aJson_Float)
|
||||||
|
{
|
||||||
|
debugSerial<<F("VENT: ")
|
||||||
|
<<item->itemArr->name<<"/"<<i->name
|
||||||
|
<<F(" in:")<<p->GetIn()<<F(" set:")<<p->GetSet()<<F(" out:")<<p->GetOut()
|
||||||
|
<<" P:"<<p->GetKp()<<" I:"<<p->GetKi()<<" D:"<<p->GetKd()<<((p->GetDirection())?" Rev ":" Dir ")<<((p->GetMode())?"A":"M");
|
||||||
|
debugSerial<<endl;
|
||||||
|
|
||||||
|
|
||||||
|
switch (execCmd)
|
||||||
|
{
|
||||||
|
case CMD_AUTO: //Passive
|
||||||
|
switch (actualMode)
|
||||||
|
{
|
||||||
|
case CMD_HEAT:
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
|
||||||
|
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
|
||||||
|
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
break;
|
||||||
|
case CMD_COOL:
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
|
||||||
|
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
|
||||||
|
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMD_HEAT:
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
|
||||||
|
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
|
||||||
|
|
||||||
|
if (actualCmd==CMD_HEAT) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
//else?
|
||||||
|
|
||||||
|
balance+=poObj->valuefloat;
|
||||||
|
break;
|
||||||
|
case CMD_COOL:
|
||||||
|
//case CMD_FAN: // if PIB using for vent
|
||||||
|
//case CMD_ON: // AC temp unknown - assuming that PID used for vent
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
|
||||||
|
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
|
||||||
|
if (actualCmd==CMD_COOL) (itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
//else ?
|
||||||
|
balance-=poObj->valuefloat;
|
||||||
|
break;
|
||||||
|
// if FAN_ONLY (AC report room temp regularry) - not use internal PID - let be on external control via /fan
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}//while
|
||||||
|
if (balance) debugSerial<<F("VENT: Chan balance=")<<balance<<endl;
|
||||||
|
if (balance>0) sendACcmd (CMD_HEAT);
|
||||||
|
else if (balance<0) sendACcmd (CMD_COOL);
|
||||||
|
else if (ventRequested) sendACcmd(CMD_FAN);
|
||||||
|
// else sendACcmd (CMD_OFF);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int out_Multivent::sendACcmd (int cmd)
|
||||||
|
{
|
||||||
|
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
|
||||||
|
if (!a) return 0;
|
||||||
|
int lastCmd = getIntFromJson(a,"@lastCmd");
|
||||||
|
int acCmd = getIntFromJson(a,"mode");
|
||||||
|
if (lastCmd && (acCmd != lastCmd)) {
|
||||||
|
//debugSerial<<"VENT: AC MODE changed manually to "<<item->getCmd()<<endl;
|
||||||
|
return 0;}
|
||||||
|
if (cmd == lastCmd) {
|
||||||
|
//debugSerial<<"VENT: AC MODE already same"<<endl;
|
||||||
|
return 0;}
|
||||||
|
executeCommand(a,-1,itemCmd().Cmd(cmd).setSuffix(S_CMD));
|
||||||
|
setValToJson(a,"@lastCmd",cmd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int out_Multivent::getChanType()
|
int out_Multivent::getChanType()
|
||||||
{
|
{
|
||||||
return CH_PWM;
|
return CH_THERMO; /////PWM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -79,6 +265,41 @@ if (cmd.getCmd()==CMD_DISABLE || cmd.getCmd()==CMD_ENABLE) return 0;
|
|||||||
int suffixCode = cmd.getSuffix();
|
int suffixCode = cmd.getSuffix();
|
||||||
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
|
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
|
||||||
|
|
||||||
|
|
||||||
|
if (!subItem) // feedback from shared AC
|
||||||
|
{
|
||||||
|
switch (suffixCode)
|
||||||
|
{
|
||||||
|
case S_VAL:
|
||||||
|
if (cmd.isValue())
|
||||||
|
{
|
||||||
|
debugSerial << F("VENT:")<<F("AC air temp: ")<< cmd.getFloat()<<endl;
|
||||||
|
item->setExt(millisNZ());
|
||||||
|
setValToJson(aJson.getObjectItem(gatesObj, ""),"val",cmd.getFloat());
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case S_FAN:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case S_SET:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case S_MODE:
|
||||||
|
debugSerial << F("VENT:")<<F("AC mode: ")<< cmd.getCmd()<<endl;
|
||||||
|
setValToJson(aJson.getObjectItem(gatesObj, ""),"mode",cmd.getCmd());
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case S_CMD:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case S_TEMP:
|
||||||
|
debugSerial << F("VENT:")<<F("AC air roomtemp: ")<< cmd.getFloat()<<endl;
|
||||||
|
setValToJson(aJson.getObjectItem(gatesObj, ""),"roomtemp",cmd.getFloat());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
aJsonObject * i = NULL;
|
aJsonObject * i = NULL;
|
||||||
|
|
||||||
if (cmd.isCommand() && cmd.getSuffix()==S_FAN)
|
if (cmd.isCommand() && cmd.getSuffix()==S_FAN)
|
||||||
@@ -110,46 +331,33 @@ int maxPercent=0;
|
|||||||
|
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
|
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
|
||||||
aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
|
||||||
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
||||||
aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas");
|
aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas");
|
||||||
if (setObj && cmdObj && setObj->type==aJson_Int && cmdObj->type==aJson_Int)
|
|
||||||
|
//aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
||||||
|
aJsonObject * pidObj=aJson.getObjectItem(i, "pid");
|
||||||
|
if (fanObj && cmdObj && fanObj->type==aJson_Int && cmdObj->type==aJson_Int)
|
||||||
{
|
{
|
||||||
|
|
||||||
int V =aJson.getObjectItem(i,"V")->valueint;
|
int V = getIntFromJson(i,"V",60);
|
||||||
int requestedV=0;
|
int requestedV=0;
|
||||||
|
|
||||||
if (subItem && !strcmp (i->name,subItem))
|
if (subItem && !strcmp (i->name,subItem))
|
||||||
{
|
{
|
||||||
if (cmdObj && cmd.isCommand())
|
|
||||||
{
|
|
||||||
cmdObj->valueint = cmd.getCmd();
|
|
||||||
//publishTopic(i->name,cmdObj->valueint,"/set");
|
|
||||||
switch (cmd.getCmd())
|
|
||||||
{
|
|
||||||
case CMD_ON:
|
|
||||||
cmd.Percents255(setObj->valueint);
|
|
||||||
break;
|
|
||||||
case CMD_OFF:
|
|
||||||
cmd.Percents255(0);
|
|
||||||
}
|
|
||||||
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (setObj->valueint<20))
|
|
||||||
{
|
|
||||||
setObj->valueint=30;
|
|
||||||
cmd.Percents255(30);
|
|
||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_COMMAND|FLAG_PARAMETERS,i->name);
|
switch (suffixCode)
|
||||||
}
|
{
|
||||||
|
|
||||||
else if (setObj && cmdObj && suffixCode == S_FAN && cmd.isValue())
|
case S_FAN:
|
||||||
|
if (cmd.isValue())
|
||||||
{
|
{
|
||||||
|
|
||||||
if (cmd.getInt())
|
if (cmd.getInt())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (cmdObj->valueint == CMD_OFF || cmdObj->valueint == -1)
|
if (cmdObj->valueint == CMD_OFF)// || cmdObj->valueint == -1)
|
||||||
{
|
{
|
||||||
debugSerial<<"VENT: Turning ON"<<endl;
|
debugSerial<<"VENT: Turning ON"<<endl;
|
||||||
cmdObj->valueint = CMD_ON;
|
cmdObj->valueint = CMD_ON;
|
||||||
@@ -157,42 +365,110 @@ while (i)
|
|||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
setObj->valueint = cmd.getInt();
|
fanObj->valueint = cmd.getInt();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
if (cmdObj->valueint == CMD_ON)// != CMD_OFF && cmdObj->valueint != -1)
|
||||||
{ debugSerial<<"VENT: Turning OFF"<<endl;
|
{ debugSerial<<"VENT: Turning OFF"<<endl;
|
||||||
cmdObj->valueint = CMD_OFF;
|
cmdObj->valueint = CMD_OFF;
|
||||||
cmd.Cmd(CMD_OFF);
|
cmd.Cmd(CMD_OFF);
|
||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
setObj->valueint = 0;
|
fanObj->valueint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fanObj->valueint = cmd.getInt();
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS|FLAG_COMMAND,i->name);
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS|FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
if (!cmd.isCommand()) break; // if have command i FAN suffix - continue processing
|
||||||
else if (setObj && cmd.isValue())
|
case S_CMD:
|
||||||
|
if (cmd.isCommand())
|
||||||
{
|
{
|
||||||
setObj->valueint = cmd.getPercents255();
|
long sendFlags = 0;
|
||||||
//publishTopic(i->name,setObj->valueint,"/set");
|
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
|
||||||
|
switch (cmd.getCmd())
|
||||||
|
{
|
||||||
|
case CMD_ON:
|
||||||
|
cmd.Percents255(fanObj->valueint);
|
||||||
|
cmd.setSuffix(S_FAN);
|
||||||
|
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
case CMD_OFF:
|
||||||
|
cmd.Percents255(0);
|
||||||
|
cmd.setSuffix(S_FAN);
|
||||||
|
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
case CMD_ENABLE:
|
||||||
|
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(AUTOMATIC);
|
||||||
|
sendFlags |= FLAG_FLAGS;
|
||||||
|
break;
|
||||||
|
case CMD_DISABLE:
|
||||||
|
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(MANUAL);
|
||||||
|
sendFlags |= FLAG_FLAGS;
|
||||||
|
break;
|
||||||
|
case CMD_AUTO:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
|
case CMD_COOL:
|
||||||
|
case CMD_HEAT:
|
||||||
|
case CMD_FAN:
|
||||||
|
case CMD_DRY:
|
||||||
|
sendFlags |= FLAG_COMMAND;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
//todo - halt-rest-xon-xoff-low-med-hi
|
||||||
}
|
}
|
||||||
|
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (fanObj->valueint<20))
|
||||||
|
{
|
||||||
|
fanObj->valueint=30;
|
||||||
|
cmd.Percents255(30);
|
||||||
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,sendFlags,i->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case S_SET:
|
||||||
|
if (cmd.isValue())
|
||||||
|
{
|
||||||
|
setValToJson(i,"set",cmd.getFloat());
|
||||||
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_VAL:
|
||||||
|
if (cmd.isValue())
|
||||||
|
{
|
||||||
|
debugSerial<<F("VENT: value ")<<cmd.getFloat()<<endl;
|
||||||
|
setValToJson(i,"val",cmd.getFloat());
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cascadeObj) executeCommand(cascadeObj,-1,cmd);
|
if (cascadeObj) executeCommand(cascadeObj,-1,cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
||||||
{
|
{
|
||||||
requestedV=V*setObj->valueint;
|
requestedV=V*fanObj->valueint;
|
||||||
activeV+=requestedV;
|
activeV+=requestedV;
|
||||||
|
|
||||||
if (setObj->valueint>maxPercent )
|
if (fanObj->valueint>maxPercent )
|
||||||
{
|
{
|
||||||
maxRequestedV=requestedV;
|
maxRequestedV=requestedV;
|
||||||
maxV=V;
|
maxV=V;
|
||||||
maxPercent=setObj->valueint;
|
maxPercent=fanObj->valueint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalV+=V;
|
totalV+=V;
|
||||||
@@ -207,10 +483,13 @@ int fanV=activeV/totalV;
|
|||||||
debugSerial << F("VENT: Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max req:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
|
debugSerial << F("VENT: Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max req:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
|
||||||
|
|
||||||
//executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF));
|
//executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF));
|
||||||
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).setSuffix(S_FAN));
|
||||||
|
/*
|
||||||
if (fanV)
|
if (fanV)
|
||||||
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd(CMD_ON));
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd(CMD_ON));
|
||||||
else
|
else
|
||||||
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV));
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV)); */
|
||||||
|
|
||||||
//Move gates only if fan is actually on
|
//Move gates only if fan is actually on
|
||||||
if (!fanV) return 1;
|
if (!fanV) return 1;
|
||||||
|
|
||||||
@@ -219,18 +498,20 @@ if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow
|
|||||||
|
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
int V =aJson.getObjectItem(i,"V")->valueint;
|
|
||||||
|
int V = getIntFromJson(i,"V",60);
|
||||||
|
|
||||||
|
|
||||||
aJsonObject * outObj=aJson.getObjectItem(i, "out");
|
aJsonObject * outObj=aJson.getObjectItem(i, "out");
|
||||||
aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
|
||||||
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
||||||
|
|
||||||
if (outObj && setObj && cmdObj && outObj->type==aJson_Int && setObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
|
if (outObj && fanObj && cmdObj && outObj->type==aJson_Int && fanObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
|
||||||
{
|
{
|
||||||
long int out = 0;
|
long int out = 0;
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV)
|
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV)
|
||||||
{
|
{
|
||||||
int requestedV=V*setObj->valueint;
|
int requestedV=V*fanObj->valueint;
|
||||||
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
|
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
|
||||||
debugSerial<<F("VENT: ")<<i->name<<F(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
|
debugSerial<<F("VENT: ")<<i->name<<F(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <abstractout.h>
|
#include <abstractout.h>
|
||||||
#include <item.h>
|
#include <item.h>
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
#include <PID_v1.h>
|
||||||
|
|
||||||
|
|
||||||
//static int8_t motorQuote = 0;
|
//static int8_t motorQuote = 0;
|
||||||
@@ -11,7 +12,9 @@
|
|||||||
class out_Multivent : public abstractOut {
|
class out_Multivent : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_Multivent(Item * _item):abstractOut(_item){getConfig();};
|
//out_Multivent(Item * _item):abstractOut(_item){getConfig();};
|
||||||
|
//out_Multivent(){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) getConfig();};
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
@@ -21,6 +24,8 @@ public:
|
|||||||
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
|
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
|
||||||
protected:
|
protected:
|
||||||
void getConfig();
|
void getConfig();
|
||||||
|
int sendACcmd (int cmd);
|
||||||
aJsonObject * gatesObj;
|
aJsonObject * gatesObj;
|
||||||
|
//float acTemp;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
|
|||||||
item->clearFlag(FLAG_ACTION_NEEDED);
|
item->clearFlag(FLAG_ACTION_NEEDED);
|
||||||
|
|
||||||
itemCmd value((float) (store->output));
|
itemCmd value((float) (store->output));
|
||||||
value.setSuffix(S_SET);
|
//value.setSuffix(S_SET);
|
||||||
executeCommand(oCmd,-1,value);
|
executeCommand(oCmd,-1,value);
|
||||||
store->prevOut=store->output;
|
store->prevOut=store->output;
|
||||||
}
|
}
|
||||||
@@ -344,6 +344,7 @@ case S_CTRL:
|
|||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
case CMD_FAN:
|
case CMD_FAN:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE));
|
executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE));
|
||||||
executeCommand(oCmd,-1,value);
|
executeCommand(oCmd,-1,value);
|
||||||
item->SendStatus(FLAG_FLAGS);
|
item->SendStatus(FLAG_FLAGS);
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
class pidPersistent : public chPersistent {
|
class pidPersistent : public chPersistent {
|
||||||
public:
|
public:
|
||||||
PID * pid;
|
PID * pid;
|
||||||
double output;
|
iotype output;
|
||||||
double input;
|
iotype input;
|
||||||
double setpoint;
|
iotype setpoint;
|
||||||
float prevOut;
|
float prevOut;
|
||||||
uint32_t alarmTimer;
|
uint32_t alarmTimer;
|
||||||
bool alarmArmed;
|
bool alarmArmed;
|
||||||
@@ -25,7 +25,10 @@ public:
|
|||||||
class out_pid : public abstractOut {
|
class out_pid : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_pid(Item * _item):abstractOut(_item){store = (pidPersistent *) item->getPersistent();};
|
//out_pid(Item * _item):abstractOut(_item){store = (pidPersistent *) item->getPersistent();};
|
||||||
|
out_pid():store(NULL){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (pidPersistent *) item->getPersistent();} else store = NULL;};
|
||||||
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
class out_pwm : public colorChannel {
|
class out_pwm : public colorChannel {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_pwm(Item * _item):colorChannel(_item){numChannels=0;};
|
// out_pwm():numChannels(0){};
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public:
|
|||||||
//int Ctrl(itemCmd cmd, char* subItem=NULL) override;
|
//int Ctrl(itemCmd cmd, char* subItem=NULL) override;
|
||||||
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) override;
|
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) override;
|
||||||
|
|
||||||
protected:
|
//protected:
|
||||||
short numChannels;
|
// short numChannels;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ int out_relay::Setup()
|
|||||||
{
|
{
|
||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
|
|
||||||
debugSerial<<F("Relay-Out #")<<pin<<F(" init")<<endl;
|
debugSerial<<F("relayCtr: ")<<F("pin#")<<pin<<F(" init")<<endl;
|
||||||
if (isProtectedPin(pin)) {errorSerial<<F("pin disabled")<<endl;return 0;}
|
if (isProtectedPin(pin)) {errorSerial<<F("relayCtr: ")<<F("pin disabled")<<endl;return 0;}
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
digitalWrite(pin,INACTIVE);
|
digitalWrite(pin,INACTIVE);
|
||||||
if (item) item->setExt(0);
|
if (item) item->setExt(0);
|
||||||
@@ -52,7 +52,7 @@ return 1;
|
|||||||
|
|
||||||
int out_relay::Stop()
|
int out_relay::Stop()
|
||||||
{
|
{
|
||||||
debugSerial<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
|
||||||
pinMode(pin, INPUT);
|
pinMode(pin, INPUT);
|
||||||
setStatus(CST_UNKNOWN);
|
setStatus(CST_UNKNOWN);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -60,39 +60,12 @@ return 1;
|
|||||||
|
|
||||||
void out_relay::relay(bool state)
|
void out_relay::relay(bool state)
|
||||||
{
|
{
|
||||||
char subtopic[10]="/";
|
|
||||||
char val[10];
|
|
||||||
digitalWrite(pin,(state)?ACTIVE:INACTIVE);
|
digitalWrite(pin,(state)?ACTIVE:INACTIVE);
|
||||||
if (period<1000) return;
|
if (period<1000) return;
|
||||||
debugSerial<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
|
||||||
|
pubAction(state);
|
||||||
|
//debugSerial << F("OUT: ")<<F("pub action ") << F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
|
||||||
|
|
||||||
strcat_P(subtopic,action_P);
|
|
||||||
short cmd=item->getCmd();
|
|
||||||
if (state)
|
|
||||||
switch(cmd)
|
|
||||||
{
|
|
||||||
case CMD_COOL:
|
|
||||||
strcpy_P(val,cooling_P);
|
|
||||||
break;
|
|
||||||
//case CMD_AUTO:
|
|
||||||
//case CMD_HEAT:
|
|
||||||
//case CMD_ON:
|
|
||||||
//
|
|
||||||
// break;
|
|
||||||
case CMD_DRY:
|
|
||||||
strcpy_P(val,drying_P);
|
|
||||||
break;
|
|
||||||
case CMD_FAN:
|
|
||||||
strcpy_P(val,fan_P);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strcpy_P(val,heating_P);
|
|
||||||
}
|
|
||||||
else //turned off
|
|
||||||
if (cmd==CMD_OFF) strcpy_P(val,off_P);
|
|
||||||
else strcpy_P(val,idle_P);
|
|
||||||
|
|
||||||
debugSerial << F("pub action ") << publishTopic(item->itemArr->name,val,subtopic)<<F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -170,6 +143,7 @@ case S_SET:
|
|||||||
case CMD_COOL:
|
case CMD_COOL:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
if (cmd.getPercents255() && !item->getExt()) item->setExt(millisNZ());
|
if (cmd.getPercents255() && !item->getExt()) item->setExt(millisNZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,6 +158,7 @@ case S_CMD:
|
|||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
case CMD_FAN:
|
case CMD_FAN:
|
||||||
case CMD_DRY:
|
case CMD_DRY:
|
||||||
|
case CMD_HEATCOOL:
|
||||||
if (!item->getExt())
|
if (!item->getExt())
|
||||||
{
|
{
|
||||||
item->setExt(millisNZ());
|
item->setExt(millisNZ());
|
||||||
@@ -197,11 +172,11 @@ case S_CMD:
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugSerial<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
|
||||||
} //switch cmd
|
} //switch cmd
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugSerial<<F("Unknown suffix ")<<suffixCode<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Unknown suffix ")<<suffixCode<<endl;
|
||||||
} //switch suffix
|
} //switch suffix
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
class out_relay : public abstractOut {
|
class out_relay : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) getConfig();};
|
||||||
out_relay(Item * _item):abstractOut(_item){ getConfig();};
|
|
||||||
void getConfig();
|
void getConfig();
|
||||||
void relay(bool state);
|
void relay(bool state);
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
class out_SPILed : public colorChannel {
|
class out_SPILed : public colorChannel {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_SPILed(Item * _item):colorChannel(_item){getConfig();};
|
//out_SPILed(Item * _item):colorChannel(_item){getConfig();};
|
||||||
|
//out_SPILed(){};
|
||||||
|
void link(Item * _item){colorChannel::link(_item);if (_item) getConfig();};
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
int getChanType() override;
|
int getChanType() override;
|
||||||
|
|||||||
@@ -58,7 +58,12 @@ public:
|
|||||||
class out_UARTbridge : public abstractOut {
|
class out_UARTbridge : public abstractOut {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
out_UARTbridge(Item * _item):abstractOut(_item){store = (ubPersistent *) item->getPersistent();};
|
// out_UARTbridge(Item * _item):abstractOut(_item){store = (ubPersistent *) item->getPersistent();};
|
||||||
|
|
||||||
|
out_UARTbridge():store(NULL){};
|
||||||
|
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (ubPersistent *) item->getPersistent();} else store = NULL;};
|
||||||
|
|
||||||
|
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
int Poll(short cause) override;
|
int Poll(short cause) override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
#define TIMEOUT_RETAIN 8000UL
|
#define TIMEOUT_RETAIN 8000UL
|
||||||
#define TIMEOUT_REINIT_NOT_CONFIGURED 120000UL
|
#define TIMEOUT_REINIT_NOT_CONFIGURED 120000UL
|
||||||
#define INTERVAL_1W 5000UL
|
#define INTERVAL_1W 5000UL
|
||||||
#define PERIOD_THERMOSTAT_FAILED (600 * 1000UL)
|
#define PERIOD_THERMOSTAT_FAILED (600 * 1000UL) //16000 sec (4h) max
|
||||||
|
|
||||||
//#define T_ATTEMPTS 200
|
//#define T_ATTEMPTS 200
|
||||||
//#define IET_TEMP 0
|
//#define IET_TEMP 0
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include "streamlog.h"
|
#include "streamlog.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "statusled.h"
|
#include "statusled.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#ifdef SYSLOG_ENABLE
|
#ifdef SYSLOG_ENABLE
|
||||||
char logBuffer[LOGBUFFER_SIZE];
|
char logBuffer[LOGBUFFER_SIZE];
|
||||||
int logBufferPos=0;
|
int logBufferPos=0;
|
||||||
|
uint32_t silentTS=0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t serialDebugLevel = 7;
|
uint8_t serialDebugLevel = 7;
|
||||||
@@ -22,6 +24,7 @@ Streamlog::Streamlog (SerialPortType * _serialPort, uint8_t _severity , Syslog *
|
|||||||
severity=_severity;
|
severity=_severity;
|
||||||
syslog=_syslog;
|
syslog=_syslog;
|
||||||
ledPattern=_ledPattern;
|
ledPattern=_ledPattern;
|
||||||
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Streamlog::Streamlog (SerialPortType * _serialPort, uint8_t _severity, uint8_t _ledPattern)
|
Streamlog::Streamlog (SerialPortType * _serialPort, uint8_t _severity, uint8_t _ledPattern)
|
||||||
@@ -76,7 +79,30 @@ if (syslogInitialized && (udpDebugLevel>=severity))
|
|||||||
if (ch=='\n')
|
if (ch=='\n')
|
||||||
{
|
{
|
||||||
logBuffer[logBufferPos]=0;
|
logBuffer[logBufferPos]=0;
|
||||||
if (syslog) syslog->log(severity,(char *)logBuffer);
|
if (syslog && (!silentTS || isTimeOver(silentTS,millis(),30000UL)))
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t ts = millis();
|
||||||
|
syslog->log(severity,(char *)logBuffer);
|
||||||
|
if (millis() - ts > 100UL)
|
||||||
|
{
|
||||||
|
#if !defined(noSerial)
|
||||||
|
if (serialPort) serialPort->println(F("Syslog suspended"));
|
||||||
|
#endif
|
||||||
|
silentTS = millisNZ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (silentTS)
|
||||||
|
{
|
||||||
|
#if !defined(noSerial)
|
||||||
|
if (serialPort) serialPort->println(F("Syslog resumed"));
|
||||||
|
#endif
|
||||||
|
silentTS = 0;
|
||||||
|
syslog->log(severity,F("Syslog resumed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
logBufferPos=0;
|
logBufferPos=0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LOGBUFFER_SIZE
|
#ifndef LOGBUFFER_SIZE
|
||||||
#define LOGBUFFER_SIZE 80
|
#define LOGBUFFER_SIZE 85
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SYSLOG_ENABLE
|
#ifdef SYSLOG_ENABLE
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#define MAXFLASHSTR 32
|
#define MAXFLASHSTR 32
|
||||||
#define PWDFLASHSTR 16
|
#define PWDFLASHSTR 16
|
||||||
#define EEPROM_SIGNATURE "LHC2"
|
#define EEPROM_SIGNATURE "LHC3"
|
||||||
#define EEPROM_SIGNATURE_LENGTH 4
|
#define EEPROM_SIGNATURE_LENGTH 4
|
||||||
|
|
||||||
//#define EEPROM_offsetJSON IFLASH_PAGE_SIZE
|
//#define EEPROM_offsetJSON IFLASH_PAGE_SIZE
|
||||||
@@ -25,11 +25,13 @@ const char EEPROM_signature[] = EEPROM_SIGNATURE;
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t serialDebugLevel:4;
|
uint8_t serialDebugLevel:4;
|
||||||
uint8_t notGetConfigFromHTTP:1;
|
uint8_t udpDebugLevel:4;
|
||||||
uint8_t udpDebugLevel:3;
|
|
||||||
|
uint8_t notGetConfigFromHTTP:1;
|
||||||
uint8_t notSaveSuccedConfig:1;
|
uint8_t notSaveSuccedConfig:1;
|
||||||
uint8_t dhcpFallback:1;
|
uint8_t dhcpFallback:1;
|
||||||
uint8_t spare2:6;
|
uint8_t spare2:5;
|
||||||
|
|
||||||
uint16_t sysConfigHash;
|
uint16_t sysConfigHash;
|
||||||
};
|
};
|
||||||
} systemConfigFlags;
|
} systemConfigFlags;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ const char on_P[] PROGMEM = "on";
|
|||||||
#define HEAT_P commands_P[CMD_HEAT]
|
#define HEAT_P commands_P[CMD_HEAT]
|
||||||
#define COOL_P commands_P[CMD_COOL]
|
#define COOL_P commands_P[CMD_COOL]
|
||||||
#define AUTO_P commands_P[CMD_AUTO]
|
#define AUTO_P commands_P[CMD_AUTO]
|
||||||
|
#define HEATCOOL_P commands_P[CMD_HEATCOOL]
|
||||||
#define FAN_ONLY_P commands_P[CMD_FAN]
|
#define FAN_ONLY_P commands_P[CMD_FAN]
|
||||||
#define DRY_P commands_P[CMD_DRY]
|
#define DRY_P commands_P[CMD_DRY]
|
||||||
#define HIGH_P commands_P[CMD_HIGH]
|
#define HIGH_P commands_P[CMD_HIGH]
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ long getIntFromStr(char **chan) {
|
|||||||
// chan is pointer to pointer to string
|
// chan is pointer to pointer to string
|
||||||
// Function return first retrived number and move pointer to position next after ','
|
// Function return first retrived number and move pointer to position next after ','
|
||||||
itemCmd getNumber(char **chan) {
|
itemCmd getNumber(char **chan) {
|
||||||
itemCmd val(ST_TENS,CMD_VOID);
|
itemCmd val(ST_VOID,CMD_VOID); //WAS ST_TENS ?
|
||||||
if (chan && *chan && **chan)
|
if (chan && *chan && **chan)
|
||||||
{
|
{
|
||||||
//Skip non-numeric values
|
//Skip non-numeric values
|
||||||
@@ -161,8 +161,8 @@ itemCmd getNumber(char **chan) {
|
|||||||
if (isDigit(*(fractptr+i))) fractnumbers += constrain(*(fractptr+i)-'0',0,9);
|
if (isDigit(*(fractptr+i))) fractnumbers += constrain(*(fractptr+i)-'0',0,9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!fractlen && !intlen) return val; //VOID
|
||||||
if (!fractlen) val.Int((int32_t) atol(*chan));
|
if (!fractlen) val.Int(atol(*chan));
|
||||||
else if (fractlen<=TENS_FRACT_LEN && intlen+TENS_FRACT_LEN<=9)
|
else if (fractlen<=TENS_FRACT_LEN && intlen+TENS_FRACT_LEN<=9)
|
||||||
{
|
{
|
||||||
long intpart = atol(*chan);
|
long intpart = atol(*chan);
|
||||||
@@ -626,7 +626,7 @@ RebootFunc();
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo)
|
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo)
|
||||||
{
|
{
|
||||||
uint32_t endTime;
|
uint32_t endTime;
|
||||||
@@ -638,7 +638,19 @@ bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t m
|
|||||||
return ((currTime>endTime) && (currTime <timestamp)) ||
|
return ((currTime>endTime) && (currTime <timestamp)) ||
|
||||||
((timestamp<endTime) && ((currTime>endTime) || (currTime <timestamp)));
|
((timestamp<endTime) && ((currTime>endTime) || (currTime <timestamp)));
|
||||||
}
|
}
|
||||||
//millis() - tmr1 >= MY_PERIOD
|
*/
|
||||||
|
|
||||||
|
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo)
|
||||||
|
{
|
||||||
|
uint32_t elapsed;
|
||||||
|
if (!time) return true;
|
||||||
|
|
||||||
|
if (modulo) elapsed = ((currTime & modulo) - (timestamp & modulo)) & modulo ;
|
||||||
|
else elapsed = currTime - timestamp ;
|
||||||
|
|
||||||
|
return elapsed >= time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -651,15 +663,23 @@ bool executeCommand(aJsonObject* cmd, int8_t toggle)
|
|||||||
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit, aJsonObject* defaultCan)
|
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit, aJsonObject* defaultCan)
|
||||||
//bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
|
//bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
|
||||||
{
|
{
|
||||||
//char * legacyString =NULL;
|
if (!cmd) return false;
|
||||||
aJsonObject *item = NULL;
|
aJsonObject *item = NULL;
|
||||||
aJsonObject *emit = NULL;
|
aJsonObject *emit = NULL;
|
||||||
aJsonObject *can = NULL;
|
aJsonObject *can = NULL;
|
||||||
aJsonObject *icmd = NULL;
|
aJsonObject *icmd = NULL;
|
||||||
aJsonObject *ecmd = NULL;
|
aJsonObject *ecmd = NULL;
|
||||||
char cmdType = 0;
|
char cmdType = 0;
|
||||||
|
if (serialDebugLevel>=LOG_TRACE || udpDebugLevel>=LOG_TRACE)
|
||||||
if (cmd) cmdType = cmd->type;
|
{
|
||||||
|
char* out = aJson.print(cmd);
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
debugSerial<<"Exec:"<<out<<endl;
|
||||||
|
free (out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdType = cmd->type;
|
||||||
|
|
||||||
switch (cmdType)
|
switch (cmdType)
|
||||||
{
|
{
|
||||||
@@ -731,7 +751,7 @@ switch (cmdType)
|
|||||||
else if (_itemCmd.isValue()) suffix = S_SET;
|
else if (_itemCmd.isValue()) suffix = S_SET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//debugSerial<<"EC:"<<emitCommand<<endl;
|
||||||
//debugSerial << F("IN:") << (pin) << F(" : ") <<endl;
|
//debugSerial << F("IN:") << (pin) << F(" : ") <<endl;
|
||||||
if (item) {
|
if (item) {
|
||||||
if (itemCommand)
|
if (itemCommand)
|
||||||
@@ -819,9 +839,9 @@ itemCmd mapInt(int32_t arg, aJsonObject* map)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Same as millis() but never return 0 or -1
|
//Same as millis() but never return 0 or -1
|
||||||
unsigned long millisNZ(uint8_t shift)
|
uint32_t millisNZ(uint8_t shift, uint32_t mask)
|
||||||
{
|
{
|
||||||
unsigned long now = millis()>>shift;
|
uint32_t now = (millis()>>shift) & mask;
|
||||||
if (!now || !(now+1)) now=1;
|
if (!now || !(now+1)) now=1;
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
@@ -991,5 +1011,113 @@ return crcStream.getCRC16();
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char* getStringFromJson(aJsonObject * a, int i)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
|
||||||
|
if (element && element->type == aJson_String) return element->valuestring;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* getStringFromJson(aJsonObject * a, const char * name)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
if (element && element->type == aJson_String) return element->valuestring;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getIntFromJson(aJsonObject * a, int i, long def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return def;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Boolean) return element->valuebool;
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getIntFromJson(aJsonObject * a, const char * name, long def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return def;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Boolean) return element->valuebool;
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getFloatFromJson(aJsonObject * a, int i, float def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return def;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getFloatFromJson(aJsonObject * a, const char * name, float def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return def;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, int n)
|
||||||
|
{
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
{
|
||||||
|
aJsonObject * element = aJson.getArrayItem(a, n);
|
||||||
|
if (!element)
|
||||||
|
{
|
||||||
|
for (int i = aJson.getArraySize(a); i < n; i++)
|
||||||
|
aJson.addItemToArray(a, element = aJson.createNull());
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, const char * name)
|
||||||
|
{
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
{
|
||||||
|
aJsonObject * element = aJson.getObjectItem(a, name);
|
||||||
|
if (!element)
|
||||||
|
{
|
||||||
|
aJson.addNullToObject(a, name);
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma message(VAR_NAME_VALUE(debugSerial))
|
#pragma message(VAR_NAME_VALUE(debugSerial))
|
||||||
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t m
|
|||||||
bool executeCommand(aJsonObject* cmd, int8_t toggle = -1);
|
bool executeCommand(aJsonObject* cmd, int8_t toggle = -1);
|
||||||
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem=NULL, aJsonObject* defaultEmit=NULL, aJsonObject* defaultCan = NULL);
|
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem=NULL, aJsonObject* defaultEmit=NULL, aJsonObject* defaultCan = NULL);
|
||||||
itemCmd mapInt(int32_t arg, aJsonObject* map);
|
itemCmd mapInt(int32_t arg, aJsonObject* map);
|
||||||
unsigned long millisNZ(uint8_t shift=0);
|
uint32_t millisNZ(uint8_t shift=0, uint32_t mask=0xFFFFFFFFUL);
|
||||||
serialParamType str2SerialParam(char * str);
|
serialParamType str2SerialParam(char * str);
|
||||||
String toString(const IPAddress& address);
|
String toString(const IPAddress& address);
|
||||||
bool getPinVal(uint8_t pin);
|
bool getPinVal(uint8_t pin);
|
||||||
@@ -82,6 +82,103 @@ bool checkToken(char * token, char * data);
|
|||||||
bool isProtectedPin(short pin);
|
bool isProtectedPin(short pin);
|
||||||
bool i2cReset();
|
bool i2cReset();
|
||||||
uint16_t getCRC(aJsonObject * in);
|
uint16_t getCRC(aJsonObject * in);
|
||||||
|
char* getStringFromJson(aJsonObject * a, int i);
|
||||||
|
char* getStringFromJson(aJsonObject * a, const char * name);
|
||||||
|
long getIntFromJson(aJsonObject * a, int i, long def = 0);
|
||||||
|
long getIntFromJson(aJsonObject * a, const char * name, long def = 0);
|
||||||
|
float getFloatFromJson(aJsonObject * a, int i, float def = 0.0);
|
||||||
|
float getFloatFromJson(aJsonObject * a, const char * name, float def = 0.0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Get object from array, create if absent and return pointer to object
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, int n, Type def); //set num value if created
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, int n); //just create null object if not find
|
||||||
|
|
||||||
|
// Get object from object by name, create absent find and return pointer to object
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, const char * name, Type def); //set num value if created
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, const char * name); //just create null object if not find
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * setValToJson(aJsonObject * a, int n, Type val);
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * setValToJson(aJsonObject * a, const char * name, Type val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, int n, Type val)
|
||||||
|
{
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
{
|
||||||
|
aJsonObject * element = aJson.getArrayItem(a, n);
|
||||||
|
if (!element)
|
||||||
|
{
|
||||||
|
for (int i = aJson.getArraySize(a); i < n; i++)
|
||||||
|
if (i==n-1)
|
||||||
|
aJson.addItemToArray(a, element = aJson.createItem(val));
|
||||||
|
else aJson.addItemToArray(a, element = aJson.createNull());
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * getCreateObject(aJsonObject * a, const char * name, Type def)
|
||||||
|
{
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
{
|
||||||
|
aJsonObject * element = aJson.getObjectItem(a, name);
|
||||||
|
if (!element)
|
||||||
|
{
|
||||||
|
aJson.addNumberToObject(a, name, def);
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * setValToJson(aJsonObject * a, const char * name, Type val)
|
||||||
|
{
|
||||||
|
aJsonObject * element = getCreateObject(a,name);
|
||||||
|
if (element)
|
||||||
|
switch (element->type)
|
||||||
|
{
|
||||||
|
case aJson_Float: element->valuefloat = val;
|
||||||
|
break;
|
||||||
|
case aJson_NULL: element->type = aJson_Int;
|
||||||
|
case aJson_Int: element->valueint = val;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
aJsonObject * setValToJson(aJsonObject * a, int n, Type val)
|
||||||
|
{
|
||||||
|
aJsonObject * element = getCreateObject(a,n);
|
||||||
|
|
||||||
|
if (element)
|
||||||
|
switch (element->type)
|
||||||
|
{
|
||||||
|
case aJson_Float: element->valuefloat = val;
|
||||||
|
break;
|
||||||
|
case aJson_NULL: element->type = aJson_Int;
|
||||||
|
case aJson_Int: element->valueint =val;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
#include "util/crc16_.h"
|
#include "util/crc16_.h"
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
# usage:
|
|
||||||
# first make your own copy of template
|
|
||||||
# cp build_flags_template.sh my_build_flags.sh
|
|
||||||
# then edit, change or comment something
|
|
||||||
# nano my_build_flags.sh
|
|
||||||
# and source it
|
|
||||||
# source my_build_flags.sh
|
|
||||||
echo "==============================================Custom build flags are:====================================================="
|
|
||||||
export FLAGS="-DMY_CONFIG_SERVER=lazyhome.ru"
|
|
||||||
# export FLAGS="$FLAGS -DWATCH_DOG_TICKER_DISABLE"
|
|
||||||
# export FLAGS="$FLAGS -DUSE_1W_PIN=12"
|
|
||||||
# export FLAGS="$FLAGS -DSD_CARD_INSERTED"
|
|
||||||
export FLAGS="$FLAGS -DSERIAL_BAUD=115200"
|
|
||||||
export FLAGS="$FLAGS -DWiz5500"
|
|
||||||
# export FLAGS="$FLAGS -DDISABLE_FREERAM_PRINT"
|
|
||||||
export FLAGS="$FLAGS -DCUSTOM_FIRMWARE_MAC=de:ad:be:ef:fe:00"
|
|
||||||
# export FLAGS="$FLAGS -DDMX_DISABLE"
|
|
||||||
# export FLAGS="$FLAGS -DMODBUS_DISABLE"
|
|
||||||
# export FLAGS="$FLAGS -DOWIRE_DISABLE"
|
|
||||||
# export FLAGS="$FLAGS -DAVR_DMXOUT_PIN=18"
|
|
||||||
export FLAGS="$FLAGS -DLAN_INIT_DELAY=500"
|
|
||||||
# export FLAGS="$FLAGS -DCONTROLLINO"
|
|
||||||
export PLATFORMIO_BUILD_FLAGS="$FLAGS"
|
|
||||||
echo PLATFORMIO_BUILD_FLAGS=$PLATFORMIO_BUILD_FLAGS
|
|
||||||
echo "==============================================Custom build flags END====================================================="
|
|
||||||
unset FLAGS
|
|
||||||
106
platformio.ini
106
platformio.ini
@@ -114,9 +114,12 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
; br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
TimerInterrupt_Generic
|
TimerInterrupt_Generic
|
||||||
d00616/arduino-NVM @ ^0.9.1
|
d00616/arduino-NVM @ ^0.9.1
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -165,10 +168,9 @@ lib_deps =
|
|||||||
https://github.com/anklimov/pubsubclient.git
|
https://github.com/anklimov/pubsubclient.git
|
||||||
Streaming
|
Streaming
|
||||||
;ESP_EEPROM
|
;ESP_EEPROM
|
||||||
;https://github.com/anklimov/NRFFlashStorage
|
|
||||||
Adafruit Unified Sensor
|
Adafruit Unified Sensor
|
||||||
DHT sensor library for ESPx
|
DHT sensor library for ESPx
|
||||||
https://github.com/anklimov/Artnet.git
|
;https://github.com/anklimov/Artnet.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||||
https://github.com/anklimov/DS2482_OneWire
|
https://github.com/anklimov/DS2482_OneWire
|
||||||
@@ -176,16 +178,19 @@ lib_deps =
|
|||||||
FastLED@3.3.2
|
FastLED@3.3.2
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
;SparkFun CCS811 Arduino Library
|
;SparkFun CCS811 Arduino Library
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
;sparkfun/SparkFun CCS811 Arduino Library@~1.0.7
|
||||||
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
M5Stack
|
M5Stack
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
;Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
; br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -193,8 +198,9 @@ monitor_speed = 115200
|
|||||||
platform = espressif32
|
platform = espressif32
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
;build_type = debug
|
build_type = debug
|
||||||
board = esp32-evb
|
board = upesy_wroom
|
||||||
|
board_build.partitions = min_spiffs.csv
|
||||||
extra_scripts = extra_script.py
|
extra_scripts = extra_script.py
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -248,17 +254,19 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ESP-Dmx
|
https://github.com/anklimov/ESP-Dmx
|
||||||
FastLED@3.3.2
|
FastLED@3.3.2
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;ESPmDNS
|
;ESPmDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/arduino-CAN.git
|
https://github.com/anklimov/arduino-CAN.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
[env:due]
|
[env:due]
|
||||||
;Experimental target with universal Ethernet Library
|
;Experimental target with universal Ethernet Library
|
||||||
@@ -317,17 +325,20 @@ lib_deps =
|
|||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
Streaming
|
Streaming
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
;sparkfun/SparkFun CCS811 Arduino Library@~1.0.7
|
||||||
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
rweather/Crypto
|
rweather/Crypto
|
||||||
collin80/can_common
|
collin80/can_common
|
||||||
collin80/due_can
|
collin80/due_can
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
[env:mega2560slim]
|
[env:mega2560slim]
|
||||||
@@ -389,9 +400,12 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -458,32 +472,34 @@ lib_deps =
|
|||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
Streaming
|
Streaming
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
rweather/Crypto
|
rweather/Crypto
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
|
||||||
[env:mega2560-5500]
|
[env:mega2560]
|
||||||
platform = atmelavr
|
platform = atmelavr
|
||||||
board = megaatmega2560
|
board = megaatmega2560
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
framework = arduino
|
framework = arduino
|
||||||
build_flags = !python get_build_flags.py mega2560-5500
|
build_flags = !python get_build_flags.py mega2560
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
;DS2482_OneWire //UNCOMMENT for software 1-wire driver
|
;DS2482_OneWire //UNCOMMENT for software 1-wire driver
|
||||||
DHT sensor library for ESPx
|
DHT sensor library for ESPx
|
||||||
DmxDue
|
DmxDue
|
||||||
DueFlashStorage
|
DueFlashStorage
|
||||||
WifiManager
|
WifiManager
|
||||||
Ethernet
|
;Ethernet
|
||||||
Ethernet3
|
Ethernet3
|
||||||
Ethernet5100
|
Ethernet5100
|
||||||
HTTPClient
|
HTTPClient
|
||||||
@@ -501,7 +517,7 @@ lib_deps =
|
|||||||
https://github.com/anklimov/CmdArduino
|
https://github.com/anklimov/CmdArduino
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
https://github.com/anklimov/DMXSerial
|
https://github.com/anklimov/DMXSerial
|
||||||
https://github.com/anklimov/Ethernet2
|
https://github.com/anklimov/Ethernet.git
|
||||||
https://github.com/anklimov/pubsubclient.git
|
https://github.com/anklimov/pubsubclient.git
|
||||||
https://github.com/anklimov/Artnet.git
|
https://github.com/anklimov/Artnet.git
|
||||||
FastLED@3.3.2
|
FastLED@3.3.2
|
||||||
@@ -510,20 +526,25 @@ lib_deps =
|
|||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
Streaming
|
Streaming
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
https://github.com/anklimov/ArduinoOTA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[env:esp8266-wifi]
|
[env:esp8266-wifi]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
monitor_filters = esp8266_exception_decoder
|
||||||
|
build_type = debug
|
||||||
;board = nodemcuv2
|
;board = nodemcuv2
|
||||||
;esp12e ESP8266 80MHz 4MB 80KB Espressif ESP8266 ESP-12E
|
;esp12e ESP8266 80MHz 4MB 80KB Espressif ESP8266 ESP-12E
|
||||||
;esp01_1m ESP8266 80MHz 1MB 80KB Espressif Generic ESP8266 ESP-01 1M
|
;esp01_1m ESP8266 80MHz 1MB 80KB Espressif Generic ESP8266 ESP-01 1M
|
||||||
@@ -606,15 +627,17 @@ lib_deps =
|
|||||||
Streaming
|
Streaming
|
||||||
ESP_EEPROM
|
ESP_EEPROM
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA.git
|
https://github.com/anklimov/ArduinoOTA.git
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;MDNS
|
;MDNS
|
||||||
ESP8266mDNS
|
ESP8266mDNS
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
[env:mega2560-5100]
|
[env:mega2560-5100]
|
||||||
@@ -659,14 +682,16 @@ lib_deps =
|
|||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
Streaming
|
Streaming
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -725,18 +750,20 @@ lib_deps =
|
|||||||
Streaming
|
Streaming
|
||||||
https://github.com/livello/PrintEx#is-select-redecl
|
https://github.com/livello/PrintEx#is-select-redecl
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/rlogiacco/CircularBuffer
|
https://github.com/rlogiacco/CircularBuffer
|
||||||
rweather/Crypto
|
rweather/Crypto
|
||||||
https://github.com/collin80/due_can.git
|
https://github.com/collin80/due_can.git
|
||||||
https://github.com/collin80/can_common.git
|
https://github.com/collin80/can_common.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
[env:controllino]
|
[env:controllino]
|
||||||
@@ -778,15 +805,17 @@ lib_deps =
|
|||||||
Streaming
|
Streaming
|
||||||
https://github.com/livello/PrintEx#is-select-redecl
|
https://github.com/livello/PrintEx#is-select-redecl
|
||||||
ClosedCube HDC1080
|
ClosedCube HDC1080
|
||||||
SparkFun CCS811 Arduino Library@~1.0.7
|
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library#v1.0.7
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -841,10 +870,12 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
@@ -909,12 +940,12 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
|
||||||
@@ -978,12 +1009,15 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
; ArduinoMDNS
|
; ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
pazi88/STM32_CAN
|
pazi88/STM32_CAN
|
||||||
ericksimoes/Ultrasonic
|
ericksimoes/Ultrasonic
|
||||||
|
https://github.com/mathertel/RotaryEncoder
|
||||||
|
;TimerInterrupt_Generic
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
|
||||||
<script>
|
|
||||||
function post_cmd(endpoint, param) {
|
|
||||||
var username = $("input#login").val();
|
|
||||||
var password = $("input#password").val();
|
|
||||||
var surl = $("input#url").val();
|
|
||||||
|
|
||||||
var settings = {
|
|
||||||
"url": surl+endpoint,
|
|
||||||
//"http://192.168.11.234:65280"+endpoint,
|
|
||||||
"method": "POST",
|
|
||||||
beforeSend: function (xhr) {
|
|
||||||
xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
|
|
||||||
xhr.setRequestHeader ("Pragma", "no-cache");
|
|
||||||
//xhr.withCredentials = true;
|
|
||||||
},
|
|
||||||
"timeout": 20000,
|
|
||||||
"headers": {
|
|
||||||
"Content-Type": "text/plain"
|
|
||||||
},
|
|
||||||
"data": param+"\n",
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajax(settings).done(function (response) {
|
|
||||||
document.getElementById("resp").innerHTML = response;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<h1>LazyHome PWA </h1>
|
|
||||||
<form name="cookieform" id="loginform">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>URL:<td><input type="text" name="url" id="url" value="" class="text"/>
|
|
||||||
<tr>
|
|
||||||
<td>Login: <td><input type="text" name="login" id="login" value="arduino" class="text"/>
|
|
||||||
<td>Password: <td> <input type="text" name="password" id="password" value="password" class="text"/>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><button onclick='post_cmd("/item/relays/cmd","toggle")'>Toggle</button>
|
|
||||||
<td><button onclick='post_cmd("/command/save","")'>Save</button>
|
|
||||||
<td><button onclick='post_cmd("/command/reboot","")'>Reboot</button>
|
|
||||||
<td><button onclick='post_cmd("/command/get,"")'>Get</button>
|
|
||||||
<td><button onclick='post_cmd("/command/load","")'>Load</button>
|
|
||||||
<tr>
|
|
||||||
<td>item:<td><input type="text" name="item" id="item" value="" class="text"/>
|
|
||||||
<td>command:<td><input type="text" name="command" id="command" value="toggle" class="text"/>
|
|
||||||
<td><button onclick='post_cmd("/item/"+$("input#item").val(),$("input#command").val())'>Exec</button>
|
|
||||||
</table>
|
|
||||||
<p id="resp"></p>
|
|
||||||
302
savedconf.json
302
savedconf.json
@@ -1,302 +0,0 @@
|
|||||||
{
|
|
||||||
"mqtt":["edem3","192.168.88.2"],
|
|
||||||
"syslog":["192.168.88.2"],
|
|
||||||
"dmx":[3,80],
|
|
||||||
"topics":{"root":"edem"},
|
|
||||||
"items":
|
|
||||||
{
|
|
||||||
"lightall":[7,[
|
|
||||||
"lampbedr3",
|
|
||||||
"lampcab31",
|
|
||||||
"lampcab32",
|
|
||||||
"lampsauna3",
|
|
||||||
"lampbath33",
|
|
||||||
"lampktc3",
|
|
||||||
"lampwc3",
|
|
||||||
"lamp4",
|
|
||||||
"lampext4",
|
|
||||||
"lamphall3",
|
|
||||||
"lampstw3",
|
|
||||||
"fasadeast",
|
|
||||||
"bra31",
|
|
||||||
"lampgst3",
|
|
||||||
"lampkln3",
|
|
||||||
"lampbalk3",
|
|
||||||
"fasadsouth",
|
|
||||||
"bra32"]],
|
|
||||||
"gr_hall3":[7,["lamphall3","lampstw3"]],
|
|
||||||
"gr_gost3":[7,["lampgst3","lampktc3"]],
|
|
||||||
"relays":[7,["pout0","thermostat","pout2","pout3","pout4","pout5","pout6"]],
|
|
||||||
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]],
|
|
||||||
|
|
||||||
"mb1":[44,[1,0,3,100]],
|
|
||||||
"mb2":[44,[1,1,3,100]],
|
|
||||||
"mb3":[44,[1,2,3,100]],
|
|
||||||
"mb4":[44,[1,3,3,100]],
|
|
||||||
"mba":[44,[96,0,0]],
|
|
||||||
"lamp_zal":[4,[1,60001,-1,255]],
|
|
||||||
|
|
||||||
"lampbedr3":[0,1],
|
|
||||||
"lampcab31":[0,2],
|
|
||||||
"lampcab32":[0,3],
|
|
||||||
|
|
||||||
"lampsauna3":[0,4],
|
|
||||||
"lampbath3":[0,5],
|
|
||||||
"lampwc3":[0,6],
|
|
||||||
|
|
||||||
"lampktc3":[0,7],
|
|
||||||
"lamp4":[0,8],
|
|
||||||
"lamphall3":[0,9],
|
|
||||||
|
|
||||||
"lampext4":[0,10],
|
|
||||||
"lampstw3":[0,11],
|
|
||||||
"fasadeast":[0,12],
|
|
||||||
|
|
||||||
"lampgst3":[0,13],
|
|
||||||
"bra31":[0,14],
|
|
||||||
"bra32":[0,15],
|
|
||||||
|
|
||||||
"lampbalk3":[0,16],
|
|
||||||
"fasadsouth":[0,17],
|
|
||||||
"lampkln3":[0,18],
|
|
||||||
"lampbar3":[0,21],
|
|
||||||
|
|
||||||
"ledbedr3":[1,22],
|
|
||||||
"ledcab31":[1,26],
|
|
||||||
"ledcab32":[1,30],
|
|
||||||
"ledkab":[7,["ledcab31","ledcab32"]],
|
|
||||||
"ledsauna31":[1,34],
|
|
||||||
"ledsauna32":[1,38],
|
|
||||||
"ledsauna":[7,["ledsauna31","ledsauna32"]],
|
|
||||||
"led4":[1,42],
|
|
||||||
|
|
||||||
"ledktc31":[1,48],
|
|
||||||
"ledktc31w":[0,52],
|
|
||||||
"ledktc32":[1,53],
|
|
||||||
"ledktc32w":[0,57],
|
|
||||||
"ledgst31":[1,58],
|
|
||||||
"ledgst31w":[0,62],
|
|
||||||
"ledgst32":[1,63],
|
|
||||||
"ledgst32w":[0,67],
|
|
||||||
"ledktc3w":[7,["ledktc31w","ledktc32w","ledgst31w","ledgst32w"]],
|
|
||||||
"ledktc3":[7,["ledktc31","ledktc32","ledgst31","ledgst32"]],
|
|
||||||
|
|
||||||
"fanbath3":[0,68],
|
|
||||||
"fanwc3":[0,69],
|
|
||||||
|
|
||||||
"pout0":[6,22],
|
|
||||||
"thermostat":[5,23,33],
|
|
||||||
"pout2":[6,24],
|
|
||||||
"water3":[6,25],
|
|
||||||
"pout4":[3,9],
|
|
||||||
"pout5":[3,8],
|
|
||||||
"pout6":[3,11],
|
|
||||||
"pout7":[6,12],
|
|
||||||
|
|
||||||
|
|
||||||
"pwm0" :[3,4],
|
|
||||||
"pwm1" :[3,5],
|
|
||||||
"pwm2" :[3,6],
|
|
||||||
"pwm3" :[3,7],
|
|
||||||
"pwm10":[3,10],
|
|
||||||
|
|
||||||
|
|
||||||
"unprot0":[6,33],
|
|
||||||
"unprot1":[6,32],
|
|
||||||
"unprot2":[6,31],
|
|
||||||
"unprot3":[6,30],
|
|
||||||
"unprot4":[6,29],
|
|
||||||
"unprot5":[6,28],
|
|
||||||
"unprot6":[6,27],
|
|
||||||
"unprot7":[6,26]
|
|
||||||
},
|
|
||||||
|
|
||||||
"in":
|
|
||||||
[ {"#":42,"emit":"power3","item":"fanwc3"},
|
|
||||||
{"#":44,"emit":"in1"},
|
|
||||||
{"#":46,"emit":"in2"},
|
|
||||||
{"#":49,"emit":"in3"},
|
|
||||||
{"#":43,"emit":"in4"},
|
|
||||||
{"#":45,"emit":"in5"},
|
|
||||||
{"#":47,"emit":"in6"},
|
|
||||||
{"#":48,"emit":"in7"},
|
|
||||||
{"#":34,"emit":"in8"},
|
|
||||||
{"#":36,"emit":"in9"},
|
|
||||||
|
|
||||||
{"#":38,"T":0,
|
|
||||||
"click":{"item":"gr_hall3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"REST"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{"#":40,"T":0,
|
|
||||||
"click":{"item":"gr_hall3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"HALT"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%-2"}
|
|
||||||
},
|
|
||||||
{"#":35,"T":0,
|
|
||||||
"click":{"item":"gr_gost3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"ON"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{"#":37,"T":0,
|
|
||||||
"click":{"item":"gr_gost3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"OFF"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
|
|
||||||
},
|
|
||||||
|
|
||||||
{"#":39,"emit":"in14"},
|
|
||||||
{"#":41,"emit":"in15"},
|
|
||||||
|
|
||||||
{"#":54,"T":0,"act":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"map":[128,640],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"ON"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map":[641,1024],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"OFF"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
{"#":55,"T":66,"emit":"a01","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
{"#":56,"T":66,"emit":"a02","map":[0,1024,0,1024,10]},
|
|
||||||
{"#":57,"T":66,"emit":"a03","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
{"#":58,"T":66,"emit":"a04","map":[0,1024,0,1024,10]},
|
|
||||||
{"#":59,"T":66,"emit":"a05","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
{"#":60,"T":0,"act":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"map":[128,640],
|
|
||||||
"click":{"item":"gr_hall3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"REST"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map":[641,1024],
|
|
||||||
"click":{"item":"gr_hall3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"HALT"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%-2"}
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
{"#":61,"T":0,"act":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"map":[128,640],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"ON"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map":[641,1024],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"OFF"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
|
|
||||||
{"#":62,"T":66,"emit":"a08","map":[0,1024,0,1024,10]},
|
|
||||||
{"#":63,"T":66,"emit":"a09","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
{"#":64,"T":66,"emit":"a10","map":[0,1024,0,1024,10]},
|
|
||||||
{"#":65,"T":66,"emit":"a11","map":[0,1024,0,1024,10]},
|
|
||||||
{"#":66,"T":0,"emit":"leak31","item":"water3","scmd":"OFF","rcmd":"ON"},
|
|
||||||
{"#":67,"T":2,"emit":"leak32","item":"water3","scmd":"OFF","rcmd":"ON"},
|
|
||||||
{"#":68,"T":0,"emit":"leak33","item":"water3","scmd":"OFF","rcmd":"ON"},
|
|
||||||
{"#":69,"T":0,"emit":"a15"}
|
|
||||||
],
|
|
||||||
|
|
||||||
"in2":
|
|
||||||
{ "42":{"emit":"power3","item":"fanwc3"},
|
|
||||||
"44":{"emit":"in1"},
|
|
||||||
"46":{"emit":"in2"},
|
|
||||||
"49":{"emit":"in3"},
|
|
||||||
"43":{"emit":"in4"},
|
|
||||||
"45":{"emit":"in5"},
|
|
||||||
"47":{"emit":"in6"},
|
|
||||||
"48":{"emit":"in7"},
|
|
||||||
"34":{"emit":"in8"},
|
|
||||||
"36":{"emit":"in9"},
|
|
||||||
|
|
||||||
"38":{"T":0,
|
|
||||||
"click":{"item":"gr_hall3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"REST"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
"40":{"T":0,
|
|
||||||
"click":{"item":"gr_hall3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampbedr3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lightall","icmd":"HALT"},
|
|
||||||
"rpcmd":{"item":"gr_hall3","icmd":"%-2"}
|
|
||||||
},
|
|
||||||
"35":{"T":0,
|
|
||||||
"click":{"item":"gr_gost3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"ON"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
"37":{"T":0,
|
|
||||||
"click":{"item":"gr_gost3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"OFF"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
|
|
||||||
},
|
|
||||||
|
|
||||||
"39":{"emit":"in14"},
|
|
||||||
"41":{"emit":"in15"},
|
|
||||||
|
|
||||||
"54":{"addr":54,"T":0,"act":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"map":[128,640],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"ON"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"ON"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"ON"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map":[641,1024],
|
|
||||||
"click":{"item":"gr_gost3","icmd":"OFF"},
|
|
||||||
"dclick":{"item":"lampwc3","icmd":"OFF"},
|
|
||||||
"tclick":{"item":"lampbath3","icmd":"OFF"},
|
|
||||||
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
|
|
||||||
}
|
|
||||||
]},
|
|
||||||
"55":{"T":66,"emit":"a01","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
"56":{"T":66,"emit":"a02","map":[0,1024,0,1024,10]},
|
|
||||||
"57":{"T":66,"emit":"a03","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
"58":{"T":66,"emit":"a04","map":[0,1024,0,1024,10]},
|
|
||||||
"59":{"T":66,"emit":"a05","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
"60":{"T":66,"emit":"a06","map":[0,1024,0,1024,10]},
|
|
||||||
"61":{"T":66,"emit":"a07","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
"62":{"T":66,"emit":"a08","map":[0,1024,0,1024,10]},
|
|
||||||
"63":{"T":66,"emit":"a09","map":[0,1024,0,1024,10]},
|
|
||||||
|
|
||||||
"64":{"T":66,"emit":"a10","map":[0,1024,0,1024,10]},
|
|
||||||
"65":{"T":66,"emit":"a11","map":[0,1024,0,1024,10]},
|
|
||||||
"66":{"T":0,"emit":"leak31","item":"water3","scmd":"OFF","rcmd":"ON"},
|
|
||||||
"67":{"T":2,"emit":"leak32","item":"water3","scmd":"OFF","rcmd":"ON"},
|
|
||||||
"68":{"T":0,"emit":"leak33","item":"water3","scmd":"OFF","rcmd":"ON"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user