Merge branch 'develop'

CORE changes:

CORE refactored.
Config persistence (saving parameters & config) - now working for Mega, DUE, ESP8266, ESP32.
Config auto-saving to flash on portal changes (http ETAG supported to version control).
HTTP API & tiny web interface (external by CORS)
MDNS controller announcing
Local config changing by web
Delayed commands (/del suffix)
NO_MQTT option
input polling on timer interrupts (DUE)
Device driver changes

PID regulator (13 type)
Relay PWM thermostat (16 type)
RGBWW channel type (17 type) & color temperature set
Legacy modbus (4 type) improvement (retry speedup, mask = 3 & 4 for swap hi & lo bytes)
Multivent driver (18 type)
UART bridge (15 type) (serial protocol interceptor) - wireshark udpdump compatible
Artnet - to DMX configuration (channel range to pass throw)
PWM driver (3 type) - RBGW compatible
Misc

flashing scripts for DUE
Platformio target for OTA (invoke OTA scripts from custom_builds)
Clean-up & optimisation
This commit is contained in:
2022-01-05 12:09:40 +03:00
127 changed files with 19653 additions and 31161 deletions

5
.gitignore vendored
View File

@@ -19,3 +19,8 @@ custom-build-flags/build_flags_nrf52840
.vscode/.browse.c_cpp.db
.vscode/c_cpp_properties.json
.vscode/launch.json
lighthub/modules/out_elevator.cpp
lighthub/modules/out_elevator.h
spare_files/*
spare_files/ArduinoOTA/*
lib/*

View File

@@ -2,3 +2,5 @@
-DCUSTOM_FIRMWARE_MAC=de:ad:be:ef:fe:07
-DWiz5100
#-DPID_DISABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"

View File

@@ -1,9 +1,17 @@
#-DW5500_CS_PIN=53
-DDMX_SMOOTH
-DSYSLOG_ENABLE
-DMODBUS_DIMMER_PARAM=SERIAL_8E1
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1
-DARTNET_ENABLE
-DOTA
-DSTATUSLED
#-DPID_DISABLE
#-DUARTBRIDGE_ENABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DMCP23017
-DCORS=\"http://lazyhome.ru\"
-DTIMER_INT
-DRESTART_LAN_ON_MQTT_ERRORS
-DOTA_PORT=80

View File

@@ -1,6 +0,0 @@
-DARTNET_ENABLE
-DDMX_SMOOTH
-DSTATUSLED
-DSYSLOG_ENABLE
-DWiz5100
#-DPID_DISABLE

View File

@@ -1,6 +0,0 @@
-DWiz5500
-DARTNET_ENABLE
-DDMX_SMOOTH
-DSTATUSLED
-DSYSLOG_ENABLE
#-DPID_DISABLE

View File

@@ -6,11 +6,45 @@
-DMODBUS_DISABLE
#-DMBUS_DISABLE
-DCOUNTER_DISABLE
#-DSYSLOG_ENABLE - udp errors
-DSYSLOG_ENABLE
# - udp errors
-DOTA
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
#- ArduinoMDNS didnt working
-DMCP23017
-DMODBUS_TX_PIN=13
#-DARTNET_ENABLE - udp rx errors ((
#-DUSE_1W_PIN=16
#-DW5500_CS_PIN=15
#-DPID_DISABLE
#Define pins for modbus UART Serial1. Default - 9/10 is utilized by ESP flash
#-DMODBUS_UART_RX_PIN=15
#-DMODBUS_UART_TX_PIN=2
#-DmodbusSerial=Serial1
#-DMODBUS_DEBUG
# Use default pins for modbus UART
#-DMODBUS_UART_RX_PIN=-1
#-DMODBUS_UART_TX_PIN=-1
# Example of UARTBRIDGE configuration
#-DUARTBRIDGE_ENABLE
#-DMODULE_UATRBRIDGE_UARTA=Serial1
#-DMODULE_UATRBRIDGE_UARTA_RX_PIN=15
#-DMODULE_UATRBRIDGE_UARTA_TX_PIN=2
#-DMODULE_UATRBRIDGE_UARTB=Serial2
#-DMODULE_UATRBRIDGE_UARTB_RX_PIN=-1
#-DMODULE_UATRBRIDGE_UARTB_TX_PIN=-1
#-DAUTOCONNECT_RECONNECT_WAITTIME=60
-DFS_STORAGE
-DFS_PREPARE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -8,3 +8,14 @@
-DUSE_1W_PIN=16
-DW5500_CS_PIN=15
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DWM_MDNS
-DMCP23017
-DFS_STORAGE
-DFS_PREPARE
-DRESTART_LAN_ON_MQTT_ERRORS
#-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -9,3 +9,22 @@
-DSTATUSLED
-DMCP23017
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DTIMER_INT
#Put modbus exchange in debug hex dump
#-DMODBUS_DEBUG
#Uncomment next 3 lines (or add it to custom build flags) to use Native USB port for debug/CLI instead Serial
#-DdebugSerialPort=SerialUSB
#-DSerialPortType=Serial_
#-DSERIAL_BAUD=0
#Default SerialDebug settings
#-DSERIAL_BAUD=115200
#-DdebugSerialPort=Serial
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -10,3 +10,14 @@
#-DSYSLOG_ENABLE
-DUSE_1W_PIN=16
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DMCP23017
-DFS_STORAGE
-DFS_PREPARE
-DOTA
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -1,5 +1,11 @@
-DMODBUS_DIMMER_PARAM=SERIAL_8E1
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1
-DAVR_DMXOUT_PIN=18
-DSYSLOG_ENABLE
-DWiz5100
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -1,5 +1,11 @@
-DWiz5500
-DMODBUS_DIMMER_PARAM=SERIAL_8E1
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1
-DAVR_DMXOUT_PIN=18
-DSYSLOG_ENABLE
#-DPID_DISABLE
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80

View File

@@ -0,0 +1,27 @@
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1
#-DAVR_DMXOUT_PIN=18
-DDMX_DISABLE
-DMODBUS_DISABLE
-DMBUS_DISABLE
-DOWIRE_DISABLE
-DDHT_DISABLE
-DCOUNTER_DISABLE
-DNO_HOMIE
-DCSSHDC_DISABLE
-DSPILED_DISABLE
#-DAC_DISABLE
-DSYSLOG_ENABLE
-DPID_DISABLE
-DOTA
-DMOTOR_DISABLE
#-DWiz5100
-DARDUINO_OTA_MDNS_DISABLE
#-DMDNS_ENABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
# Example of UARTBRIDGE configuration
#-DUARTBRIDGE_ENABLE
-DOTA_PORT=80

View File

@@ -13,3 +13,17 @@
-DAC_DISABLE
-DSYSLOG_ENABLE
-DPID_DISABLE
-DWiz5100
-DMOTOR_DISABLE
-DOTA
-DARDUINO_OTA_MDNS_DISABLE
#-DMDNS_ENABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"http://lazyhome.ru\"
-DOTA_PORT=80
-DHSV_DISABLE
-DMULTIVENT_DISABLE
-DPID_DISABLE
-DPWM_DISABLE
-DSPILED_DISABLE
-DOW_DEVICES_LIMIT=17

View File

@@ -1,4 +1,4 @@
-DWiz5500
#-DWiz5500
#-DW5500_CS_PIN=10
-DDMX_DISABLE
-DMODBUS_DISABLE
@@ -12,3 +12,5 @@
-DSYSLOG_ENABLE
-DMBUS_DISABLE
-DPID_DISABLE
#-DMCP23017

View File

@@ -0,0 +1,23 @@
-DDMX_DISABLE
-DMODBUS_DISABLE
-DMBUS_DISABLE
-DOWIRE_DISABLE
-DDHT_DISABLE
-DCOUNTER_DISABLE
-DNO_HOMIE
-DCSSHDC_DISABLE
-DSPILED_DISABLE
-DAC_DISABLE
-DPID_DISABLE
-DdebugSerialPort=SerialUSB
-DSerialPortType=USBSerial
-DSERIAL_BAUD=0
-DPIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-DUSBCON
#-DUSBD_VID=0x0483
#-DUSBD_PID=0x5740
#-DUSB_MANUFACTURER="Unknown"
#-DUSB_PRODUCT="\"BLUEPILL_F103C8\""
#-DHAL_PCD_MODULE_ENABLED
#-D USBD_USE_CDC

View File

@@ -9,3 +9,4 @@
-DSPILED_DISABLE
-DAC_DISABLE
-DPID_DISABLE
-DUIPETHERNET

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
{
"syslog":["192.168.88.2"],
"mqtt":["elev","192.168.88.22"],
"dmx":[30],
"items": {
"relay1":[6,32],
"relay2":[6,33],
"relays":[7,["relay1","relay2"]],
"sensair1":[44,[254,
"sensair",
{"co2":{"emit":"co2"}},
{"mode":"auto"}
]
],
"elevator":[15,{"baud":9600,"serial":"8N1"]
},
"modbus":
{
"sensair":{"baud":9600,
"poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"outStat":{"ir":0},
"pwm":{"ir":21},
"typeid":{"ir":25,"type":"u32"},
"mapver":{"ir":27},
"fwver":{"ir":28},
"sensorid":{"ir":29,"type":"u32"},
"ack":{"reg":0},
"command":{"reg":1},
"abc":{"reg":31}
}
}
},
"in":{ "23":{"item":"relays","emit":"in1"},
"25":{"item":"relays","emit":"in2"},
"27":{"item":"relays","emit":"in3"},
"29":{"item":"relays","emit":"in4"}
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
../tools/mac/arduinoOTA -d -address 192.168.88.70 -port 65280 -username arduino -password password -b /config

View File

@@ -0,0 +1 @@
../tools/mac/arduinoOTA -address elev.local -port 65280 -username arduino -password password -sketch config.json -b -upload /config.json

View File

@@ -1 +1 @@
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch

View File

@@ -0,0 +1 @@
../tools/mac/arduinoOTA -address 192.168.11.213 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch

View File

@@ -0,0 +1,61 @@
:020000023000CC
:10FC000002C0EFC037C1112484B7882369F0982F50
:10FC10009A70923049F081FF02C097EF94BF282E6E
:10FC200080E002D10C94000085E08093810082E0A6
:10FC30008093C00088E18093C1008CE08093C40071
:10FC400086E08093C2008EE0EFD0279A84E023EC18
:10FC50003FEF91E0309385002093840096BBB09BEA
:10FC6000FECF1F9AA8954091C00047FD02C0815069
:10FC700089F7CED0813479F4CBD0C82FDBD0C2380D
:10FC800011F480E004C088E0C13809F083E0B9D005
:10FC900080E1B7D0EECF823419F484E1D3D0F8CF2D
:10FCA000853411F485E0FACF853581F4B1D0E82EA2
:10FCB000AFD0F82E87FF07C08BB781608BBFEE0CEB
:10FCC000FF1CB8D0E5CF8BB78E7FF8CF863579F49F
:10FCD0009FD08D3451F49CD0CBB79AD0C170880F8F
:10FCE0008C2B8BBF81E0AED0CCCF83E0FCCF8436B1
:10FCF00009F046C08DD0C82FD0E0DC2FCC2788D0AB
:10FD0000C82B86D0D82E5E018EEFB81A00E012E024
:10FD10004801EFEF8E1A9E0A7BD0F80180838401A0
:10FD20008A149B04A9F786D0F5E410E000E0DF1602
:10FD300009F150E040E063E0C70153D08701C12CD6
:10FD400092E0D92EF601419151916F0161E0C80115
:10FD500048D00E5F1F4F2297A9F750E040E065E0C2
:10FD6000C7013FD095CF6081C8018E0D9F1D01D185
:10FD70000F5F1F4FF801FE5FC017D107A1F788CFB3
:10FD8000843701F545D0C82FD0E0DC2FCC2740D0F8
:10FD9000C82B3ED0D82E4ED08701F5E4DF120BC021
:10FDA000CE0DDF1DC801DDD02CD00F5F1F4FC01757
:10FDB000D107C1F76DCFF80187918F0122D021972C
:10FDC000D1F766CF853739F435D08EE11AD088E97E
:10FDD00018D081E05CCF813509F073CF88E024D062
:10FDE00070CFFC010A0167BFE895112407B600FC3B
:10FDF000FDCF667029F0452B19F481E187BFE895A6
:10FE000008959091C00095FFFCCF8093C60008959F
:10FE10008091C00087FFFCCF8091C00084FD01C0AD
:10FE2000A8958091C6000895E0E6F0E098E19083FF
:10FE300080830895EDDF803219F088E0F5DFFFCF91
:10FE400084E1DFCFCF93C82FE3DFC150E9F7CF9133
:10FE5000F1CFCF92DF92EF92FF92DC01CB01642FC2
:10FE60006D01EE24FF24CBBEA901FF90EF90DF903F
:10FE7000CF90B7CF2F923F924F925F926F927F9227
:10FE80008F929F92AF92BF92CF92DF92EF92FF92AA
:10FE90000F931F93CF93DF9300D0CDB7DEB7180138
:10FEA000E9826B017C0110E000E029013A014C1865
:10FEB0005D086E087F0846015701840C951CA61C3E
:10FEC000B71C0215130531F489818823A1F188E05C
:10FED000ABDFFFCF30E020E043E0C701B601B9DF80
:10FEE00080E890E09B838A83ABBEF4012791369132
:10FEF000C501B401641975098609970941E0A9DFB4
:10FF00008A819B8101979B838A8392E0890E911C51
:10FF1000A11CB11C8A819B81892B31F730E020E044
:10FF200045E0C701B60195DF9FEFD91AE90AF90A42
:10FF30000F5F1F4FC0CF0F900F900F90DF91CF91A9
:10FF40001F910F91FF90EF90DF90CF90BF90AF90F7
:10FF50009F908F907F906F905F904F903F902F90E9
:10FF60000895F999FECF92BD81BDF89A992780B581
:10FF70000895262FF999FECF1FBA92BD81BD20BDED
:0EFF80000FB6F894FA9AF99A0FBE01960895FA
:02FFFE000008F9
:040000033000FC00CD
:00000001FF

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
mode com3:1200,n,8,1
pause
..\tools\win\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b firmware.bin -R

View File

@@ -1,3 +0,0 @@
export PORT=cu.usbmodem1451
echo . | stty -f /dev/$PORT speed 1200
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -e -w -v -b firmware.bin -R

View File

@@ -1,3 +0,0 @@
mode com3:1200,n,8,1
pause
..\tools\win\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b firmware.bin -R

View File

@@ -1 +0,0 @@
../tools/mac/arduinoOTA -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch

Binary file not shown.

2
compiled/due/sendcommand.sh Executable file
View File

@@ -0,0 +1,2 @@
#../tools/mac/arduinoOTA -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
curl --basic --user arduino:password --data-ascii "$2" --url http://192.168.88.21:65280/command/$1

View File

@@ -1,3 +1,90 @@
mode com3:1200,n,8,1
pause
C:\Users\Akmal\.platformio\packages\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b C:\Users\Akmal\ownCloud\compiled\due\Wiz5500\firmware.bin -R
@ECHO off
REM Wait X second for memory on Arduino Due is erased.
SET WAIT_ERASED=4
ECHO ------ External tool BossacArduinoDue started ------
REM number of command line arguments ok?
REM IF [%1]==[] GOTO error_args
REM IF [%2]==[] GOTO error_args
REM set command line arguments
SET BOSSACPATH=..\tools\win\tool-bossac\bossac.exe
SET BINFILE=firmware.bin
REM parse command line arguments
SET BOSSACPATH=%BOSSACPATH:"=%
SET BINFILE=%BINFILE:"=%
REM workeround for bug in Atmel Studio 6.0.1996 Service Pack 2
SET BINFILE=%BINFILE:\\=\%
SET BINFILE=%BINFILE:.cproj=%
REM bossac path exist?
IF NOT EXIST "%BOSSACPATH%" GOTO error_arg1
REM bin file exist?
IF NOT EXIST "%BINFILE%" GOTO error_binfile
REM fetch DeviceID of Arduino Due Programming Port from WMI Service
FOR /f "tokens=* skip=1" %%a IN ('wmic PATH Win32_SerialPort Where "Caption LIKE '%%USB%%'" get DeviceID') DO (
SET COMX=%%a
GOTO exit1
)
REM Arduino Due Programming Port not exist
GOTO error_comport
:exit1
REM remove blank
SET COMPORT=%COMX: =%
REM report in Atmel Studio 6.0 IDE output window
ECHO BossacPath=%BOSSACPATH%
ECHO BinFile=%BINFILE%
ECHO Arduino Due Programming Port is detected as %COMPORT%.
REM The bossac bootloader only runs if the memory on Arduino Due is erased.
REM The Arduino IDE does this by opening and closing the COM port at 1200 baud.
REM This causes the Due to execute a soft erase command.
ECHO Forcing reset using 1200bps open/close on port
ECHO MODE %COMPORT%:1200,N,8,1
MODE %COMPORT%:1200,N,8,1
REM Wait X second for memory on Arduino Due is erased.
ECHO Wait for memory on Arduino Due is erased...
PING -n %WAIT_ERASED% 127.0.0.1>NUL
REM Execute bossac.exe
ECHO Execute bossac with command line:
ECHO "%BOSSACPATH%" -i -d --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R
START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R
GOTO end
:error_args
ECHO Error: wrong number of command line arguments passed!
GOTO end
:error_arg1
ECHO Error: command line argument 1 - path to bossac.exe not exist! - "C:\Program Files (x86)\arduino-1.5.2\hardware\tools\bossac.exe"
ECHO Error: command line argument 1 - argument passed = %1
GOTO end
:error_arg2
ECHO Error: command line argument 2 - path to bin file not exist! - use $(OutputDirectory)\$(OutputFileName).bin
ECHO Error: command line argument 2 - argument passed = %1
GOTO end
:error_binfile
ECHO Error: bin file "%BINFILE%" not exist!
GOTO end
:error_comport
ECHO Error: Arduino Due Programming Port not found!
:end
ECHO ======================== Done ========================

View File

@@ -1,3 +0,0 @@
mode com3:1200,n,8,1
pause
C:\Users\Akmal\.platformio\packages\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b C:\Users\Akmal\ownCloud\compiled\due\Wiz5500\firmware999.bin -R

View File

@@ -1,5 +1 @@
<<<<<<< HEAD
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
=======
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
>>>>>>> 9b164a1dfc40ee0e8f29dbedff4f3954edf55d76

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,62 @@
{
"syslog":["192.168.88.2"],
"mqtt1":["esp32","m2m.eclipse.org"],
"mqtt":["elevator","192.168.88.2"],
"mqtt4":["esp32","test.mosquitto.org"],
"dmx":[30],
"items": {
"relay1":[6,32],
"relay2":[6,33],
"relays":[7,["relay1","relay2"]],
"sensair1":[44,[254,
"sensair",
{"co2":{"emit":"co2"}},
{"mode":"auto"}
]
],
"elevator":[15,{"baud":9600,"serial":"8N1","ip":"192.168.88.255","port":502}],
"aaa1":[44,[254,
"aaa",
{"aaa1":{"emit":"aaa2"}},
{"mode":"auto"}
]
]
},
"modbus":
{
"aaa":
{"baud":19200,
"poll":{"irs":[1]},
"par":{
"aaa1":{"ir":1}
}
},
"sensair":{"baud":9600,
"poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"outStat":{"ir":0},
"pwm":{"ir":21},
"typeid":{"ir":25,"type":"u32"},
"mapver":{"ir":27},
"fwver":{"ir":28},
"sensorid":{"ir":29,"type":"u32"},
"ack":{"reg":0},
"command":{"reg":1},
"abc":{"reg":31}
}
}
},
"in":{ "34":{"item":"relays","emit":"myhome/in/bedr","scmd":"TOGGLE","rcmd":""},
"17":{"T":64,"emit":"analog","map":[0,1024,0,100,15]}
}
}

Binary file not shown.

View File

@@ -0,0 +1,2 @@
~/.platformio/packages/tool-mkspiffs/mkspiffs_espressif32_arduino -s 20480 -c data data.bin
../tools/mac/arduinoOTA -v -address 192.168.88.50 -port 65280 -username arduino -password password -sketch data.bin -upload /data -b

View File

@@ -1 +0,0 @@
../tools/mac/arduinoOTA -address 192.168.8.58 -port 65280 -username arduino -password password -sketch StartCounter.ino.bin -b -upload /sketch

View File

@@ -1 +1 @@
../tools/mac/arduinoOTA -address 192.168.88.45 -port 65280 -username arduino -password password -sketch firmware.bin -upload /sketch -b
../tools/mac/arduinoOTA -v -address 192.168.88.50 -port 65280 -username arduino -password password -sketch firmware.bin -upload /sketch -b

Binary file not shown.

View File

@@ -0,0 +1,215 @@
{
"dmx":[3,60],
"syslog":["192.168.88.2"],
"dmxin":["led5","led6","led7","led8"],
"topics":{"root":"lazyhome.ru"},
"mqtt":["lazyhome.ru-939a","192.168.88.3"],
"modbus":
{
"airset":{
"baud":9600,
"serial":"8E1",
"poll":{"regs":[[0,38],[1000,1008]],"delay":100000},
"par":{
"uheat":{"reg":0,"type":"u16"},
"umot":{"reg":2,"type":"u16"},
"amode":{"reg":3,"type":"u8","map":{}},
"onoff":{"reg":1000},
"fsauto":{"reg":1001},
"pmode":{"reg":1002},
"set":{"reg":1003},
"frcautoff":{"reg":1007},
"fault":{"reg":1008},
"t_heat":{"reg":8,"map":[0,1024,0,1024],"type":"i16"},
"mode":{"reg":24}
}
},
"dim4":{"serial":"8N1",
"poll":{"regs":[[0,4]],"delay":100000},
"par":{
"ch1":{"reg":0,"map":[]},
"ch2":{"reg":1,"map":[]},
"ch3":{"reg":2,"map":[]},
"ch4":{"reg":3,"map":[]}
}
},
"panel":{
"serial":"8E1",
"poll":{"regs":[[40000,40014],[30000,30002]],"delay":10000},
"par":{
"fan" :{"reg":40000,"map":[1,[0,7,0,100]],"id":1},
"mode" :{"reg":40001,"mapcmd":[2,[[1,"FAN_ONLY"],[2,"HEAT"],[4,"COOL"],[8,"AUTO"]]]},
"set" :{"reg":40002,"id":2},
"pwr" :{"reg":40003,"mapcmd":[2,[[0,2],[1,1]]]},
"alm01":{"reg":40004},
"alm17":{"reg":40005},
"alm33":{"reg":40006},
"sethum" :{"reg":40007,"id":3},
"setvoc" :{"reg":40008,"id":4},
"temp" :{"reg":30000,"map":[1,[-1000,1000,-100.0,100.0]],"type":"x10"},
"hum" :{"reg":30001},
"voc" :{"reg":30002},
"ch_temp" :{"reg":40009,"type":"x10","id":5},
"ext_temp" :{"reg":40010,"type":"x10","id":6},
"out_temp" :{"reg":40011,"type":"x10","id":7},
"water_temp" :{"reg":40012,"type":"x10","id":8},
"ch_hum" :{"reg":40013},
"heat_pwr":{"reg":40014}
}
}
},
"ow":{
"2861641227C1EFED":[{"emit":"t_1","item":"pid0/val"},{"emit":"pid_t"}]
},
"items": {
"dimer1":[44,[1,
"dim4",
{"ch1":{"emit":"aaa1"},"ch2":{"emit":"aaa2"},"ch3":{"emit":"aaa3"}},
{"mode":"auto"}
]
],
"p_bedr":[44,[2,"panel",
{
"fan" :{"sa":10, "act":
[
{"emit":"edem/ac/bedr/fan"},
{"emit":"edem/vent/bedr/fan"}
]
},
"mode":{"sa":11,"emit":"edem/ac/bedr/mode"},
"pwr" :{"sa":12,"emit":"edem/ac/bedr/pwr"},
"sethum":{"emit":"edem/vent/hum_bedr/set","item":"thermostat/set"},
"hum" :{"emit":"edem/vent/hum_bedr/val"},
"setvoc":{"emit":"edem/vent/bedr/set","item":"lled/sat"},
"voc" :{"emit":"edem/vent/bedr/val"},
"set" :{"sa":13, "act":
[
{"emit":"edem/fl2/term_bedr/set"},
{"emit":"edem/ac/bedr/set","item":"pid0/set"}
]
},
"temp" :{"emit":"edem/fl2/term_bedr/1/val"},
"ch_temp":{"sa":14},
"ch_hum":{"sa":15},
"ext_temp":{"sa":16},
"out_temp":{"sa":17},
"water_temp":{"sa":18},
"heat_pwr":{"sa":19},
"cmd":{"sa":2,"reg":"mode","on":1,"off":0}
}
]],
"airset1":[44,[247,"airset"]],
"mbusdim1":[44,[1,0,3,100]],
"mbusdim2":[44,[1,1,3,100]],
"mbusdim3":[44,[1,2,3,100]],
"mbusdim4":[44,[1,3,3,100]],
"relay":[6,22],
"pout1":[6,23],
"pout2":[6,24],
"pout3":[6,25],
"pout4":[33,9],
"pout5":[33,8],
"pout6":[33,11],
"pout7":[33,12],
"lled":[3,[9,8,11,12]],
"pwm0" :[33,4],
"pwm1" :[33,5],
"pwm2" :[3,6],
"pwm3" :[3,7],
"pwm10":[3,3],
"thermostat":[5,2,33],
"airgate1":[12,[-4,-27,59,617,284,5000]],
"airgate2":[12,[-5,-26,60,750,160,5000]],
"airgates":[7,["airgate1","airgate2"]],
"pid0":[413,
[
[20,0.2,7,0,100],
[{"item":"airgates/set","emit":"pid_out","pin":29},{"item":"pwm10/set"}]],
32.1],
"relaytermostat":[16,[[2,3.5,10000],{"pin":28},33]],
"virtualAC0":[17,[]],
"vent5":[18,
{
"":{"item":"dimmer3/set"},
"airgate1":{"V":100,"set":255,"item":"airgate1/set"},
"airgate2":{"V":200,"set":128,"cmd":2,"item":"airgate2/set"},
"airgate4":{"V":150,"set":0,"emit":"edem/in/airgate4/set"}
}
],
"unprot0":[6,33],
"unprot1":[6,32],
"unprot2":[6,31],
"unprot3":[6,30],
"unprot4":[6,29],
"unprot5":[6,28],
"unprot6":[66,27],
"unprot7":[66,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","mbuses"]],
"relays":[7,["relay","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","item":"unprot0","scmd":"TOGGLE","rcmd":""},
"38":{"emit":"in10","item":"dimmers","scmd":"TOGGLE","rcmd":""},
"40":{"emit":"in11","item":"leds","scmd":"TOGGLE","rcmd":""},
"35":{"emit":"in12","item":"mbuses","scmd":"TOGGLE","rcmd":""},
"37":{"emit":"in13","item":"relays","scmd":"TOGGLE","rcmd":""},
"39":{"emit":"in14","item":"uouts","scmd":"TOGGLE","rcmd":""},
"41":{"emit":"in15","item":"all","scmd":"TOGGLE","rcmd":""},
"54":{"T":66,"emit":"myhome/in/a00","map":[0,1024,0,1024,10]},
"55":{"T":66,"emit":"myhome/in/a01","map":[0,1024,0,1024,10]},
"56":{"T":66,"emit":"myhome/in/a02","map":[0,1024,0,1024,10]},
"57":{"T":66,"emit":"myhome/in/a03","map":[0,1024,0,1024,10]},
"58":{"T":66,"emit":"myhome/in/a04","map":[0,1024,0,1024,10]},
"61":{"T":66,"emit":"myhome/in/a07","map":[0,1024,0,1024,10]},
"62":{"T":66,"emit":"myhome/in/a08","map":[0,1024,0,1024,10]},
"63":{"T":66,"emit":"myhome/in/a09","map":[0,1024,0,1024,10]},
"64":{"T":66,"emit":"myhome/in/a10","map":[0,1024,0,1024,10]},
"65":{"T":66,"emit":"myhome/in/a11","map":[0,1024,0,1024,10]},
"66":{"T":0,"emit":"myhome/in/d12"},
"67":{"T":0,"emit":"myhome/in/d13"},
"68":{"T":0,"emit":"myhome/in/d14"},
"69":{"T":0,"emit":"myhome/in/d15"}
}
}

Binary file not shown.

View File

@@ -1,3 +1,90 @@
mode com3:1200,n,8,1
pause
..\tools\win\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b firmware.bin -R
@ECHO off
REM Wait X second for memory on Arduino Due is erased.
SET WAIT_ERASED=4
ECHO ------ External tool BossacArduinoDue started ------
REM number of command line arguments ok?
REM IF [%1]==[] GOTO error_args
REM IF [%2]==[] GOTO error_args
REM set command line arguments
SET BOSSACPATH=..\tools\win\tool-bossac\bossac.exe
SET BINFILE=firmware.bin
REM parse command line arguments
SET BOSSACPATH=%BOSSACPATH:"=%
SET BINFILE=%BINFILE:"=%
REM workeround for bug in Atmel Studio 6.0.1996 Service Pack 2
SET BINFILE=%BINFILE:\\=\%
SET BINFILE=%BINFILE:.cproj=%
REM bossac path exist?
IF NOT EXIST "%BOSSACPATH%" GOTO error_arg1
REM bin file exist?
IF NOT EXIST "%BINFILE%" GOTO error_binfile
REM fetch DeviceID of Arduino Due Programming Port from WMI Service
FOR /f "tokens=* skip=1" %%a IN ('wmic PATH Win32_SerialPort Where "Caption LIKE '%%USB%%'" get DeviceID') DO (
SET COMX=%%a
GOTO exit1
)
REM Arduino Due Programming Port not exist
GOTO error_comport
:exit1
REM remove blank
SET COMPORT=%COMX: =%
REM report in Atmel Studio 6.0 IDE output window
ECHO BossacPath=%BOSSACPATH%
ECHO BinFile=%BINFILE%
ECHO Arduino Due Programming Port is detected as %COMPORT%.
REM The bossac bootloader only runs if the memory on Arduino Due is erased.
REM The Arduino IDE does this by opening and closing the COM port at 1200 baud.
REM This causes the Due to execute a soft erase command.
ECHO Forcing reset using 1200bps open/close on port
ECHO MODE %COMPORT%:1200,N,8,1
MODE %COMPORT%:1200,N,8,1
REM Wait X second for memory on Arduino Due is erased.
ECHO Wait for memory on Arduino Due is erased...
PING -n %WAIT_ERASED% 127.0.0.1>NUL
REM Execute bossac.exe
ECHO Execute bossac with command line:
ECHO "%BOSSACPATH%" -i -d --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R
START /WAIT "" "%BOSSACPATH%" -i --port=%COMPORT% -U false -e -w -v -b "%BINFILE%" -R
GOTO end
:error_args
ECHO Error: wrong number of command line arguments passed!
GOTO end
:error_arg1
ECHO Error: command line argument 1 - path to bossac.exe not exist! - "C:\Program Files (x86)\arduino-1.5.2\hardware\tools\bossac.exe"
ECHO Error: command line argument 1 - argument passed = %1
GOTO end
:error_arg2
ECHO Error: command line argument 2 - path to bin file not exist! - use $(OutputDirectory)\$(OutputFileName).bin
ECHO Error: command line argument 2 - argument passed = %1
GOTO end
:error_binfile
ECHO Error: bin file "%BINFILE%" not exist!
GOTO end
:error_comport
ECHO Error: Arduino Due Programming Port not found!
:end
ECHO ======================== Done ========================

View File

@@ -0,0 +1 @@
../tools/mac/arduinoOTA -address 192.168.88.45 -port 65280 -username arduino -password password -sketch data/config.json -b -upload /data

View File

@@ -1,5 +0,0 @@
<<<<<<< HEAD
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
=======
..\tools\win\arduinoOTA.exe -address 192.168.88.21 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
>>>>>>> 9b164a1dfc40ee0e8f29dbedff4f3954edf55d76

View File

@@ -1 +1 @@
../tools/mac/arduinoOTA -address 192.168.11.172 -port 65280 -username arduino -password password -sketch firmware.bin -b -upload /sketch
../tools/mac/arduinoOTA -address 192.168.11.172 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

BIN
compiled/stm32/firmware.bin Executable file

Binary file not shown.

BIN
compiled/stm32/firmware.elf Executable file

Binary file not shown.

1
compiled/stm32/upload.sh Executable file
View File

@@ -0,0 +1 @@
dfu-util -D firmware.bin -a 1

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +0,0 @@
mode com3:1200,n,8,1
pause
..\tools\win\tool-bossac\bossac.exe -i --port=com3 -U false -e -w -v -b firmware.bin -R

View File

@@ -1,3 +0,0 @@
export PORT=cu.usbmodem14101
echo . | stty -f /dev/$PORT speed 1200
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -e -w -v -b firmware.bin -R

View File

@@ -2,12 +2,14 @@ cp ../.pio/build/due/firmware.bin due
cp ../.pio/build/controllino/firmware.hex controllino
cp ../.pio/build/m5stack/firmware.bin m5stack
cp ../.pio/build/mega2560slim-5100/firmware.hex mega2560slim-5100
cp ../.pio/build/due-5100/firmware.bin due-5100
cp ../.pio/build/mega2560slim-5100/firmware.bin mega2560slim-5100
cp ../.pio/build/mega2560-optiboot/firmware.hex mega2560-optiboot
cp ../.pio/build/mega2560-optiboot/firmware.bin mega2560-optiboot
cp ../.pio/build/mega2560-5100/firmware.hex mega2560-5100
cp ../.pio/build/due-5500/firmware.bin due-5500
cp ../.pio/build/nrf52840-5500/firmware.hex nrf52840-5500
cp ../.pio/build/nrf52840/firmware.hex nrf52840-5500
cp ../.pio/build/esp32-wifi/firmware.bin esp32-wifi
cp ../.pio/build/stm32-enc2860/firmware.bin stm32-enc2860
cp ../.pio/build/esp8266-wifi/firmware.bin esp8266-wifi
cp ../.pio/build/lighthub21/firmware.bin lighthub21
cp ../.pio/build/mega2560-5500/firmware.hex mega2560-5500
cp ../.pio/build/mega2560-5500/firmware.hex mega2560-5500
cp ../.pio/build/stm32/firmware.* stm32

62
data/config.json Normal file
View File

@@ -0,0 +1,62 @@
{
"syslog":["192.168.88.2"],
"mqtt1":["esp32","m2m.eclipse.org"],
"mqtt":["elevator","192.168.88.2"],
"mqtt4":["esp32","test.mosquitto.org"],
"dmx":[30],
"items": {
"relay1":[6,32],
"relay2":[6,33],
"relays":[7,["relay1","relay2"]],
"sensair1":[44,[254,
"sensair",
{"co2":{"emit":"co2"}},
{"mode":"auto"}
]
],
"elevator":[15,{"baud":9600,"serial":"8N1","ip":"192.168.88.255","port":502}],
"aaa1":[44,[254,
"aaa",
{"aaa1":{"emit":"aaa2"}},
{"mode":"auto"}
]
]
},
"modbus":
{
"aaa":
{"baud":19200,
"poll":{"irs":[1]},
"par":{
"aaa1":{"ir":1}
}
},
"sensair":{"baud":9600,
"poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"outStat":{"ir":0},
"pwm":{"ir":21},
"typeid":{"ir":25,"type":"u32"},
"mapver":{"ir":27},
"fwver":{"ir":28},
"sensorid":{"ir":29,"type":"u32"},
"ack":{"reg":0},
"command":{"reg":1},
"abc":{"reg":31}
}
}
},
"in":{ "34":{"item":"relays","emit":"myhome/in/bedr","scmd":"TOGGLE","rcmd":""},
"17":{"T":64,"emit":"analog","map":[0,1024,0,100,15]}
}
}

12
extra_script.py Normal file
View File

@@ -0,0 +1,12 @@
Import("env")
script = env.GetProjectOption("_upload_command")
#env.Replace(
# UPLOADER="executable or path to executable",
# UPLOADCMD=script
#)
env.AddCustomTarget(
"ota",
"$BUILD_DIR/${PROGNAME}.bin",
script
)

View File

@@ -31,7 +31,7 @@ int abstractCh::publishTopic(const char* topic, const char * value, const char*
{
strncpy(addrstr,topic,sizeof(addrstr));
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,topic);
strncat(addrstr,subtopic,sizeof(addrstr));
strncat(addrstr,subtopic,sizeof(addrstr)-1);
if (mqttClient.connected() && lanStatus == OPERATION && !ethernetIdleCount)
{
mqttClient.publish(addrstr, value, true);

View File

@@ -19,6 +19,6 @@ int abstractOut::isActive()
int abstractOut::Setup()
{
if (item) item->setCmd(CMD_OFF);
if (item && (item->getCmd()==-1)) item->setCmd(CMD_OFF);
return 1;
}

View File

@@ -6,14 +6,14 @@ uint8_t getBright255(uint8_t percent255)
#ifdef BRIGHT_LINEAR
return percent255;
#else
return pgm_read_byte_near(stepvar[percent255]);
return pgm_read_byte_near(&stepvar[percent255]);
/*
int val = stepvar[index];
if (val>255) val=255;
Serial.print(F("Bright:"));
Serial.print(percent);
Serial.print(F("->"));
Serial.println(val);
debugSerialPort.print(F("Bright:"));
debugSerialPort.print(percent);
debugSerialPort.print(F("->"));
debugSerialPort.println(val);
return val;*/
#endif
}

View File

@@ -25,6 +25,7 @@ int colorChannel::getDefaultStorageType()
{
case 3:
case 4:
case 5:
return ST_HSV255;
case 1:
return ST_PERCENTS255;
@@ -62,7 +63,7 @@ case S_HSV:
PixelCtrl(cmd, subItem, toExecute);
return 1;
case S_CMD:
item->setCmd(cmd.getCmd());
//item->setCmd(cmd.getCmd());
switch (cmd.getCmd())
{
case CMD_ON:

375
lighthub/config.cpp Normal file
View File

@@ -0,0 +1,375 @@
#include "config.h"
#include "main.h"
String systemConfig::getMACString()
{
String res;
for (int i=0; i<6; i++) {res+= ((String(mac[i]>>4,HEX)));res+=((String(mac[i]&0xf,HEX)));}
return res;
}
int systemConfig::openStream(char mode)
{
#if defined(FS_STORAGE)
return stream->open("/config.bin",mode);
#else
return stream->open(FN_CONFIG_BIN,mode);
#endif
//stream->setSize(SYSCONF_SIZE);
};
bool systemConfig::isValidSysConf()
{
if (!stream) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,signature));
for (int i=0;i<sizeof(systemConfigData::signature);i++)
if (stream->read()!=EEPROM_signature[i])
{
stream->close();
return false;
}
stream->close();
return true;
};
bool systemConfig::getMAC()
{
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,mac));
bool isMacValid = false;
for (short i = 0; i < 6; i++) {
mac[i] = stream->read();
if (mac[i] != 0 && mac[i] != 0xff) isMacValid = true;
}
stream->close();
return isMacValid;
}
bool systemConfig::setMAC(macAddress& _mac)
{
if (!stream || !isValidSysConf()) return false;
openStream('a');
stream->seek(offsetof(systemConfigData,mac));
stream->write ((const uint8_t *)&_mac,sizeof(_mac));
memcpy(mac, _mac, sizeof(mac));
stream->close();
return true;
}
char * systemConfig::getMQTTpwd(char * buffer, uint16_t bufLen)
{
if (!stream || !isValidSysConf()) return NULL;
openStream('r');
stream->seek(offsetof(systemConfigData,MQTTpwd));
short bytes=stream->readBytesUntil(0,buffer,bufLen-1);
stream->close();
if (bytes)
{
buffer[bytes]=0;
return buffer;
}
return NULL;
}
bool systemConfig::setMQTTpwd(char * pwd)
{
if (!stream || !isValidSysConf() || (strlen(pwd)>=sizeof(systemConfigData::MQTTpwd))) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,MQTTpwd));
stream->print(pwd);
int bytes = stream->write((uint8_t)'\0');
stream->close();
return bytes;
}
char * systemConfig::getOTApwd(char * buffer, uint16_t bufLen)
{
if (!stream || !isValidSysConf()) return NULL;
openStream('r');
stream->seek(offsetof(systemConfigData,OTApwd));
short bytes=stream->readBytesUntil(0,buffer,bufLen-1);
stream->close();
if (bytes)
{
buffer[bytes]=0;
return buffer;
}
return NULL;
}
bool systemConfig::setOTApwd(char * pwd)
{
if (!stream || !isValidSysConf() || (strlen(pwd)>=sizeof(systemConfigData::OTApwd))) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,OTApwd));
stream->print(pwd);
int bytes = stream->write((uint8_t)'\0');
stream->close();
return bytes;
}
char * systemConfig::getServer(char * buffer, uint16_t bufLen)
{
if (!stream || !isValidSysConf()) return NULL;
openStream('r');
stream->seek(offsetof(systemConfigData,configURL));
short bytes=stream->readBytesUntil(0,buffer,bufLen-1);
stream->close();
if (bytes)
{
buffer[bytes]=0;
return buffer;
}
return NULL;
}
bool systemConfig::setServer(char* url)
{
if (!stream || !isValidSysConf() || (strlen(url)>=sizeof(systemConfigData::configURL))) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,configURL));
stream->print(url);
int bytes = stream->write((uint8_t)'\0');
stream->close();
return bytes;
}
bool systemConfig::getIP(IPAddress& ip)
{
uint32_t addr;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ip));
stream->readBytes((uint8_t *) &addr,4);
ip=addr;
stream->close();
return (ip[0] && ((ip[0] != 0xff) || (ip[1] != 0xff) || (ip[2] != 0xff) || (ip[3] != 0xff)));
}
bool systemConfig::getMask(IPAddress& mask)
{
uint32_t addr;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,mask));
stream->readBytes((uint8_t *) &addr,4);
mask=addr;
stream->close();
return (mask[0] && ((mask[0] != 0xff) || (mask[1] != 0xff) || (mask[2] != 0xff) || (mask[3] != 0xff)));
}
bool systemConfig::getDNS(IPAddress& dns)
{ uint32_t addr;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,dns));
stream->readBytes((uint8_t *) &addr,4);
dns = addr;
stream->close();
return (dns[0] && ((dns[0] != 0xff) || (dns[1] != 0xff) || (dns[2] != 0xff) || (dns[3] != 0xff)));
}
bool systemConfig::getGW(IPAddress& gw)
{ uint32_t addr;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,gw));
stream->readBytes((uint8_t *) &addr,4);
gw=addr;
stream->close();
return (gw[0] && ((gw[0] != 0xff) || (gw[1] != 0xff) || (gw[2] != 0xff) || (gw[3] != 0xff)));
}
bool systemConfig::setIP(IPAddress& ip)
{ uint32_t addr=ip;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ip));
int bytes = stream->write((uint8_t *) &addr, 4);
stream->close();
return bytes;
}
bool systemConfig::setMask(IPAddress& mask)
{ uint32_t addr = mask;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,mask));
int bytes = stream->write((uint8_t *) &addr, 4);
stream->close();
return bytes;
}
bool systemConfig::setDNS(IPAddress& dns)
{ uint32_t addr = dns;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,dns));
int bytes = stream->write((uint8_t *) &addr, 4);
stream->close();
return bytes;
}
bool systemConfig::setGW(IPAddress& gw)
{ uint32_t addr = gw;
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,gw));
int bytes = stream->write((uint8_t *) &addr, 4);
stream->close();
return bytes;
}
bool systemConfig::clear()
{
if (!stream) return false;
openStream('w');
stream->seek(0);
for (unsigned int i = 0; i < stream->getSize(); i++) {
stream->write((uint8_t)'\0');
}
stream->seek(offsetof(systemConfigData,signature));
for (unsigned int i=0;i<sizeof(systemConfigData::signature);i++)
if (stream->write(EEPROM_signature[i]));
stream->close();
setETAG("");
setSerialDebuglevel(7);
setUdpDebuglevel(7);
return true;
}
systemConfigFlags systemConfig::getConfigFlags()
{
systemConfigFlags flags;
flags.configFlags32bit=0;
flags.serialDebugLevel=7;
flags.udpDebugLevel=7;
if (stream && isValidSysConf())
{
openStream('r');
stream->seek(offsetof(systemConfigData,configFlags));
stream->readBytes((uint8_t *) &flags,sizeof (flags));
stream->close();
}
return flags;
}
bool systemConfig::setConfigFlags(systemConfigFlags flags)
{
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,configFlags));
int bytes = stream->write((uint8_t *) &flags, sizeof (flags));
stream->close();
return bytes;
}
bool systemConfig::getSaveSuccedConfig()
{
systemConfigFlags flags = getConfigFlags();
return !flags.notSaveSuccedConfig;
}
bool systemConfig::setSaveSuccedConfig(bool flag)
{
systemConfigFlags flags = getConfigFlags();
flags.notSaveSuccedConfig=!flag;
return setConfigFlags(flags);
}
bool systemConfig::getLoadHTTPConfig()
{
systemConfigFlags flags = getConfigFlags();
return !flags.notGetConfigFromHTTP;
}
bool systemConfig::setLoadHTTPConfig(bool load)
{
systemConfigFlags flags = getConfigFlags();
flags.notGetConfigFromHTTP=!load;
return setConfigFlags(flags);
}
bool systemConfig::setSerialDebuglevel(short level)
{
systemConfigFlags flags = getConfigFlags();
flags.serialDebugLevel=level;
return setConfigFlags(flags);
}
bool systemConfig::setUdpDebuglevel(short level)
{
systemConfigFlags flags = getConfigFlags();
flags.udpDebugLevel=level;
return setConfigFlags(flags);
}
uint8_t systemConfig::getSerialDebuglevel()
{
systemConfigFlags flags = getConfigFlags();
return flags.serialDebugLevel;
}
uint8_t systemConfig::getUdpDebuglevel()
{
systemConfigFlags flags = getConfigFlags();
return flags.udpDebugLevel;
}
String systemConfig::getETAG()
{
debugSerial<<F("Get ETAG: ")<<currentConfigETAG<<endl;
return String("\"")+currentConfigETAG+String("\"");
}
bool systemConfig::setETAG(String etag)
{
int firstPos = etag.indexOf('"');
int lastPos = etag.lastIndexOf('"');
if ((firstPos>=0) && (lastPos>0)) currentConfigETAG=etag.substring(firstPos+1,lastPos);
else currentConfigETAG=etag;
debugSerial<<F("Set ETAG: ")<<currentConfigETAG<<endl;
return 1;
}
bool systemConfig::saveETAG()
{
if (!stream || !isValidSysConf() || (currentConfigETAG.length()>=sizeof(systemConfigData::ETAG))) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ETAG));
stream->print(currentConfigETAG);
int bytes = stream->write((uint8_t)'\0');
stream->close();
if (bytes) debugSerial<<F("Saved ETAG:")<<currentConfigETAG<<endl;
return bytes;
}
bool systemConfig::loadETAG()
{
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ETAG));
currentConfigETAG=stream->readStringUntil(0);
stream->close();
debugSerial<<F("Loaded ETAG:")<<currentConfigETAG<<endl;
return currentConfigETAG.length();
}

68
lighthub/config.h Normal file
View File

@@ -0,0 +1,68 @@
#pragma once
#if defined(ESP8266) || defined(ESP32)
#include "FS.h"
#endif
#include <Arduino.h>
#include "flashstream.h"
#include <IPAddress.h>
#include "systemconfigdata.h"
class systemConfig {
private:
flashStream * stream;
String currentConfigETAG;
int openStream(char mode = '\0');
public:
macAddress mac;
systemConfig():currentConfigETAG() {stream=NULL;};
systemConfig(flashStream * fs):currentConfigETAG() {stream=fs;};
bool isValidSysConf();
bool getMAC();
String getMACString();
bool setMAC(macAddress& mac);
char * getMQTTpwd(char * buffer, uint16_t bufLen);
bool setMQTTpwd(char * pwd = NULL);
char * getOTApwd(char * buffer, uint16_t bufLen);
bool setOTApwd(char * pwd = NULL);
bool setServer(char* url);
char * getServer(char * buffer, uint16_t bufLen);
bool getIP(IPAddress& ip);
bool getMask(IPAddress& mask);
bool getDNS(IPAddress& dns);
bool getGW(IPAddress& gw);
bool setIP(IPAddress& ip);
bool setMask(IPAddress& mask);
bool setDNS(IPAddress& dns);
bool setGW(IPAddress& gw);
bool setSerialDebuglevel(short);
bool setUdpDebuglevel(short);
uint8_t getSerialDebuglevel();
uint8_t getUdpDebuglevel();
bool clear();
bool getSaveSuccedConfig();
bool setSaveSuccedConfig(bool);
bool getLoadHTTPConfig();
bool setLoadHTTPConfig(bool);
String getETAG();
bool setETAG(String etag);
bool saveETAG();
bool loadETAG();
systemConfigFlags getConfigFlags();
bool setConfigFlags(systemConfigFlags flags);
//bool Save();
};

11
lighthub/discovery.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "Спальня LED_",
"command_topic": "myhome/in/bedr/cmd",
"state_topic": "myhome/s_out/bedr/cmd",
"hs_command_topic": "myhome/in/bedr/set",
"hs_state_topic": "myhome/s_out/bedr/set",
"hs_value_template": "{%set a=value.split(',')%} {% if a[1] -%} {{a[0]+','+a[1]}} {%- endif %}",
"brightness_scale": 100,
"brightness_command_topic": "myhome/in/bedr/set",
"brightness_state_topic": "myhome/s_out/bedr/set",
"brightness_value_template": "{{ value.split(',')[2] }}" }

View File

@@ -39,18 +39,21 @@ DMXESPSerial dmxout;
uint8_t * DMXin = NULL;
#ifdef DMX_SMOOTH
uint8_t * DMXinterimBuf = NULL;
uint16_t DMXOUT_Channels=0;
uint32_t checkTimestamp=0L;
volatile uint8_t * DMXinterimBuf = NULL;
volatile uint16_t DMXOUT_Channels=0;
volatile uint32_t checkTimestamp=0L;
#endif
int D_State=0;
unsigned long D_checkT=0;
#if defined(_dmxin)
volatile uint32_t D_State=0;
volatile unsigned long D_checkT=0;
#endif
#ifdef _artnet
#include <Artnet.h>
Artnet *artnet = NULL;
uint16_t artnetMinCh=1;
uint16_t artnetMaxCh=512;
#endif
@@ -123,6 +126,7 @@ void DMXSemiImmediateUpdate(short tch,short trh, int val)
void DMXput(void)
{
if (!DMXin) return;
for (short tch=0; tch<=3 ; tch++)
{
short base = tch*4;
@@ -130,34 +134,47 @@ for (short tch=0; tch<=3 ; tch++)
}
};
extern volatile uint8_t timerHandlerBusy;
#if defined(_dmxin)
volatile int DMXinDoublecheck=0;
#endif
void DMXUpdate(void)
{
#if defined(_dmxin)
int t;
if(!DMXin) return;
#if defined(__SAM3X8E__)
if (dmxin.getRxLength()<16) return;
#endif
for (short tch=0; tch<=3 ; tch++)
{
short base = tch*4;
bool updated = 0;
bool updated = 0;
bool confirmed = 0;
for (short trh=0; trh<4 ; trh++)
if ((t=dmxin.read(base+trh+1)) != DMXin[base+trh])
if (((t=dmxin.read(base+trh+1)) != DMXin[base+trh]))
{
D_State |= (1<<tch);
updated=1;
//Serial.print("onContactChanged :"); Serial.print(DMXin[tch*4+trh]); Serial.print(" => "); Serial.print(t);Serial.println();
DMXin[base+trh]=t;
//DMXImmediateUpdate(tch,trh,t);
//break;
}
if (DMXinDoublecheck>2)
{
D_State |= (1<<tch);
DMXin[base+trh]=t;
confirmed = 1;
}
}
if (updated)
if (updated) DMXinDoublecheck++; else DMXinDoublecheck=0;
if (confirmed)
{
DMXImmediateUpdate(tch,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]);
//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print("-");};debugSerial.print("|");
D_checkT=millisNZ();
}
}
@@ -191,19 +208,22 @@ D_checkT=0;
// Here code for network update
//int ch = 0;
DMXput();
#ifdef _dmxout
for (int i=1; i<17; i++) {Serial.print(dmxin.read(i));Serial.print(";");}
for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
debugSerial.println();
#endif
Serial.println();
#endif
}
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP)
{
#ifdef _dmxout
for (unsigned int i = 0 ; i < length && i<MAX_CHANNELS ; i++)
#if defined (_dmxout) && defined (_artnet)
for (unsigned int i = artnetMinCh-1 ; i < length && i<artnetMaxCh ; i++)
{
DmxWrite(i+1,data[i]);
}
@@ -221,7 +241,7 @@ void DMXinSetup(int channels)
DMXin = new uint8_t [channels];
#if defined(ARDUINO_ARCH_AVR)
DMXSerial.init(DMXReceiver,0,channels);
if (DMXSerial.getBuffer()) {Serial.print(F("Init in ch:"));Serial.println(channels);} else Serial.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"));
//DMXSerial.maxChannel(channels);
DMXSerial.attachOnUpdate(&DMXUpdate);
#endif
@@ -242,6 +262,11 @@ dmxin.begin();
void DMXoutSetup(int channels)
{
#ifdef _dmxout
//#ifdef _artnet
//if (channels<artnetMaxCh) artnetMaxCh=channels;
//#endif
#if defined(ARDUINO_ARCH_AVR)
DmxSimple.usePin(AVR_DMXOUT_PIN);
DmxSimple.maxChannel(channels);
@@ -271,42 +296,64 @@ debugSerial<<F("DMXInterim. Free:")<<freeRam()<<endl;
#endif
}
volatile int8_t propagateBusy = 0;
void DMXOUT_propagate()
{
#ifdef DMX_SMOOTH
if (propagateBusy) return;
propagateBusy++;
uint32_t now = millis();
//if (now<checkTimestamp) return;
if (!isTimeOver(checkTimestamp,now,DMX_SMOOTH_DELAY)) return;
for(int i=1;i<=DMXOUT_Channels;i++)
if (isTimeOver(checkTimestamp,now,DMX_SMOOTH_DELAY))
{
uint8_t currLevel=dmxout.getTx(i);
int32_t delta = currLevel-DMXinterimBuf[i-1];
if (delta)
{
uint16_t step = abs(delta) >> 4;
if (!step) step=1;
for(int i=1;i<=DMXOUT_Channels;i++)
{
uint8_t currLevel=dmxout.getTx(i);
int32_t delta = currLevel-DMXinterimBuf[i-1];
if (delta)
{
uint16_t step = abs(delta) >> 4;
if (!step) step=1;
if (delta<0)
{DmxWrite2(i,currLevel+step);debugSerial<<"<";}
if (delta<0)
{
DmxWrite2(i,currLevel+step);
//debugSerial<<"<";
}
if (delta>0)
{DmxWrite2(i,currLevel-step);debugSerial<<">";}
}
if (delta>0)
{
DmxWrite2(i,currLevel-step);
//debugSerial<<">";
}
}
}
checkTimestamp=now;
}
checkTimestamp=now;
propagateBusy--;
#endif
}
void ArtnetSetup()
void artnetSetup()
{
#ifdef _artnet
if (!artnet) artnet = new Artnet;
// this will be called for each packet received
if (artnet) artnet->setArtDmxCallback(onDmxFrame);
if (!artnet)
{
artnet = new Artnet;
artnet->begin();
// this will be called for each packet received
if (artnet) artnet->setArtDmxCallback(onDmxFrame);
}
#endif
}
void artnetSetChans(uint8_t minCh, uint8_t maxCh)
{
#ifdef _artnet
artnetMinCh=minCh;
artnetMaxCh=maxCh;
#endif
}
void DmxWriteBuf(uint16_t chan,uint8_t val)
{

View File

@@ -23,7 +23,7 @@ e-mail anklimov@gmail.com
#define D_UPDATED4 8
#define D_CHECKT 300
#define MAX_CHANNELS 60
//#define MAX_CHANNELS 60
//define MAX_IN_CHANNELS 16
//#define DMX_OUT_PIN 3
@@ -105,9 +105,9 @@ extern aJsonObject *dmxArr;
void DMXput(void);
void DMXinSetup(int channels);
void DMXoutSetup(int channels);
void ArtnetSetup();
void artnetSetup();
void artnetSetChans(uint8_t minCh, uint8_t maxCh);
void DMXCheck(void);
int itemCtrl2(char* name,int r,int g, int b, int w);
void ArtnetSetup();
void DmxWriteBuf(uint16_t chan,uint8_t val);
void DMXOUT_propagate();

View File

@@ -1,54 +0,0 @@
#include "options.h"
#ifdef __ESP__
#include "esp.h"
ESP8266WiFiMulti wifiMulti;
WiFiClient ethClient;
char mqtt_password[16];
//default custom static IP
//char static_ip[16] = "10.0.1.56";
//char static_gw[16] = "10.0.1.1";
//char static_sn[16] = "255.255.255.0";
//flag for saving data
bool shouldSaveConfig = false;
//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println(F("Should save config"));
shouldSaveConfig = true;
}
void espSetup () {
Serial.println(F("Setting up Wifi"));
shouldSaveConfig = true;
//WiFiManager
WiFiManagerParameter custom_mqtt_password("", "mqtt password", mqtt_password, 16);
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&custom_mqtt_password);
wifiManager.setMinimumSignalQuality();
if (!wifiManager.autoConnect()) {
Serial.println(F("failed to connect and hit timeout"));
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
//if you get here you have connected to the WiFi
Serial.println(F("connected...yeey :)"));
//read updated parameters
strcpy(mqtt_password, custom_mqtt_password.getValue());
}
#endif

View File

@@ -1,24 +0,0 @@
#include <ESP8266WiFi.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ESP8266WiFiMulti.h>
extern ESP8266WiFiMulti wifiMulti;
extern WiFiClient ethClient;
//WiFiManager wifiManager;
//define your default values here, if there are different values in config.json, they are overwritten.
//length should be max size + 1
extern char mqtt_password[16];
//default custom static IP
//char static_ip[16] = "10.0.1.56";
//char static_gw[16] = "10.0.1.1";
//char static_sn[16] = "255.255.255.0";
//flag for saving data
extern bool shouldSaveConfig;
void espSetup ();

244
lighthub/flashstream.cpp Normal file
View File

@@ -0,0 +1,244 @@
#include "flashstream.h"
#include "systemconfigdata.h"
#include <main.h>
#ifdef OTA
#include <WiFiOTA.h>
#endif
#if defined(ARDUINO_ARCH_AVR)
#include <EEPROM.h>
#endif
#if defined(ESP32) && !defined(FS_STORAGE)
#include <EEPROM.h>
#endif
#if defined(ARDUINO_ARCH_ESP8266) && !defined(FS_STORAGE)
#include <ESP_EEPROM.h>
#endif
#if defined(__SAM3X8E__)
#include <DueFlashStorage.h>
extern DueFlashStorage EEPROM;
#endif
#ifdef NRF5
#include <NRFFlashStorage.h> //STUB
extern NRFFlashStorage EEPROM;
#endif
#ifdef ARDUINO_ARCH_STM32
#include <NRFFlashStorage.h> //STUB
extern NRFFlashStorage EEPROM;
#endif
#if defined(__SAM3X8E__)
DueFlashStorage EEPROM;
#endif
#ifdef NRF5
NRFFlashStorage EEPROM;
#endif
#ifdef ARDUINO_ARCH_STM32
NRFFlashStorage EEPROM;
#endif
#if defined(FS_STORAGE)
int flashStream::open(String _filename, char mode)
{
char modestr[4];
int paramPos=-1;
//modestr[0]=mode; modestr[1]='b'; modestr[2]='+'; modestr[3]='\0';
modestr[0]=mode; modestr[1]='+'; modestr[2]='\0';
if (fs) fs.close();
if ((paramPos=_filename.indexOf('?'))>=0)
{
filename=_filename.substring(0,paramPos);
}
else filename=_filename;
if (fs = SPIFFS.open(filename,modestr))
{
openedMode=mode;
streamSize = DEFAULT_FILESIZE_LIMIT;
if (filename.endsWith(".json")) {contentType=HTTP_TEXT_JSON;textMode=true;streamSize = MAX_JSON_CONF_SIZE; }
else if (filename.endsWith(".bin")) {contentType=HTTP_OCTET_STREAM;textMode=false;streamSize = SYSCONF_SIZE; }
else if (filename.endsWith(".txt")) {contentType=HTTP_TEXT_PLAIN;textMode=true;}
else if (filename.endsWith(".html")) {contentType=HTTP_TEXT_HTML;textMode=true;}
else if (filename.endsWith(".gif")) {contentType=HTTP_IMAGE_GIF;textMode=false;}
else if (filename.endsWith(".jpg")) {contentType=HTTP_IMAGE_JPEG;textMode=false;}
debugSerial<<(F("Opened ("))<<modestr<<(F(")"))<<filename<<F(" Size:")<<streamSize<<endl;
return fs;
}
else
{
openedMode='\0';
debugSerial<<("Open error (")<<modestr<<(")")<<filename<<endl;
return 0;
}
};
int flashStream::available()
{
if (!fs) return 0;
//if (textMode && (peek()==EOFchar)) {debugSerial<<"X";return 0;} //Not working for esp8266
if (fs.position()>=streamSize) return 0;
return fs.available();
};
int flashStream::read() {
return fs.read();
};
int flashStream::peek() {
return fs.peek();
};
unsigned int flashStream::seek (unsigned int _pos)
{
debugSerial<<(F("Seek:"))<<_pos;
if (_pos>streamSize) _pos=streamSize;
unsigned int res = fs.seek(_pos,SeekSet);
debugSerial<<(F(" Res:"))<<res<<endl;
return res;
};
void flashStream::close() {fs.close(); debugSerial<<filename<<" Closed\n";};
void flashStream::flush() {fs.flush(); debugSerial<<filename<<" Flushed\n";};
size_t flashStream::write(uint8_t ch)
{
return fs.write(ch);
};
flashStream::~flashStream () {if (fs) fs.close();} ;
#else
void flashStream::setSize(unsigned int _size) {streamSize=_size;};
int flashStream::open(short fileNum, char mode)
{
switch (fileNum) {
case FN_CONFIG_JSON:
pos = 0;
streamSize = MAX_JSON_CONF_SIZE;
startPos = EEPROM_offsetJSON;
textMode = true;
#ifdef OTA
contentType = HTTP_TEXT_JSON;
#endif
return 1;
case FN_CONFIG_BIN:
pos = 0;
startPos = SYSCONF_OFFSET;
streamSize = SYSCONF_SIZE;
textMode =false;
#ifdef OTA
contentType = HTTP_OCTET_STREAM;
#endif
return 1;
default:
return 0;
}
};
int flashStream::open(String _filename, char mode)
{
int paramPos;
if ((paramPos=_filename.indexOf('?'))>=0)
{
_filename=_filename.substring(0,paramPos);
}
if (_filename == "/config.json") return open (FN_CONFIG_JSON,mode);
else if (_filename == "/config.bin") return open (FN_CONFIG_BIN,mode);
else return 0;
};
unsigned int flashStream::seek(unsigned int _pos)
{ pos=min(_pos, streamSize);
//debugSerial<<F("Seek:")<<pos<<endl;
return pos;
};
int flashStream::available()
{
if (textMode && peek()==EOFchar) return 0;
return (pos<streamSize);
};
int flashStream::read()
{
int ch = peek();
pos++;
return ch;
};
int flashStream::peek()
{
if (pos<streamSize)
return EEPROM.read(startPos+pos);
else return -1;
};
void flashStream::flush() {
#if defined(ESP8266) || defined(ESP32)
if (EEPROM.commitReset())
infoSerial<<"Commited to FLASH"<<endl;
else errorSerial<<"Commit error. len:"<<EEPROM.length()<<endl;
#endif
};
size_t flashStream::write(uint8_t ch)
{
#if defined(__AVR__)
EEPROM.update(startPos+pos++,(char)ch);
return 1;
#elif defined(__SAM3X8E__)
return EEPROM.write(startPos+pos++,(char)ch);
#else
EEPROM.write(startPos+pos++,(char)ch);
return 1;
#endif
};
#if defined(__SAM3X8E__)
size_t flashStream::write(const uint8_t *buffer, size_t size)
{
EEPROM.write(startPos+pos,(byte*)buffer,size);
pos+=size;
return size;
};
#endif
#if defined(ESP8266) || defined(ESP32)
void flashStream::putEOF()
{
if (textMode) write (EOFchar);
EEPROM.commit();
};
#endif
void flashStream::close()
{
putEOF();
}
#endif

83
lighthub/flashstream.h Normal file
View File

@@ -0,0 +1,83 @@
#pragma once
//#ifndef _FLASHSTREAM_H_
//#define _FLASHSTREAM_H_
#include <Stream.h>
#include <Arduino.h>
#include "seekablestream.h"
//#include "config.h"
#if defined(FS_STORAGE)
#include <FS.h>
#if defined ARDUINO_ARCH_ESP32
#include <SPIFFS.h>
#endif
#endif
#define FN_CONFIG_JSON 1
#define FN_CONFIG_BIN 2
#if defined(FS_STORAGE)
class flashStream : public seekableStream
{
private:
String filename;
char openedMode;
File fs;
public:
flashStream():seekableStream(65535)
{
openedMode='\0';
filename = "";
};
virtual int open(String _filename, char mode) override;
virtual int available() override;
virtual int read() override;
virtual int peek() override;
virtual unsigned int seek (unsigned int _pos = 0) override;
virtual void close() override;
virtual void flush() override;
virtual size_t write(uint8_t ch);
using Print::write;
virtual void putEOF() override {};
virtual ~flashStream ();
};
#else
#define MAX_STREAM_SIZE 4096
class flashStream : public seekableStream
{
protected:
unsigned int pos;
unsigned int startPos;
public:
flashStream():seekableStream(MAX_STREAM_SIZE){};
void setSize(unsigned int _size);
int open(short fileNum, char mode='\0') ;
virtual int open(String _filename, char mode='\0') override;
virtual unsigned int seek(unsigned int _pos = 0);
virtual int available() override;
virtual int read() ;
virtual int peek() ;
virtual void flush();
virtual size_t write(uint8_t ch) ;
#if defined(__SAM3X8E__)
virtual size_t write(const uint8_t *buffer, size_t size) override;
#else
using Print::write;//(const uint8_t *buffer, size_t size);
#endif
#if defined(ESP8266) || defined(ESP32)
virtual void putEOF() override ;
#endif
virtual void close() override;
};
#endif
//#endif

View File

@@ -34,8 +34,8 @@ e-mail anklimov@gmail.com
#endif
#ifdef MCP23017
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp;
#include "Adafruit_MCP23X17.h"
Adafruit_MCP23X17 mcp;
#endif
extern PubSubClient mqttClient;
@@ -181,10 +181,10 @@ switch (inType)
case IN_I2C | IN_PUSH_ON | IN_ACTIVE_HIGH:
case IN_I2C | IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
mcp.begin(); //TBD - multiple chip
mcp.pinMode(pin, INPUT);
if (inputPinMode == INPUT_PULLUP) mcp.pullUp(0, HIGH); // turn on a 100K pullup internally
mcp.begin_I2C(); //TBD - multiple chip
// CHECK! mcp.pinMode(pin, INPUT);
// CHECK! if (inputPinMode == INPUT_PULLUP) mcp.pullUp(0, HIGH); // turn on a 100K pullup internally
mcp.pinMode(pin,inputPinMode);
store->state=IS_IDLE;
break;
#endif
@@ -300,9 +300,9 @@ void Input::counterPoll() {
short real_pin = mega_interrupt_array[interrupt_number];
attachInterruptPinIrq(real_pin,interrupt_number);
} else {
Serial.print(F("IRQ:"));
Serial.print(pin);
Serial.print(F(" Counter type. INCORRECT Interrupt number!!!"));
debugSerial.print(F("IRQ:"));
debugSerial.print(pin);
debugSerial.print(F(" Counter type. INCORRECT Interrupt number!!!"));
return;
}
#endif
@@ -339,9 +339,9 @@ void Input::counterPoll() {
void Input::attachInterruptPinIrq(int realPin, int irq) {
pinMode(realPin, INPUT);
int real_irq;
#if defined(ARDUINO_ARCH_AVR)
//#if defined(ARDUINO_ARCH_AVR)
real_irq = irq;
#endif
//#endif
#if defined(__SAM3X8E__)
real_irq = realPin;
#endif
@@ -365,7 +365,7 @@ void Input::attachInterruptPinIrq(int realPin, int irq) {
attachInterrupt(real_irq, onCounterChanged5, RISING);
break;
default:
Serial.print(F("Incorrect irq:"));Serial.println(irq);
debugSerial.print(F("Incorrect irq:"));debugSerial.println(irq);
break;
}
}
@@ -526,16 +526,22 @@ if (newState == IS_REQSTATE)
{
// Requested delayed change State and safe moment
newState=store->reqState; //Retrieve requested state
debugSerial<<F("Pended state retrieved:")<<newState;
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
if (store->state == newState)
{
store->delayedState = false;
return false;
}
}
else return true; // No pended State
else if (store->delayedState)
return false; //State changing is postponed already (( giving up
aJsonObject *cmd = NULL;
itemCmd defCmd;
int8_t toggle=0;
if (newState!=store->state) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
switch (newState)
{
case IS_IDLE:
@@ -564,6 +570,7 @@ if (newState!=store->state) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("-
cmd = aJson.getObjectItem(inputObj, "scmd");
toggle=store->toggle1;
store->toggle1 = !store->toggle1;
if (!cmd) defCmd.Cmd(CMD_ON);
break;
case IS_PRESSED2: //scmd2
cmd = aJson.getObjectItem(inputObj, "scmd2");
@@ -580,6 +587,7 @@ if (newState!=store->state) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("-
case IS_WAITPRESS:
case IS_RELEASED2:
cmd = aJson.getObjectItem(inputObj, "rcmd");
if (!cmd) defCmd.Cmd(CMD_OFF);
// toggle=state->toggle1;
break;
@@ -609,32 +617,46 @@ if (newState!=store->state) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("-
break;
}
if (!cmd)
aJsonObject *defaultItem = aJson.getObjectItem(inputObj, "item");
aJsonObject *defaultEmit = aJson.getObjectItem(inputObj, "emit");
if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID);
if (!cmd && !defCmd.isCommand())
{
store->state=newState;
store->delayedState=false;
return true; //nothing to do
}
if (cause != CHECK_INTERRUPT)
{
store->state=newState;
executeCommand(cmd,toggle);
//Executed
store->delayedState=false;
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit);
return true;
}
else
{
//Postpone actual execution
store->reqState=store->state;
store->delayedState=true;
if (newState != store->state)
{
store->reqState=newState;
store->delayedState=true;
}
return true;
}
}
static volatile uint8_t contactPollBusy = 0;
void Input::contactPoll(short cause) {
boolean currentInputState;
if (!store) return;
if (!store /*|| contactPollBusy*/) return;
contactPollBusy++;
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
@@ -658,7 +680,8 @@ else
else currentInputState = false;
}
else currentInputState = (digitalRead(pin) == inputOnLevel);
switch (store->state) //Timer based transitions
if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
{
case IS_PRESSED:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
@@ -749,19 +772,21 @@ switch (store->state) //Timer based transitions
{
if (store->bounce) store->bounce = store->bounce - 1;
else //confirmed change
{
{
//if (cause == CHECK_INTERRUPT) return;
store->timestamp16 = millis() & 0xFFFF; //Saving timestamp of changing
/*
if (inType & IN_PUSH_TOGGLE) { //To refactore
if (currentInputState) { //react on leading edge only (change from 0 to 1)
//store->logicState = !store->logicState;
store->lastValue = currentInputState;
onContactChanged(store->toggle1);
onContactChanged(store->toggle1);
}
} else
} else */
{
onContactChanged(currentInputState); //Legacy input - to remove later
// onContactChanged(currentInputState); //Legacy input - to remove later
bool res = true;
if (currentInputState) //Button pressed state transitions
@@ -775,7 +800,15 @@ switch (store->state) //Timer based transitions
case IS_RELEASED:
case IS_WAITPRESS:
res = changeState(IS_PRESSED2, cause);
if ( //No future
!aJson.getObjectItem(inputObj, "scmd2") &&
!aJson.getObjectItem(inputObj, "lcmd2") &&
!aJson.getObjectItem(inputObj, "rpcmd2") &&
!aJson.getObjectItem(inputObj, "dclick")
)
res = changeState(IS_PRESSED, cause);
else res = changeState(IS_PRESSED2, cause);
break;
@@ -790,6 +823,7 @@ switch (store->state) //Timer based transitions
case IS_PRESSED:
res = changeState(IS_RELEASED, cause);
break;
case IS_LONG:
@@ -799,7 +833,13 @@ switch (store->state) //Timer based transitions
break;
case IS_PRESSED2:
res = changeState(IS_RELEASED2, cause);
if ( //No future
!aJson.getObjectItem(inputObj, "scmd2") &&
!aJson.getObjectItem(inputObj, "lcmd2") &&
!aJson.getObjectItem(inputObj, "rpcmd2") &&
!aJson.getObjectItem(inputObj, "dclick")
) res = changeState(IS_IDLE, cause);
else res = changeState(IS_RELEASED2, cause);
break;
case IS_LONG2:
@@ -819,6 +859,7 @@ switch (store->state) //Timer based transitions
}
} else // no change
store->bounce = SAME_STATE_ATTEMPTS;
contactPollBusy--;
}
@@ -826,6 +867,7 @@ switch (store->state) //Timer based transitions
void Input::analogPoll(short cause) {
int16_t inputVal;
int32_t mappedInputVal; // 10x inputVal
if (cause == CHECK_INTERRUPT) return;
aJsonObject *inputMap = aJson.getObjectItem(inputObj, "map");
int16_t Noize = ANALOG_NOIZE;
short simple = 0;
@@ -879,7 +921,7 @@ void Input::analogPoll(short cause) {
if (simple) {
if (mappedInputVal != store->currentValue)
{
onContactChanged(mappedInputVal);
onContactChanged(mappedInputVal);
store->currentValue = mappedInputVal;
}}
else
@@ -892,7 +934,7 @@ void Input::analogPoll(short cause) {
if ((store->bounce<ANALOG_STATE_ATTEMPTS-1 || mappedInputVal == min || mappedInputVal ==max )&& (inputVal != store->currentValue))//confirmed change
{
onAnalogChanged(itemCmd().Tens(mappedInputVal));
onAnalogChanged(itemCmd().Tens(mappedInputVal));
// store->currentValue = mappedInputVal;
store->currentValue = inputVal;
}
@@ -954,6 +996,7 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
}
}
void Input::onAnalogChanged(itemCmd newValue) {
debugSerial << F("IN:") << (pin) << F("="); newValue.debugOut();

View File

@@ -55,7 +55,7 @@ e-mail anklimov@gmail.com
#define SAME_STATE_ATTEMPTS 3
#define SAME_STATE_ATTEMPTS 2
#define ANALOG_STATE_ATTEMPTS 6
#define ANALOG_NOIZE 1

File diff suppressed because it is too large Load Diff

View File

@@ -35,12 +35,14 @@ e-mail anklimov@gmail.com
#define S_SAT 10
#define S_TEMP 11
#define S_VAL 12
#define S_ADDITIONAL 12
#define S_DELAYED 13
#define S_RAW 14
#define S_ADDITIONAL 14
#define CH_DIMMER 0 //DMX 1 ch
#define CH_DIMMER 0 //DMX 1-4 ch
#define CH_RGBW 1 //DMX 4 ch
#define CH_RGB 2 //DMX 3 ch
#define CH_PWM 3 //PWM output directly to PIN
#define CH_PWM 3 //PWM output directly to PIN 1-4 CH
#define CH_MODBUS 4 //Modbus AC Dimmer
#define CH_THERMO 5 //Simple ON/OFF thermostat
#define CH_RELAY 6 //ON_OFF relay output
@@ -52,6 +54,11 @@ e-mail anklimov@gmail.com
#define CH_MOTOR 12
#define CH_PID 13
#define CH_MBUS 14
#define CH_UARTBRIDGE 15
#define CH_RELAYX 16
#define CH_RGBWW 17
#define CH_MULTIVENT 18
#define CH_ELEVATOR 19
//#define CHANNEL_TYPES 13
@@ -73,6 +80,7 @@ e-mail anklimov@gmail.com
#define I_VAL 2 //Latest preset (int or array of presets)
#define I_CMD 3 //Latest CMD received
#define I_EXT 4 //Chanell-depended extension - array
#define I_TIMESTAMP 5
#define MODBUS_CMD_ARG_ADDR 0
#define MODBUS_CMD_ARG_REG 1
@@ -111,6 +119,7 @@ class Item
int Ctrl(char * payload, char * subItem=NULL);
int getArg(short n=0);
float getFloatArg(short n=0);
short getArgCount();
//int getVal(short n); //From VAL array. Negative if no array
long int getVal(); //From int val OR array
@@ -125,10 +134,11 @@ class Item
void setFlag (short flag);
void clearFlag (short flag);
void setVal(long int par);
void setFloatVal(float par);
void setSubtype(uint8_t par);
int Poll(int cause);
int SendStatus(int sendFlags);
int SendStatusImmediate(int sendFlags);
int SendStatusImmediate(itemCmd st, int sendFlags, char * subItem=NULL);
int isActive();
int getChanType();
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
@@ -136,20 +146,23 @@ class Item
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
protected:
//short cmd2changeActivity(int lastActivity, short defaultCmd = CMD_SET);
int VacomSetFan (itemCmd st);
int VacomSetHeat(itemCmd st);
int modbusDimmerSet(itemCmd st);
int modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint16_t value);
void mb_fail();
void mb_fail(int result=0);
void Parse();
int checkModbusDimmer();
int checkModbusDimmer(int data);
boolean checkModbusRetry();
boolean checkVCRetry();
boolean checkHeatRetry();
int checkModbusRetry();
//boolean checkVCRetry();
//boolean checkHeatRetry();
void sendDelayedStatus();
bool resumeModbus();
int checkFM();
char defaultSubItem[10];

View File

@@ -5,11 +5,13 @@
#include "item.h"
#include "bright.h"
#ifndef HSV_DISABLE
#ifdef ADAFRUIT_LED
#include <Adafruit_NeoPixel.h>
#else
#include "FastLED.h"
#endif
#endif
//#include "hsv2rgb.h"
@@ -81,6 +83,7 @@ itemCmd::itemCmd(Item *item)
itemCmd itemCmd::setChanType(short chanType)
{
cmd.itemArgType=getStoragetypeByChanType(chanType);
debugSerial<<F("Chan type:")<<chanType<<F(" -> AT:")<<cmd.itemArgType<<endl;
return *this;
}
@@ -91,6 +94,7 @@ uint8_t itemCmd::getStoragetypeByChanType(short chanType)
{
case CH_RGB:
case CH_RGBW:
case CH_RGBWW:
case CH_SPILED:
return ST_HSV255;
break;
@@ -105,6 +109,7 @@ uint8_t itemCmd::getStoragetypeByChanType(short chanType)
case CH_RELAY:
case CH_VC:
case CH_MODBUS:
//case CH_GROUP:
return ST_PERCENTS255;
break;
default:
@@ -177,6 +182,11 @@ bool itemCmd::setS(uint8_t s)
//! Internally 1 - cold, 101 - warm light
bool itemCmd::setColorTemp(int t)
{
if (!t)
{
param.colorTemp=0;
return true;
}
int par=map(t,153,500,0,100);
switch (cmd.itemArgType)
{
@@ -197,7 +207,7 @@ bool itemCmd::setColorTemp(int t)
return true;
}
//! Setup color tempetature parameter from HSV or HSV255 types. return 0..100 value in success.
//! Return color tempetature parameter from HSV or HSV255 types. return 153..500 value in success.
//! -1 - if no value stored
int itemCmd::getColorTemp()
{
@@ -319,7 +329,9 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
setColorTemp(t);
}
cmd.suffixCode=from.cmd.suffixCode;
cmd.cmdCode=from.cmd.cmdCode;
//cmd.cmdFlag
//cmd.cmdParam
switch (cmd.itemArgType){ //Destination
case ST_HSV255:
@@ -355,6 +367,12 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
break;
case ST_FLOAT:
param.v=constrain(from.param.asfloat,0.,255.);
break;
case ST_VOID:
break;
case ST_STRING:
cmd.itemArgType=from.cmd.itemArgType;
param.asString=from.param.asString;
break;
default:
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
@@ -362,6 +380,8 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
break;
case ST_VOID:
cmd.itemArgType=from.cmd.itemArgType;
param=from.param;
break;
case ST_INT32:
case ST_UINT32:
@@ -373,12 +393,17 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
param.h=from.param.h;
param.s=from.param.s;
cmd.itemArgType=ST_HSV255;
break;
case ST_STRING:
cmd.itemArgType=from.cmd.itemArgType;
param.asString=from.param.asString;
break;
default:
param.asInt32=from.param.asInt32;
cmd.itemArgType=from.cmd.itemArgType;
}
break;
case ST_HS:
case ST_HS: //ToDo - string ?
param.v=from.getPercents255();
cmd.itemArgType=ST_HSV255;
break;
@@ -388,6 +413,11 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
case ST_FLOAT_CELSIUS:
switch (from.cmd.itemArgType)
{
case ST_STRING:
cmd.itemArgType=from.cmd.itemArgType;
param.asString=from.param.asString;
break;
case ST_TENS:
param.asfloat=from.param.asInt32/10.;
break;
@@ -421,7 +451,9 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
param.h=from.param.h;
param.s=from.param.s;
cmd.itemArgType=ST_HSV255;
break;
break;
case ST_VOID:
break;
default:
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
}
@@ -433,6 +465,10 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
case ST_RGB:
switch (from.cmd.itemArgType)
{
case ST_STRING:
cmd.itemArgType=from.cmd.itemArgType;
param.asString=from.param.asString;
break;
case ST_RGBW:
// RGBW_flag=true;
case ST_RGB:
@@ -542,7 +578,7 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
}
}
#ifndef HSV_DISABLE
#ifdef ADAFRUIT_LED
Adafruit_NeoPixel strip(0, 0, 0);
uint32_t rgb = strip.ColorHSV(map(from.param.h, 0, 365, 0, 65535), rgbSaturation, rgbValue);
@@ -555,10 +591,15 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
param.g=rgb.g;
param.b=rgb.b;
#endif
#else
debugSerial<<F("HSV disabled")<<endl;
#endif
debugSerial<<F("RGBx: ");
debugOut();
break;
}
case ST_VOID:
break;
default:
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
} //Translation to RGB_XX
@@ -616,6 +657,17 @@ long int itemCmd::getInt()
}
}
char* itemCmd::getString()
{
switch (cmd.itemArgType) {
case ST_STRING:
return param.asString;
default:
return NULL;
}
}
float itemCmd::getFloat()
{
@@ -674,7 +726,8 @@ short itemCmd::getPercents(bool inverse)
case ST_TENS:
if (inverse) return constrain (100-param.asInt32/10,0,100);
else return constrain(param.asInt32/10,0,100);
case ST_VOID:
return 0;
default:
return -1;
@@ -721,7 +774,9 @@ short itemCmd::getPercents255(bool inverse)
case ST_TENS:
if (inverse) return 255-constrain(param.asInt32/10,0,255); else return constrain(param.asInt32/10,0,255);
case ST_VOID:
return 0;
default:
return -1;
}
@@ -875,7 +930,12 @@ itemCmd itemCmd::RGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w)
return *this;
}
itemCmd itemCmd::Str(char * str)
{
cmd.itemArgType=ST_STRING;
param.asString = str;
return *this;
}
itemCmd itemCmd::Cmd(uint8_t i)
@@ -896,42 +956,86 @@ itemCmd itemCmd::setSuffix(uint8_t suffix)
return *this;
}
bool itemCmd::loadItem(Item * item, bool includeCommand)
bool itemCmd::loadItem(Item * item, uint16_t optionsFlag)
{
bool res = false;
if (item && item->isValid())
{
short subtype =item->getSubtype();
if (optionsFlag & SEND_COMMAND) cmd.cmdCode = item->getCmd();
if (subtype)
{
param.asInt32=item->getVal();
cmd.itemArgType= subtype;
if (includeCommand) cmd.cmdCode=item->getCmd();
if (optionsFlag & SEND_PARAMETERS) param.asInt32 = item->getVal();
//debugSerial<<F("Loaded :");
//debugOut();
return 1;
return true;
}
switch (item->itemVal->type)
{
case aJson_Int:
Int((int32_t)item->itemVal->valueint);
return true;
case aJson_Float:
Float(item->itemVal->valueint);
return true;
}
if (optionsFlag & SEND_PARAMETERS)
switch (item->itemVal->type)
{
case aJson_Int:
Int((int32_t)item->itemVal->valueint);
//debugSerial<<F("Loaded Int:");
//debugOut();
return true;
case aJson_Float:
Float(item->itemVal->valuefloat);
//debugSerial<<F("Loaded Float:");
//debugOut();
return true;
}
}
return false;
}
bool itemCmd::saveItem(Item * item, bool includeCommand)
bool itemCmd::loadItemDef(Item * item, uint16_t optionsFlag)
{
//Restrieve previous channel state to "stored"
//if no values - set default values, save and put to MQTT
if (!loadItem(item,optionsFlag))
{
debugSerial<<F("No stored values - default: ");
setChanType(item->getChanType());
setDefault();
saveItem(item);
debugOut();
item->SendStatus(SEND_PARAMETERS | SEND_DEFFERED);
return false;
}
return true;
}
bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
{
if (item && item->isValid())
{
item->setVal(param.asInt32);
item->setSubtype(cmd.itemArgType);
if (includeCommand) item->setCmd(cmd.cmdCode);
if (optionsFlag & SEND_COMMAND) item->setCmd(cmd.cmdCode);
if (optionsFlag & SEND_PARAMETERS)
switch (cmd.itemArgType)
{
case ST_FLOAT:
case ST_FLOAT_CELSIUS:
item->setFloatVal(param.asfloat);
//
break;
case ST_INT32:
case ST_UINT32:
item->setVal(param.asInt32);
break;
default:
item->setSubtype(cmd.itemArgType);
item->setVal(param.asInt32);
}
debugSerial<<F("Saved:");
debugOut();
return true;

View File

@@ -19,7 +19,7 @@ e-mail anklimov@gmail.com
*/
#pragma once
#include "Arduino.h"
#include "aJson.h"
#include "aJSON.h"
typedef char cmdstr[9];
@@ -64,12 +64,15 @@ const cmdstr commands_P[] PROGMEM =
#define CMD_UNKNOWN -1
#define CMD_JSON -2
#define SEND_IMMEDIATE 0x1
#define SEND_COMMAND 0x100
#define SEND_PARAMETERS 0x200
#define SEND_RETRY 0x400
#define SEND_DEFFERED 0x800
#define ACTION_NEEDED 0x1000
#define ACTION_IN_PROCESS 0x2000
#define SEND_DELAYED 0x1000
#define ACTION_NEEDED 0x2000
#define ACTION_IN_PROCESS 0x4000
int txt2cmd (char * payload);
@@ -93,7 +96,7 @@ int txt2cmd (char * payload);
#define ST_INT32 10 /// 32 bits signed integer
#define ST_UINT32 11 /// 32 bits unsigned integer
#define ST_STRING 12 /// pointer to string (for further use)
//#define ST_TIMESTAMP 13 /// Timestamp for delayed cmd execution
#define MAP_SCALE 1
#define MAP_VAL_CMD 2
@@ -108,21 +111,11 @@ typedef union
struct
{
uint8_t cmdCode;
union {
uint8_t cmdFlag;
/*
struct
{ uint8_t suffixCode:4;
uint8_t itemArgType:4;
};
*/
};
struct
{ uint8_t suffixCode:4;
uint8_t itemArgType:4;
};
// uint8_t cmdEffect;
uint8_t cmdParam;
uint8_t suffixCode:4;
uint8_t itemArgType:4;
uint8_t cmdEffect; //Reserve
uint8_t cmdParam; //Reserve
};
} itemCmdStore;
@@ -168,8 +161,9 @@ public:
itemCmd assignFrom(itemCmd from, short chanType=-1);
bool loadItem(Item * item, bool includeCommand=false );
bool saveItem(Item * item, bool includeCommand=false);
bool loadItem(Item * item, uint16_t optionsFlag=SEND_PARAMETERS);
bool loadItemDef(Item * item, uint16_t optionsFlag=SEND_PARAMETERS );
bool saveItem(Item * item, uint16_t optionsFlag=SEND_PARAMETERS);
itemCmd Int(int32_t i);
itemCmd Int(uint32_t i);
@@ -181,6 +175,7 @@ public:
itemCmd HS(uint16_t h, uint8_t s);
itemCmd RGB(uint8_t r, uint8_t g, uint8_t b);
itemCmd RGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
itemCmd Str(char * str);
bool setH(uint16_t);
bool setS(uint8_t);
bool setColorTemp(int);
@@ -203,6 +198,7 @@ public:
long int getInt();
float getFloat();
char * getString();
long int getSingleInt();
short getPercents(bool inverse=false);
short getPercents255(bool inverse=false);

View File

@@ -1,11 +1,9 @@
#include "main.h"
void setup(){
//if (millis()>1000)
setup_main();
//else Serial.println("Hello");
//delay(1000);
void setup()
{
setup_main();
}
void loop(){
//if (millis()>10000)
void loop()
{
loop_main();
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,22 +7,23 @@
#endif
#if defined(__SAM3X8E__)
#include <DueFlashStorage.h>
#include <watchdog.h>
#include <ArduinoHttpClient.h>
//#include "TimerInterrupt_Generic.h"
#endif
#if defined(ARDUINO_ARCH_AVR)
#include "HTTPClientAVR.h"
#include "HTTPClient.h"
//#include <ArduinoHttpClient.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <EEPROM.h>
#endif
#if defined(ARDUINO_ARCH_ESP8266)
#include <FS.h> //this needs to be first, or it all crashes and burns...
//#include "SPIFFS.h"
#ifndef FS_STORAGE
#include <ESP_EEPROM.h>
#endif
//#include <ESP8266HTTPClient.h>
//#include <ArduinoHttpClient.h>
//#include "HttpClient.h"
@@ -38,7 +39,7 @@
#include <FS.h> //this needs to be first, or it all crashes and burns...
//#include "SPIFFS.h"
//#include <EEPROM.h>
#include <NRFFlashStorage.h>
//#include <NRFFlashStorage.h>
//#include "HttpClient.h"
//#include <ArduinoHttpClient.h>
//#include <HTTPClient.h>
@@ -53,14 +54,14 @@
#endif
#ifdef NRF5
#include <NRFFlashStorage.h>
//#include <NRFFlashStorage.h>
#include <ArduinoHttpClient.h>
#endif
#ifdef ARDUINO_ARCH_STM32
#include "HttpClient.h"
//#include "UIPEthernet.h"
#include <NRFFlashStorage.h>
//#include <NRFFlashStorage.h>
//#include <EEPROM.h>
#endif
@@ -128,10 +129,6 @@ extern Streamlog errorSerial;
#include <ModbusMaster.h>
#endif
//#ifndef DMX_DISABLE
//#include "FastLED.h"
//#endif
#ifdef _owire
#include "owTerm.h"
#endif
@@ -149,19 +146,21 @@ extern Streamlog errorSerial;
#include <WiFiClientSecure.h>
#include <WiFiManager.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#else
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiManager.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#endif
#define Ethernet WiFi
#else //Wired connection
#ifdef Wiz5500
#include <Ethernet2.h>
#else
#ifdef ARDUINO_ARCH_STM32
#ifdef UIPETHERNET
#include "UIPEthernet.h"
#else
#include <Ethernet.h>
@@ -178,6 +177,12 @@ extern Streamlog errorSerial;
#include "sd_card_w5100.h"
#endif
#ifdef MDNS_ENABLE
#ifndef WIFI_ENABLE
#include <ArduinoMDNS.h>
#endif
#endif
#include "Arduino.h"
#include "utils.h"
#include "textconst.h"
@@ -202,22 +207,24 @@ enum lan_status {
IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER = 4,
RETAINING_COLLECTING = 5,
OPERATION = 6,
OPERATION_NO_MQTT = 7,
DO_REINIT = -10,
REINIT = - 11,
DO_RECONNECT = 12,
RECONNECT = 13,
READ_RE_CONFIG = 14,
DO_READ_RE_CONFIG = 15,
DO_NOTHING = -15
};
extern lan_status lanStatus;
typedef union {
uint32_t UID_Long[5];
uint8_t UID_Byte[20];
} UID;
bool isNotRetainingStatus();
//void watchdogSetup(void);
void mqttCallback(char *topic, byte *payload, unsigned int length);
@@ -231,30 +238,26 @@ void Changed(int i, DeviceAddress addr, float currentTemp);
void modbusIdle(void);
void cmdFunctionHelp(int arg_cnt, char **args);
int cmdFunctionHelp(int arg_cnt, char **args);
void cmdFunctionKill(int arg_cnt, char **args);
int cmdFunctionKill(int arg_cnt, char **args);
void applyConfig();
void cmdFunctionLoad(int arg_cnt, char **args);
int cmdFunctionLoad(int arg_cnt, char **args);
int loadConfigFromEEPROM();
void cmdFunctionReq(int arg_cnt, char **args);
int cmdFunctionSave(int arg_cnt, char **args);
int mqttConfigRequest(int arg_cnt, char **args);
int cmdFunctionSetMac(int arg_cnt, char **args);
int mqttConfigResp(char *as);
int cmdFunctionGet(int arg_cnt, char **args);
void cmdFunctionSave(int arg_cnt, char **args);
void cmdFunctionSetMac(int arg_cnt, char **args);
void cmdFunctionGet(int arg_cnt, char **args);
int cmdFunctionLoglevel(int arg_cnt, char **args);
void printBool(bool arg);
/*
void saveFlash(short n, char *str);
int loadFlash(short n, char *str, short l=MAXFLASHSTR);
@@ -262,8 +265,9 @@ int loadFlash(short n, char *str, short l=MAXFLASHSTR);
void saveFlash(short n, IPAddress& ip);
int ipLoadFromFlash(short n, IPAddress &ip);
*/
lan_status loadConfigFromHttp(int arg_cnt = 0, char **args = NULL);
int loadConfigFromHttp();
void preTransmission();
@@ -277,7 +281,7 @@ void owIdle(void);
void modbusIdle(void);
void inputLoop(void);
void inputLoop(short);
void inputSetup(void);

View File

@@ -28,7 +28,7 @@ int in_ccs811::Setup()
digitalWrite(WAK_PIN,LOW);
#endif
Serial.println("CCS811 Init");
debugSerial.println("CCS811 Init");
Wire.begin(); //Inialize I2C Harware
Wire.setClock(4000);
@@ -41,7 +41,7 @@ Wire.setClock(4000);
//if (returnCode != CCS811Core::CCS811_Stat_SUCCESS)
{
Serial.print("CCS811 Init error ");
//Serial.println(ccs811.statusString(returnCode));
//debugSerial.println(ccs811.statusString(returnCode));
printDriverError(returnCode);
return 0;
}
@@ -61,16 +61,16 @@ return 1;
int in_hdc1080::Setup()
{
if (HDC1080ready) {debugSerial<<F("hdc1080 is already initialized")<<endl; return 0;}
Serial.println("HDC1080 Init ");
debugSerial.println("HDC1080 Init ");
Wire.begin(); //Inialize I2C Harware
// Default settings:
// - Heater off
// - 14 bit Temperature and Humidity Measurement Resolutions
hdc1080.begin(0x40);
Serial.print("Manufacturer ID=0x");
Serial.println(hdc1080.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
Serial.print("Device ID=0x");
Serial.println(hdc1080.readDeviceId(), HEX); // 0x1050 ID of the device
debugSerial.print("Manufacturer ID=0x");
debugSerial.println(hdc1080.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
debugSerial.print("Device ID=0x");
debugSerial.println(hdc1080.readDeviceId(), HEX); // 0x1050 ID of the device
printSerialNumber();
HDC1080ready = true;
return 1;
@@ -91,15 +91,15 @@ int in_hdc1080::Poll(short cause)
int reg;
if (cause!=POLLING_SLOW) return 0;
if (!HDC1080ready) {debugSerial<<F("HDC1080 not initialized")<<endl; return 0;}
Serial.print("HDC Status=");
Serial.println(reg=hdc1080.readRegister().rawData,HEX);
debugSerial.print("HDC Status=");
debugSerial.println(reg=hdc1080.readRegister().rawData,HEX);
if (reg!=0xff)
{
Serial.print(" T=");
Serial.print(t=hdc1080.readTemperature());
Serial.print("C, RH=");
Serial.print(h=hdc1080.readHumidity());
Serial.println("%");
debugSerial.print(" T=");
debugSerial.print(t=hdc1080.readTemperature());
debugSerial.print("C, RH=");
debugSerial.print(h=hdc1080.readHumidity());
debugSerial.println("%");
#ifdef M5STACK
@@ -125,7 +125,7 @@ if (reg!=0xff)
}
else //ESP I2C glitch
{
Serial.println("I2C Reset");
debugSerial.println("I2C Reset");
i2cReset();
}
return INTERVAL_SLOW_POLLING;
@@ -147,15 +147,15 @@ int in_ccs811::Poll(short cause)
CCS811Core::status returnCode = ccs811.readAlgorithmResults();
printDriverError(returnCode);
float co2,tvoc;
Serial.print(" CO2[");
debugSerial.print(" CO2[");
//Returns calculated CO2 reading
Serial.print(co2 = ccs811.getCO2());
Serial.print("] tVOC[");
debugSerial.print(co2 = ccs811.getCO2());
debugSerial.print("] tVOC[");
//Returns calculated TVOC reading
Serial.print(tvoc = ccs811.getTVOC());
Serial.print("] baseline[");
Serial.print(ccs811Baseline = ccs811.getBaseline());
debugSerial.print(tvoc = ccs811.getTVOC());
debugSerial.print("] baseline[");
debugSerial.print(ccs811Baseline = ccs811.getBaseline());
#ifdef M5STACK
M5.Lcd.print(" CO2[");
@@ -181,7 +181,7 @@ int in_ccs811::Poll(short cause)
publish(co2,"/CO2");
publish(tvoc,"/TVOC");
publish(ccs811Baseline,"/base");}
Serial.println("]");
debugSerial.println("]");
printSensorError();
#ifdef WAK_PIN
@@ -192,11 +192,11 @@ int in_ccs811::Poll(short cause)
}
void in_hdc1080::printSerialNumber() {
Serial.print("Device Serial Number=");
debugSerial.print("Device Serial Number=");
HDC1080_SerialNumber sernum = hdc1080.readSerialNumber();
char format[16];
sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
Serial.println(format);
debugSerial.println(format);
}
//printDriverError decodes the CCS811Core::status type and prints the
@@ -209,22 +209,22 @@ void in_ccs811::printDriverError( CCS811Core::status errorCode )
switch ( errorCode )
{
case CCS811Core::SENSOR_SUCCESS:
Serial.print("SUCCESS");
debugSerial.print("SUCCESS");
break;
case CCS811Core::SENSOR_ID_ERROR:
Serial.print("ID_ERROR");
debugSerial.print("ID_ERROR");
break;
case CCS811Core::SENSOR_I2C_ERROR:
Serial.print("I2C_ERROR");
debugSerial.print("I2C_ERROR");
break;
case CCS811Core::SENSOR_INTERNAL_ERROR:
Serial.print("INTERNAL_ERROR");
debugSerial.print("INTERNAL_ERROR");
break;
case CCS811Core::SENSOR_GENERIC_ERROR:
Serial.print("GENERIC_ERROR");
debugSerial.print("GENERIC_ERROR");
break;
default:
Serial.print("Unspecified error.");
debugSerial.print("Unspecified error.");
}
}
@@ -236,18 +236,18 @@ void in_ccs811::printSensorError()
if ( error == 0xFF ) //comm error
{
Serial.println("Failed to get ERROR_ID register.");
debugSerial.println("Failed to get ERROR_ID register.");
}
else
{
//Serial.print("");
if (error & 1 << 5) Serial.print("Error: HeaterSupply");
if (error & 1 << 4) Serial.print("Error: HeaterFault");
if (error & 1 << 3) Serial.print("Error: MaxResistance");
if (error & 1 << 2) Serial.print("Error: MeasModeInvalid");
if (error & 1 << 1) Serial.print("Error: ReadRegInvalid");
if (error & 1 << 0) Serial.print("Error: MsgInvalid");
Serial.println();
//debugSerial.print("");
if (error & 1 << 5) debugSerial.print("Error: HeaterSupply");
if (error & 1 << 4) debugSerial.print("Error: HeaterFault");
if (error & 1 << 3) debugSerial.print("Error: MaxResistance");
if (error & 1 << 2) debugSerial.print("Error: MeasModeInvalid");
if (error & 1 << 1) debugSerial.print("Error: ReadRegInvalid");
if (error & 1 << 0) debugSerial.print("Error: MsgInvalid");
debugSerial.println();
}
}
#endif

View File

@@ -31,6 +31,7 @@
#if defined (ARDUINO_ARCH_ESP32)
#undef WAK_PIN
#undef SCL_RESET
//#ifndef WAK_PIN
//#define WAK_PIN 17
//#endif

View File

@@ -53,6 +53,7 @@ void out_AC::InsertData(byte data[], size_t size){
char s_mode[10];
set_tmp = data[B_SET_TMP]+16;
if (set_tmp>40 || set_tmp<16) return;
cur_tmp = data[B_CUR_TMP];
mode = data[B_MODE];
fan_spd = data[B_FAN_SPD];
@@ -82,8 +83,8 @@ void out_AC::InsertData(byte data[], size_t size){
}
*/
Serial.print ("Power=");
Serial.println(power);
debugSerial.print ("Power=");
debugSerial.println(power);
if (power & 0x08)
publishTopic(item->itemArr->name, "ON", "/quiet");
@@ -188,8 +189,8 @@ byte getCRC(byte req[], size_t size){
void SendData(byte req[], size_t size){
AC_Serial.write(req, size - 1);
AC_Serial.write(getCRC(req, size-1));
AC_Serial.flush();
//AC_Serial.flush();
/*
Serial.print("<<");
for (int i=0; i < size-1; i++)
{
@@ -203,6 +204,7 @@ void SendData(byte req[], size_t size){
}
}
Serial.println();
*/
}
inline unsigned char toHex( char ch ){
@@ -214,7 +216,7 @@ inline unsigned char toHex( char ch ){
int out_AC::Setup()
{
abstractOut::Setup();
Serial.println("AC Init");
debugSerial<<F("AC Init")<<endl;
AC_Serial.begin(9600);
driverStatus = CST_INITIALIZED;
return 1;
@@ -222,7 +224,7 @@ return 1;
int out_AC::Stop()
{
Serial.println("AC De-Init");
debugSerial<<F("AC De-Init")<<endl;
driverStatus = CST_UNKNOWN;
return 1;
@@ -246,11 +248,11 @@ if (cause!=POLLING_SLOW) return 0;
//if (now - prevPolling > INTERVAL_AC_POLLING) {
if (isTimeOver(prevPolling,millis(),INTERVAL_AC_POLLING)) {
prevPolling = millisNZ();
Serial.println ("Polling");
debugSerial.println(F("Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
}
delay(100);
if(AC_Serial.available() > 0){
///delay(100);
if(AC_Serial.available() >= 37){ //was 0
AC_Serial.readBytes(data, 37);
while(AC_Serial.available()){
delay(2);
@@ -281,13 +283,14 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch(suffixCode)
{
case S_SET:
//case S_ESET:
set_tmp = cmd.getInt();
if (set_tmp >= 10 && set_tmp <= 30)
if (set_tmp >= 16 && set_tmp <= 40)
{
//if (set_tmp>40 || set_tmp<16) set_temp=21;
data[B_SET_TMP] = set_tmp -16;
publishTopic(item->itemArr->name,(long) set_tmp,"/set");
}
else return -1;
break;
case S_CMD:

View File

@@ -18,7 +18,7 @@
#define S_LOCK S_ADDITIONAL+1
#define S_QUIET S_ADDITIONAL+2
#define S_SWING S_ADDITIONAL+3
#define S_RAW S_ADDITIONAL+4
//#define S_RAW S_ADDITIONAL+4
extern void modbusIdle(void) ;
class out_AC : public abstractOut {

View File

@@ -14,14 +14,14 @@ static int driverStatus = CST_UNKNOWN;
int out_dmx::Setup()
{
abstractOut::Setup();
debugSerial<<F("DMX-Out Init")<<endl;
debugSerial<<F("DMX-Out Init: ")<< item->itemArr->name <<endl;
driverStatus = CST_INITIALIZED;
return 1;
}
int out_dmx::Stop()
{
debugSerial<<F("DMX-Out stop")<<endl;
debugSerial<<F("DMX-Out stop: ")<< item->itemArr->name << endl;
driverStatus = CST_UNKNOWN;
return 1;
}
@@ -46,7 +46,9 @@ int out_dmx::getChanType()
case 3:
return CH_RGB;
case 4:
return CH_RGBW;
return CH_RGBW;
case 5:
return CH_RGBWW;
default:
return item->itemType;
}
@@ -81,11 +83,15 @@ if (cType==CH_DIMMER) //Single channel
return 1;
}
int colorTemp = cmd.getColorTemp();
switch (cType)
{
case CH_RGB:
storageType=ST_RGB;
break;
case CH_RGBWW:
cmd.setColorTemp(0); //Supress cold conversoin
case CH_RGBW:
storageType=ST_RGBW;
break;
@@ -98,9 +104,19 @@ st.assignFrom(cmd);
debugSerial<<F("Assigned:");st.debugOut();
switch (cType)
{
{
case CH_RGBWW:
if (colorTemp == -1) colorTemp = 255/2;
else colorTemp=map(colorTemp,153,500,0,255);
DmxWrite(getChannelAddr(3), map(st.param.w,0,255,0,colorTemp));
DmxWrite(getChannelAddr(4), map(st.param.w,0,255,0,255-colorTemp));
DmxWrite(iaddr, st.param.r);
DmxWrite(getChannelAddr(1), st.param.g);
DmxWrite(getChannelAddr(2), st.param.b);
break;
case CH_RGBW:
DmxWrite(getChannelAddr(3), st.param.w);
DmxWrite(getChannelAddr(3), st.param.w);
case CH_RGB:
DmxWrite(iaddr, st.param.r);
DmxWrite(getChannelAddr(1), st.param.g);

View File

@@ -22,11 +22,13 @@ struct reg_t
const uint8_t id;
};
/*
struct serial_t
{
const char verb[4];
const serialParamType mode;
};
*/
#define PAR_I16 1
#define PAR_I32 2
@@ -53,6 +55,7 @@ const reg_t regSize_P[] PROGMEM =
} ;
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
/*
const serial_t serialModes_P[] PROGMEM =
{
{ "8E1", (serialParamType) SERIAL_8E1},//(uint16_t) US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_EVEN },
@@ -90,6 +93,8 @@ serialParamType str2SerialParam(char * str)
debugSerial<< F("Default serial mode N81 used");
return static_cast<serialParamType> (SERIAL_8N1);
}
*/
int str2regSize(char * str)
{
for(uint8_t i=0; i<regSizeNum && str;i++)
@@ -101,7 +106,7 @@ int str2regSize(char * str)
bool out_Modbus::getConfig()
{
// Retrieve and store template values from global modbus settings
if (!store || !item || !item->itemArg || (item->itemArg->type != aJson_Array) || aJson.getArraySize(item->itemArg)<2)
if (!store || !item || !item->itemArg || (item->itemArg->type != aJson_Array) || aJson.getArraySize(item->itemArg)<2 || !modbusObj)
{
errorSerial<<F("MBUS: config failed:")<<(bool)store<<F(",")<<(bool)item<<F(",")<<(bool)item->itemArg<<F(",")<<(item->itemArg->type != aJson_Array)<<F(",")<< (aJson.getArraySize(item->itemArg)<2)<<endl;
return false;
@@ -131,6 +136,8 @@ bool out_Modbus::getConfig()
modbusSerial.begin(store->baud, static_cast <USARTClass::USARTModes> (store->serialParam));
#elif defined (ARDUINO_ARCH_ESP8266)
modbusSerial.begin(store->baud, static_cast <SerialConfig>(store->serialParam));
#elif defined (ARDUINO_ARCH_ESP32)
modbusSerial.begin(store->baud, (store->serialParam),MODBUS_UART_RX_PIN,MODBUS_UART_TX_PIN);
#else
modbusSerial.begin(store->baud, (store->serialParam));
#endif
@@ -180,7 +187,7 @@ else
int out_Modbus::Stop()
{
Serial.println("Modbus De-Init");
debugSerial.println("Modbus De-Init");
delete store;
item->setPersistent(NULL);
@@ -216,7 +223,7 @@ switch (regType) {
default:
debugSerial<<F("Not supported reg type\n");
}
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<result<<endl;
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl;
return (result == node.ku8MBSuccess);
}
@@ -349,7 +356,7 @@ return is8bit;
//if (readModbus(registerFrom,MODBUS_HOLDING_REG_TYPE,registerTo-registerFrom+1))
if (readModbus(registerFrom,regType,registerTo-registerFrom+1))
{
{ debugSerial<<endl;
for(int i=registerFrom;i<=registerTo;i++)
{
findRegister(i,i-registerFrom,regType);
@@ -416,6 +423,7 @@ int out_Modbus::getChanType()
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute)
{
return 0;
//int chActive = item->isActive();
//bool toExecute = (chActive>0);
//itemCmd st(ST_UINT32,CMD_VOID);
@@ -424,9 +432,9 @@ aJsonObject *templateParamObj = NULL;
short mappedCmdVal = 0;
// trying to find parameter in template with name == subItem (NB!! standard suffixes dint working here)
if (subItem && strlen (subItem)) templateParamObj = aJson.getObjectItem(store->parameters, subItem);
if (subItem && strlen (subItem) && store) templateParamObj = aJson.getObjectItem(store->parameters, subItem);
if (!templateParamObj)
if (!templateParamObj && store)
{
// Trying to find template parameter where id == suffixCode
templateParamObj = store->parameters->child;

View File

@@ -4,12 +4,9 @@
#include <abstractout.h>
#include <item.h>
#include "itemCmd.h"
#include <utils.h>
#if defined(ESP32)
#define serialParamType uint32_t
#else
#define serialParamType uint16_t
#endif
class mbPersistent : public chPersistent {

View File

@@ -50,7 +50,7 @@ int out_Motor::Setup()
{
abstractOut::Setup();
getConfig();
Serial.println("Motor Init");
debugSerial.println("Motor Init");
pinMode(pinUp,OUTPUT);
pinMode(pinDown,OUTPUT);
@@ -70,7 +70,7 @@ return 1;
int out_Motor::Stop()
{
Serial.println("Motor De-Init");
debugSerial.println("Motor De-Init");
digitalWrite(pinUp,INACTIVE);
digitalWrite(pinDown,INACTIVE);
@@ -240,7 +240,7 @@ else
}
else //Target zone
{ Serial.println("Target");
{ debugSerial.println("Target");
digitalWrite(pinUp,INACTIVE);
digitalWrite(pinDown,INACTIVE);
item->setExt(0);
@@ -298,7 +298,7 @@ case S_SET:
//break;
case S_CMD:
item->setCmd(cmd.getCmd());
//item->setCmd(cmd.getCmd());
switch (cmd.getCmd())
{
case CMD_ON:

View File

@@ -0,0 +1,232 @@
#ifndef MULTIVENT_DISABLE
#include "modules/out_multivent.h"
#include "Arduino.h"
#include "options.h"
#include "Streaming.h"
#include "item.h"
#include "main.h"
static int driverStatus = CST_UNKNOWN;
void out_Multivent::getConfig()
{
gatesObj = NULL;
if (!item || !item->itemArg || item->itemArg->type != aJson_Object) return;
gatesObj = item->itemArg;
}
int out_Multivent::Setup()
{
abstractOut::Setup();
//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
if (gatesObj /*&& aJson.getArraySize(item->itemArg)>=2*/)
{
aJsonObject * i = gatesObj->child;
while (i)
{
if (i->name && *i->name)
{
aJsonObject * setObj = aJson.getObjectItem(i, "set");
if (!setObj) aJson.addNumberToObject(i, "set", (long int) -1);
aJsonObject * cmdObj = aJson.getObjectItem(i, "cmd");
if (!cmdObj) aJson.addNumberToObject(i, "cmd", (long int) -1);
aJsonObject * outObj = aJson.getObjectItem(i, "out");
if (!outObj) aJson.addNumberToObject(i, "out", (long int) -1);
}
i=i->next;
}
debugSerial << F ("MultiVent init")<< endl;
driverStatus = CST_INITIALIZED;
return 1;
}
debugSerial << F ("MultiVent config failed")<< endl;
return 0;
}
int out_Multivent::Stop()
{
debugSerial << F ("Multivent De-Init") << endl;
driverStatus = CST_UNKNOWN;
return 1;
}
int out_Multivent::Status()
{
return driverStatus;
}
/*
int out_Multivent::isActive()
{
itemCmd st;
switch (item->getCmd())
{
case CMD_OFF:
case CMD_HALT:
return 0;
break;
default:
st.loadItem(item);
return st.getPercents255();
}
}
*/
int out_Multivent::Poll(short cause)
{
return 0;
};
int out_Multivent::getChanType()
{
return CH_PWM;
}
int out_Multivent::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
{
int suffixCode = cmd.getSuffix();
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
aJsonObject * i = NULL;
if (gatesObj) i = gatesObj->child; // Pass 1 - calculate summ air value, max value etc
int activeV = 0;
int totalV = 0;
int maxV=0;
int maxRequestedV=0;
int maxPercent=0;
while (i)
{
aJsonObject * setObj=aJson.getObjectItem(i, "set");
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
if (setObj && cmdObj && setObj->type==aJson_Int && cmdObj->type==aJson_Int)
{
int V =aJson.getObjectItem(i,"V")->valueint;
int requestedV=0;
if (subItem && !strcmp (i->name,subItem))
{
if (cmdObj && cmd.isCommand())
{
cmdObj->valueint = cmd.getCmd();
//publishTopic(i->name,cmdObj->valueint,"/set");
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_COMMAND,i->name);
}
if (setObj && cmd.isValue())
{
setObj->valueint = cmd.getPercents255();
//publishTopic(i->name,setObj->valueint,"/set");
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_PARAMETERS,i->name);
}
}
if (cmdObj->valueint != CMD_OFF)
{
requestedV=V*setObj->valueint;
activeV+=requestedV;
}
totalV+=V;
//if(requestedV>maxRequestedV)
if (setObj->valueint>maxPercent)
{
maxRequestedV=requestedV;
maxV=V;
maxPercent=setObj->valueint;
}
}
i=i->next;
}
if (!totalV) return 0;
int fanV=activeV/totalV;
debugSerial << F("Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max request:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV));
i=NULL;
if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow
while (i)
{
int V =aJson.getObjectItem(i,"V")->valueint;
aJsonObject * outObj=aJson.getObjectItem(i, "out");
aJsonObject * setObj=aJson.getObjectItem(i, "set");
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
if (outObj && setObj && cmdObj && outObj->type==aJson_Int && setObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
{
long int out = 0;
if (cmdObj->valueint != CMD_OFF && maxRequestedV)
{
int requestedV=V*setObj->valueint;
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
debugSerial<<i->name<<(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
}
// executeCommand(i,-1,itemCmd().Percents255(out));
if (out != outObj->valueint)
{
//report out
executeCommand(i,-1,itemCmd().Percents255(out));
outObj->valueint=out;
}
}
i=i->next;
}
return 1;
switch(suffixCode)
{
case S_NOTFOUND:
// turn on and set
toExecute = true;
debugSerial<<F("Forced execution");
case S_SET:
if (!cmd.isValue()) return 0;
return 1;
//break;
case S_CMD:
//item->setCmd(cmd.getCmd());
switch (cmd.getCmd())
{
case CMD_ON:
return 1;
case CMD_OFF:
return 1;
} //switch cmd
break;
} //switch suffix
debugSerial<<F("Unknown cmd")<<endl;
return 0;
}
#endif

Some files were not shown because too many files have changed in this diff Show More