mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03:00
1343 lines
37 KiB
C++
1343 lines
37 KiB
C++
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
|
||
*
|
||
Licensed under the Apache License, Version 2.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
|
||
Homepage: http://lazyhome.ru
|
||
GIT: https://github.com/anklimov/lighthub
|
||
e-mail anklimov@gmail.com
|
||
|
||
|
||
|
||
*
|
||
*
|
||
* Done:
|
||
* MQMT/openhab
|
||
* 1-wire
|
||
* DMX - out
|
||
* DMX IN
|
||
* 1809 strip out (discarded)
|
||
* Modbus master Out
|
||
* DHCP
|
||
* JSON config
|
||
* cli
|
||
* PWM Out 7,8,9
|
||
* 1-w relay out
|
||
* Termostat out
|
||
|
||
Todo (backlog)
|
||
===
|
||
rotary encoder local ctrl ?
|
||
analog in local ctrl
|
||
Smooth regulation/fading
|
||
PID Termostat out ?
|
||
dmx relay out
|
||
Relay array channel
|
||
Relay DMX array channel
|
||
Config URL & MQTT password commandline configuration
|
||
1-wire Update refactoring (save memory)
|
||
Topic configuration
|
||
Timer
|
||
Modbus response check
|
||
control/debug (Commandline) over MQTT
|
||
more Modbus dimmers
|
||
|
||
todo DUE related:
|
||
PWM freq fix
|
||
Config webserver
|
||
SSL
|
||
|
||
todo ESP:
|
||
Config webserver
|
||
SSL
|
||
|
||
ESP32
|
||
PWM Out
|
||
|
||
*/
|
||
|
||
#include "Arduino.h"
|
||
#include "main.h"
|
||
#include "options.h"
|
||
|
||
#if defined(__SAM3X8E__)
|
||
DueFlashStorage EEPROM;
|
||
EthernetClient ethClient;
|
||
#endif
|
||
|
||
#if defined(__AVR__)
|
||
EthernetClient ethClient;
|
||
#endif
|
||
|
||
const char outprefix[] PROGMEM = OUTTOPIC;
|
||
const char inprefix[] PROGMEM = INTOPIC;
|
||
const char configserver[] PROGMEM = CONFIG_SERVER;
|
||
|
||
|
||
aJsonObject *root = NULL;
|
||
aJsonObject *items = NULL;
|
||
aJsonObject *inputs = NULL;
|
||
|
||
aJsonObject *mqttArr = NULL;
|
||
aJsonObject *modbusArr = NULL;
|
||
aJsonObject *owArr = NULL;
|
||
aJsonObject *dmxArr = NULL;
|
||
|
||
unsigned long nextPollingCheck = 0;
|
||
unsigned long nextInputCheck = 0;
|
||
unsigned long lanCheck = 0;
|
||
unsigned long nextThermostatCheck = 0;
|
||
|
||
aJsonObject *pollingItem = NULL;
|
||
|
||
bool owReady = false;
|
||
bool configOk = false;
|
||
int lanStatus = 0;
|
||
|
||
#ifdef _modbus
|
||
ModbusMaster node;
|
||
#endif
|
||
|
||
byte mac[6];
|
||
|
||
|
||
PubSubClient mqttClient(ethClient);
|
||
|
||
|
||
void watchdogSetup(void) {} //Do not remove - strong re-definition WDT Init for DUE
|
||
|
||
|
||
// MQTT Callback routine
|
||
|
||
|
||
void mqttCallback(char *topic, byte *payload, unsigned int length) {
|
||
|
||
Serial.print(F("\n["));
|
||
Serial.print(topic);
|
||
Serial.print(F("] "));
|
||
if (!payload) return;
|
||
payload[length] = 0;
|
||
|
||
int fr = freeRam();
|
||
if (fr < 250) {
|
||
Serial.println(F("OOM!"));
|
||
return;
|
||
}
|
||
|
||
for (int i = 0; i < length; i++) {
|
||
Serial.print((char) payload[i]);
|
||
}
|
||
Serial.println();
|
||
|
||
boolean retaining = (lanStatus == 4); //Todo - named constant
|
||
//Check if topic = Command topic
|
||
short intopic = 0;
|
||
{
|
||
char buf[MQTT_TOPIC_LENGTH + 1];
|
||
strncpy_P(buf, inprefix, sizeof(buf));
|
||
intopic = strncmp(topic, buf, strlen(inprefix));
|
||
}
|
||
|
||
// in Retaining status - trying to restore previous state from retained output topic. Retained input topics are not relevant.
|
||
if (retaining && !intopic) {
|
||
Serial.println(F("Skipping.."));
|
||
return;
|
||
}
|
||
|
||
char subtopic[MQTT_SUBJECT_LENGTH] = "";
|
||
int cmd = 0;
|
||
|
||
cmd = txt2cmd((char *) payload);
|
||
char *t;
|
||
if (t = strrchr(topic, '/'))
|
||
strncpy(subtopic, t + 1, MQTT_SUBJECT_LENGTH - 1);
|
||
|
||
|
||
|
||
/* No 1-w direct support anymore
|
||
int subchan;
|
||
char buf[17];
|
||
//Check for one-wire address
|
||
if (sscanf(subtopic,"S%1d%16s",&subchan,&buf)==2) // SnXXXXXXXX
|
||
{ DeviceAddress addr;
|
||
SetAddr(buf,addr);;
|
||
PrintBytes(addr,8);
|
||
Serial.print(F(":"));
|
||
Serial.println(subchan);
|
||
cntrl2413(addr,subchan,(cmd==CMD_ON)?1:0);
|
||
}// End OneWire
|
||
|
||
else
|
||
*/
|
||
{
|
||
|
||
Item item(subtopic);
|
||
if (item.isValid()) {
|
||
if (item.itemType == CH_GROUP && retaining)
|
||
return; //Do not restore group channels - they consist not relevant data
|
||
switch (cmd) {
|
||
case 0: {
|
||
short i = 0;
|
||
int Par[3];
|
||
|
||
while (payload && i < 3)
|
||
Par[i++] = getInt((char **) &payload);
|
||
|
||
item.Ctrl(0, i, Par, !retaining);
|
||
}
|
||
break;
|
||
|
||
case -1: //Not known command
|
||
case -2: //JSON input (not implemented yet
|
||
break;
|
||
case -3: //RGB color in #RRGGBB notation
|
||
{
|
||
CRGB rgb;
|
||
if (sscanf((const char*)payload, "#%2X%2X%2X", &rgb.r, &rgb.g, &rgb.b) == 3) {
|
||
int Par[3];
|
||
CHSV hsv = rgb2hsv_approximate(rgb);
|
||
Par[0] = map(hsv.h, 0, 255, 0, 365);
|
||
Par[1] = map(hsv.s, 0, 255, 0, 100);
|
||
Par[2] = map(hsv.v, 0, 255, 0, 100);
|
||
item.Ctrl(0, 3, Par, !retaining);
|
||
}
|
||
break;
|
||
}
|
||
case CMD_ON:
|
||
|
||
// if (item.getEnableCMD(500) || lanStatus == 4)
|
||
item.Ctrl(cmd, 0, NULL,
|
||
!retaining); //Accept ON command not earlier then 500 ms after set settings (Homekit hack)
|
||
// else Serial.println(F("on Skipped"));
|
||
|
||
break;
|
||
default: //some known command
|
||
item.Ctrl(cmd, 0, NULL, !retaining);
|
||
|
||
} //ctrl
|
||
} //valid json
|
||
} //no1wire
|
||
}
|
||
|
||
#ifndef __ESP__
|
||
|
||
void printIPAddress() {
|
||
Serial.print(F("My IP address: "));
|
||
for (byte thisByte = 0; thisByte < 4; thisByte++) {
|
||
Serial.print(Ethernet.localIP()[thisByte], DEC);
|
||
Serial.print(F("."));
|
||
}
|
||
Serial.println();
|
||
}
|
||
|
||
#endif
|
||
|
||
void printMACAddress() {
|
||
Serial.print(F("Configured MAC:"));
|
||
for (byte thisByte = 0; thisByte < 6; thisByte++) {
|
||
Serial.print(mac[thisByte], HEX);
|
||
Serial.print(F(":"));
|
||
}
|
||
Serial.println();
|
||
}
|
||
|
||
void restoreState() {
|
||
// Once connected, publish an announcement... // Once connected, publish an announcement...
|
||
//mqttClient.publish("/myhome/out/RestoreState", "ON");
|
||
};
|
||
|
||
int lanLoop() {
|
||
|
||
#ifdef NOETHER
|
||
lanStatus=-14;
|
||
#endif
|
||
|
||
//Serial.println(lanStatus);
|
||
switch (lanStatus) {
|
||
//Initial state
|
||
case 0: //Ethernet.begin(mac,ip);
|
||
{
|
||
#ifdef __ESP__
|
||
//WiFi.mode(WIFI_STA);
|
||
//wifiMulti.addAP("Smartbox", "");
|
||
if((wifiMulti.run() == WL_CONNECTED)) lanStatus=1;
|
||
#else
|
||
IPAddress ip;
|
||
IPAddress dns;
|
||
IPAddress gw;
|
||
IPAddress mask;
|
||
int res = 1;
|
||
Serial.println(F("Starting lan"));
|
||
if (loadFlash(OFFSET_IP,ip))
|
||
if (loadFlash(OFFSET_DNS,dns))
|
||
if (loadFlash(OFFSET_GW,gw))
|
||
if (loadFlash(OFFSET_MASK,mask)) Ethernet.begin(mac,ip,dns,gw,mask);
|
||
else Ethernet.begin(mac,ip,dns,gw);
|
||
else Ethernet.begin(mac,ip,dns);
|
||
else Ethernet.begin(mac,ip);
|
||
else
|
||
{
|
||
wdt_dis();
|
||
res = Ethernet.begin(mac, 12000);
|
||
wdt_en();
|
||
wdt_res();
|
||
}
|
||
|
||
|
||
if (res == 0) {
|
||
Serial.println(F("Failed to configure Ethernet using DHCP"));
|
||
lanStatus = -10;
|
||
lanCheck = millis() + 60000;
|
||
} else {
|
||
printIPAddress();
|
||
lanStatus = 1;
|
||
}
|
||
|
||
|
||
#endif
|
||
break;
|
||
}
|
||
//Have IP address
|
||
case 1:
|
||
if (!configOk)
|
||
lanStatus = getConfig(0, NULL); //got config from server or load from NVRAM
|
||
else lanStatus = 2;
|
||
#ifdef _artnet
|
||
if (artnet) artnet->begin();
|
||
#endif
|
||
|
||
break;
|
||
case 2: // IP Ready, config loaded, Connecting broker & subscribeArming Watchdog
|
||
wdt_res();
|
||
{
|
||
short n = 0;
|
||
int port = 1883;
|
||
char empty = 0;
|
||
char *user = ∅
|
||
char passwordBuf[16]="";
|
||
char *password = passwordBuf;
|
||
|
||
|
||
if (!mqttClient.connected() && mqttArr && ((n = aJson.getArraySize(mqttArr)) > 1)) {
|
||
char *client_id = aJson.getArrayItem(mqttArr, 0)->valuestring;
|
||
char *servername = aJson.getArrayItem(mqttArr, 1)->valuestring;
|
||
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
||
if (n >= 4) user = aJson.getArrayItem(mqttArr, 3)->valuestring;
|
||
if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf,sizeof(passwordBuf)) && (n >= 5))
|
||
{
|
||
password = aJson.getArrayItem(mqttArr, 4)->valuestring;
|
||
Serial.println(F("Using MQTT password from config"));
|
||
}
|
||
|
||
mqttClient.setServer(servername, port);
|
||
mqttClient.setCallback(mqttCallback);
|
||
|
||
Serial.print(F("Attempting MQTT connection to "));
|
||
Serial.print(servername);
|
||
Serial.print(F(":"));
|
||
Serial.print(port);
|
||
Serial.print(F(" user:"));
|
||
Serial.print(user);
|
||
Serial.print(F(" ..."));
|
||
|
||
wdt_dis(); //potential unsafe for ethernetIdle(), but needed to avoid cyclic reboot if mosquitto out of order
|
||
if (mqttClient.connect(client_id, user, password)) {
|
||
Serial.print(F("connected as "));
|
||
Serial.println(client_id);
|
||
wdt_en();
|
||
configOk=true;
|
||
// ... Temporary subscribe to status topic
|
||
char buf[MQTT_TOPIC_LENGTH];
|
||
|
||
strncpy_P(buf, outprefix, sizeof(buf));
|
||
strncat(buf, "#", sizeof(buf));
|
||
mqttClient.subscribe(buf);
|
||
|
||
//Subscribing for command topics
|
||
strncpy_P(buf, inprefix, sizeof(buf));
|
||
strncat(buf, "#", sizeof(buf));
|
||
mqttClient.subscribe(buf);
|
||
|
||
//restoreState();
|
||
// if (_once) {DMXput(); _once=0;}
|
||
lanStatus = 4;
|
||
lanCheck = millis() + 5000;
|
||
Serial.println(F("Awaiting for retained topics"));
|
||
} else {
|
||
Serial.print(F("failed, rc="));
|
||
Serial.print(mqttClient.state());
|
||
Serial.println(F(" try again in 5 seconds"));
|
||
lanCheck = millis() + 5000;
|
||
lanStatus = 12;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case 4: //retaining ... Collecting
|
||
if (millis() > lanCheck) {
|
||
char buf[MQTT_TOPIC_LENGTH];
|
||
|
||
//Unsubscribe from status topics..
|
||
strncpy_P(buf, outprefix, sizeof(buf));
|
||
strncat(buf, "#", sizeof(buf));
|
||
mqttClient.unsubscribe(buf);
|
||
|
||
lanStatus = 3;
|
||
Serial.println(F("Accepting commands..."));
|
||
break;
|
||
}
|
||
|
||
case 3: //operation
|
||
if (!mqttClient.connected()) lanStatus = 2;
|
||
break;
|
||
|
||
//Awaiting address
|
||
case -10:
|
||
if (millis() > lanCheck)
|
||
lanStatus = 0;
|
||
break;
|
||
//Reconnect
|
||
case 12:
|
||
if (millis() > lanCheck)
|
||
|
||
lanStatus = 2;
|
||
break;
|
||
// read or Re-read config
|
||
case -11:
|
||
if (loadConfigFromEEPROM(0, NULL)) lanStatus = 2;
|
||
else {
|
||
lanCheck = millis() + 5000;
|
||
lanStatus = -10;
|
||
}
|
||
break;
|
||
|
||
case -14:;
|
||
// do notghing with net
|
||
}
|
||
|
||
|
||
{
|
||
#ifndef __ESP__
|
||
wdt_dis();
|
||
if (lanStatus > 0)
|
||
switch (Ethernet.maintain()) {
|
||
case NO_LINK:
|
||
Serial.println(F("No link"));
|
||
if (mqttClient.connected()) mqttClient.disconnect();
|
||
lanStatus = -10;
|
||
break;
|
||
case DHCP_CHECK_RENEW_FAIL:
|
||
//renewed fail
|
||
Serial.println(F("Error: renewed fail"));
|
||
if (mqttClient.connected()) mqttClient.disconnect();
|
||
lanStatus = -10;
|
||
break;
|
||
|
||
case DHCP_CHECK_RENEW_OK:
|
||
Serial.println(F("Renewed success"));
|
||
printIPAddress();
|
||
break;
|
||
|
||
case DHCP_CHECK_REBIND_FAIL:
|
||
Serial.println(F("Error: rebind fail"));
|
||
if (mqttClient.connected()) mqttClient.disconnect();
|
||
lanStatus = -10;
|
||
break;
|
||
|
||
case DHCP_CHECK_REBIND_OK:
|
||
Serial.println(F("Rebind success"));
|
||
printIPAddress();
|
||
break;
|
||
|
||
default:
|
||
//nothing happened
|
||
break;
|
||
|
||
}
|
||
|
||
wdt_en();
|
||
#endif
|
||
}
|
||
|
||
return lanStatus;
|
||
|
||
}
|
||
|
||
#ifdef _owire
|
||
|
||
void Changed(int i, DeviceAddress addr, int val) {
|
||
char addrstr[32] = "NIL";
|
||
char addrbuf[17];
|
||
char valstr[16] = "NIL";
|
||
char *owEmit = NULL;
|
||
char *owItem = NULL;
|
||
|
||
//PrintBytes(addr,8);
|
||
// Serial.print("Emit: ");
|
||
SetBytes(addr, 8, addrbuf);
|
||
addrbuf[17] = 0;
|
||
|
||
//Serial.println(addrbuf);
|
||
|
||
aJsonObject *owObj = aJson.getObjectItem(owArr, addrbuf);
|
||
if (owObj) {
|
||
owEmit = aJson.getObjectItem(owObj, "emit")->valuestring;
|
||
if (owEmit) {
|
||
strncpy(addrbuf, owEmit, sizeof(addrbuf));
|
||
Serial.print(owEmit);
|
||
Serial.print(F("="));
|
||
Serial.println(val);
|
||
}
|
||
owItem = aJson.getObjectItem(owObj, "item")->valuestring;
|
||
} else Serial.println(F("Not find"));
|
||
|
||
|
||
/* No sw support anymore
|
||
switch (addr[0]){
|
||
case 0x29: // DS2408
|
||
snprintf(addrstr,sizeof(addrstr),"%sS0%s",outprefix,addrbuf);
|
||
// Serial.println(addrstr);
|
||
client.publish(addrstr, (val & SW_STAT0)?"ON":"OFF");
|
||
snprintf(addrstr,sizeof(addrstr),"%sS1%s",outprefix,addrbuf);
|
||
// Serial.println(addrstr);
|
||
client.publish(addrstr, (val & SW_STAT1)?"ON":"OFF");
|
||
snprintf(addrstr,sizeof(addrstr),"%sS2%s",outprefix,addrbuf);
|
||
// Serial.println(addrstr);
|
||
client.publish(addrstr, (val & SW_AUX0)?"OFF":"ON");
|
||
snprintf(addrstr,sizeof(addrstr),"%sS3%s",outprefix,addrbuf);
|
||
// Serial.println(addrstr);
|
||
client.publish(addrstr, (val & SW_AUX1)?"OFF":"ON");
|
||
break;
|
||
|
||
case 0x28: // Thermomerer
|
||
|
||
snprintf(addrstr,sizeof(addrstr),"%s%s",outprefix,addrbuf);
|
||
sprintf(valstr,"%d",val);
|
||
//Serial.println(val);
|
||
//Serial.println(valstr);
|
||
client.publish(addrstr, valstr);
|
||
|
||
if (owItem)
|
||
{
|
||
thermoSetCurTemp(owItem,val);
|
||
}
|
||
break;
|
||
|
||
case 0x01:
|
||
case 0x81:
|
||
snprintf(addrstr,sizeof(addrstr),"%sDS%s",outprefix,addrbuf);
|
||
if (val) sprintf(valstr,"%s","ON"); else sprintf(valstr,"%s","OFF");
|
||
client.publish(addrstr, valstr);
|
||
}
|
||
*/
|
||
|
||
if ((val == -127) || (val == 85) || (val == 0)) { //ToDo: 1-w short circuit mapped to "0" celsium
|
||
// Serial.print("Temp err ");Serial.println(t);
|
||
return;
|
||
}
|
||
|
||
strcpy_P(addrstr, outprefix);
|
||
strncat(addrstr, addrbuf, sizeof(addrstr));
|
||
//snprintf(addrstr,sizeof(addrstr),"%s%s",F(outprefix),addrbuf);
|
||
sprintf(valstr, "%d", val);
|
||
mqttClient.publish(addrstr, valstr);
|
||
|
||
if (owItem) {
|
||
thermoSetCurTemp(owItem, val); ///TODO: Refactore using Items interface
|
||
}
|
||
}
|
||
|
||
#endif //_owire
|
||
|
||
|
||
void cmdFunctionHelp(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{
|
||
printFirmwareVersionAndBuildOptions();
|
||
Serial.println(F("Use the commands: 'help' - this text\n"
|
||
"'mac de:ad:be:ef:fe:00' set and store MAC-address in EEPROM\n"
|
||
"'ip [ip[,dns[,gw[,subnet]]]]' - set static IP\n"
|
||
"'save' - save config in NVRAM\n"
|
||
"'get' [config addr]' - get config from pre-configured URL and store addr\n"
|
||
"'load' - load config from NVRAM\n"
|
||
"'pwd' - define MQTT password\n"
|
||
"'kill' - test watchdog"));
|
||
}
|
||
|
||
void cmdFunctionKill(int arg_cnt, char **args) {
|
||
for (short i = 1; i < 20; i++) {
|
||
delay(1000);
|
||
Serial.println(i);
|
||
};
|
||
}
|
||
|
||
void applyConfig() {
|
||
if (!root) return;
|
||
#ifdef _dmxout
|
||
int maxChannels;
|
||
aJsonObject *dmxoutArr = aJson.getObjectItem(root, "dmx");
|
||
if (dmxoutArr && aJson.getArraySize(dmxoutArr) == 2) {
|
||
DMXoutSetup(maxChannels = aJson.getArrayItem(dmxoutArr, 1)->valueint,
|
||
aJson.getArrayItem(dmxoutArr, 0)->valueint);
|
||
Serial.print(F("DMX out started. Channels: "));
|
||
Serial.println(maxChannels);
|
||
}
|
||
#endif
|
||
#ifdef _dmxin
|
||
int itemsCount;
|
||
dmxArr = aJson.getObjectItem(root, "dmxin");
|
||
if (dmxArr && (itemsCount = aJson.getArraySize(dmxArr))) {
|
||
DMXinSetup(itemsCount * 4);
|
||
Serial.print(F("DMX in started. Channels:"));
|
||
Serial.println(itemsCount * 4);
|
||
}
|
||
#endif
|
||
#ifdef _modbus
|
||
modbusArr = aJson.getObjectItem(root, "modbus");
|
||
#endif
|
||
|
||
#ifdef _owire
|
||
owArr = aJson.getObjectItem(root, "ow");
|
||
#endif
|
||
|
||
#ifdef _owire
|
||
if (owArr && !owReady) {
|
||
aJsonObject *item = owArr->child;
|
||
owReady = owSetup(&Changed);
|
||
t_count = 0;
|
||
while (item && owReady) {
|
||
if ((item->type == aJson_Object)) {
|
||
DeviceAddress addr;
|
||
//Serial.print(F("Add:")),Serial.println(item->name);
|
||
SetAddr(item->name, addr);
|
||
owAdd(addr);
|
||
}
|
||
item = item->next;
|
||
}
|
||
}
|
||
#endif
|
||
items = aJson.getObjectItem(root, "items");
|
||
|
||
// Digital output related Items initialization
|
||
pollingItem=NULL;
|
||
if (items) {
|
||
aJsonObject * item = items->child;
|
||
while (items && item)
|
||
if (item->type == aJson_Array && aJson.getArraySize(item)>1) {
|
||
Item it(item);
|
||
if (it.isValid()) {
|
||
int pin=it.getArg();
|
||
int cmd = it.getCmd();
|
||
switch (it.itemType) {
|
||
case CH_THERMO:
|
||
if (cmd<1) it.setCmd(CMD_OFF);
|
||
case CH_RELAY:
|
||
{
|
||
int k;
|
||
pinMode(pin, OUTPUT);
|
||
digitalWrite(pin, k = ((cmd == CMD_ON) ? HIGH : LOW));
|
||
Serial.print(F("Pin:"));
|
||
Serial.print(pin);
|
||
Serial.print(F("="));
|
||
Serial.println(k);
|
||
}
|
||
break;
|
||
} //switch
|
||
} //isValid
|
||
item = item->next;
|
||
} //if
|
||
pollingItem = items->child;
|
||
}
|
||
inputs = aJson.getObjectItem(root, "in");
|
||
mqttArr = aJson.getObjectItem(root, "mqtt");
|
||
printConfigSummary();
|
||
}
|
||
|
||
void printConfigSummary() {
|
||
Serial.println(F("Configured:"));
|
||
Serial.print(F("items "));
|
||
printBool(items);
|
||
Serial.print(F("inputs "));
|
||
printBool(inputs);
|
||
Serial.print(F("modbus "));
|
||
printBool(modbusArr);
|
||
Serial.print(F("mqtt "));
|
||
printBool(mqttArr);
|
||
Serial.print(F("1-wire "));
|
||
printBool(owArr);
|
||
}
|
||
|
||
void cmdFunctionLoad(int arg_cnt, char **args) {
|
||
loadConfigFromEEPROM(arg_cnt, args);
|
||
restoreState();
|
||
}
|
||
|
||
int loadConfigFromEEPROM(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{
|
||
char ch;
|
||
Serial.println(F("loading Config"));
|
||
|
||
ch = EEPROM.read(EEPROM_offset);
|
||
if (ch == '{') {
|
||
aJsonEEPROMStream as = aJsonEEPROMStream(EEPROM_offset);
|
||
aJson.deleteItem(root);
|
||
root = aJson.parse(&as);
|
||
Serial.println();
|
||
if (!root) {
|
||
Serial.println(F("load failed"));
|
||
return 0;
|
||
}
|
||
Serial.println(F("Loaded"));
|
||
applyConfig();
|
||
ethClient.stop(); //Refresh MQTT connect to get retained info
|
||
return 1;
|
||
} else {
|
||
Serial.println(F("No stored config"));
|
||
return 0;
|
||
|
||
}
|
||
}
|
||
|
||
void cmdFunctionReq(int arg_cnt, char **args) {
|
||
mqttConfigRequest(arg_cnt, args);
|
||
restoreState();
|
||
}
|
||
|
||
|
||
int mqttConfigRequest(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{
|
||
char buf[25] = "/";
|
||
Serial.println(F("request MQTT Config"));
|
||
SetBytes((uint8_t *) mac, 6, buf + 1);
|
||
buf[13] = 0;
|
||
strncat(buf, "/resp/#", 25);
|
||
Serial.println(buf);
|
||
mqttClient.subscribe(buf);
|
||
buf[13] = 0;
|
||
strncat(buf, "/req/conf", 25);
|
||
Serial.println(buf);
|
||
mqttClient.publish(buf, "1");
|
||
|
||
}
|
||
|
||
|
||
int mqttConfigResp(char *as) {
|
||
Serial.println(F("got MQTT Config"));
|
||
|
||
//aJsonEEPROMStream as=aJsonEEPROMStream(EEPROM_offset);
|
||
|
||
//aJson.deleteItem(root);
|
||
root = aJson.parse(as);
|
||
Serial.println();
|
||
if (!root) {
|
||
Serial.println(F("load failed"));
|
||
return 0;
|
||
}
|
||
Serial.println(F("Loaded"));
|
||
applyConfig();
|
||
return 1;
|
||
}
|
||
|
||
void cmdFunctionSave(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{
|
||
aJsonEEPROMStream jsonEEPROMStream = aJsonEEPROMStream(EEPROM_offset);
|
||
Serial.println(F("Saving config to EEPROM.."));
|
||
aJson.print(root, &jsonEEPROMStream);
|
||
jsonEEPROMStream.putEOF();
|
||
Serial.println(F("Saved to EEPROM"));
|
||
}
|
||
|
||
void cmdFunctionIp(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{ IPAddress ip0 (0,0,0,0);
|
||
IPAddress ip;
|
||
DNSClient dns;
|
||
switch (arg_cnt) {
|
||
case 5: if (dns.inet_aton(args[4],ip)) saveFlash(OFFSET_MASK,ip); else saveFlash(OFFSET_MASK,ip0);
|
||
case 4: if (dns.inet_aton(args[3],ip)) saveFlash(OFFSET_GW,ip); else saveFlash(OFFSET_GW,ip0);
|
||
case 3: if (dns.inet_aton(args[2],ip)) saveFlash(OFFSET_DNS,ip); else saveFlash(OFFSET_DNS,ip0);
|
||
case 2: if (dns.inet_aton(args[1],ip)) saveFlash(OFFSET_IP,ip); else saveFlash(OFFSET_IP,ip0);
|
||
break;
|
||
case 1: //dynamic IP
|
||
saveFlash(OFFSET_IP,ip0);
|
||
}
|
||
Serial.println(F("Saved"));
|
||
}
|
||
|
||
void cmdFunctionPwd(int arg_cnt, char **args)
|
||
//(char* tokens)
|
||
{ char empty[]="";
|
||
if (arg_cnt)
|
||
saveFlash(OFFSET_MQTT_PWD,args[1]);
|
||
else saveFlash(OFFSET_MQTT_PWD,empty);
|
||
Serial.println(F("Password updated"));
|
||
}
|
||
|
||
void cmdFunctionSetMac(int arg_cnt, char **args) {
|
||
|
||
//Serial.print("Got:");
|
||
//Serial.println(args[1]);
|
||
if (sscanf(args[1], "%x:%x:%x:%x:%x:%x%с",
|
||
&mac[0],
|
||
&mac[1],
|
||
&mac[2],
|
||
&mac[3],
|
||
&mac[4],
|
||
&mac[5]) < 6) {
|
||
Serial.print(F("could not parse: "));
|
||
Serial.println(args[1]);
|
||
return;
|
||
}
|
||
printMACAddress();
|
||
for (short i = 0; i < 6; i++) { EEPROM.write(i, mac[i]); }
|
||
Serial.println(F("Updated"));
|
||
}
|
||
|
||
void cmdFunctionGet(int arg_cnt, char **args) {
|
||
lanStatus=getConfig(arg_cnt, args);
|
||
ethClient.stop(); //Refresh MQTT connect to get retained info
|
||
//restoreState();
|
||
}
|
||
|
||
void printBool(bool arg) { (arg) ? Serial.println(F("on")) : Serial.println(F("off")); }
|
||
|
||
|
||
void saveFlash(short n, char *str) {
|
||
short i;
|
||
short len=strlen(str);
|
||
if (len>31) len=31;
|
||
for(int i=0;i<len;i++) EEPROM.write(n+i,str[i]);
|
||
EEPROM.write(n+len,0);
|
||
}
|
||
|
||
int loadFlash(short n, char *str, short l) {
|
||
short i;
|
||
uint8_t ch = EEPROM.read(n);
|
||
if (!ch || (ch == 0xff)) return 0;
|
||
for (i=0;i<l-1 && (str[i] = EEPROM.read(n++));i++);
|
||
str[i]=0;
|
||
return 1;
|
||
}
|
||
|
||
void saveFlash(short n, IPAddress& ip) {
|
||
for(int i=0;i<4;i++) EEPROM.write(n++,ip[i]);
|
||
}
|
||
|
||
int loadFlash(short n, IPAddress& ip) {
|
||
for(int i=0;i<4;i++) ip[i]=EEPROM.read(n++);
|
||
if (ip[0] && (ip[0] != 0xff)) return 1;
|
||
return 0;
|
||
}
|
||
|
||
int getConfig(int arg_cnt, char **args)
|
||
//(char *tokens)
|
||
{
|
||
|
||
|
||
int responseStatusCode = 0;
|
||
char ch;
|
||
char URI[40];
|
||
char configServer[32]="";
|
||
if (arg_cnt > 1) {
|
||
strncpy(configServer, args[1], sizeof(configServer) - 1);
|
||
saveFlash(OFFSET_CONFIGSERVER, configServer);
|
||
} else if (!loadFlash(OFFSET_CONFIGSERVER, configServer))
|
||
strncpy_P(configServer,configserver,sizeof(configServer));
|
||
|
||
snprintf(URI, sizeof(URI), "/%02x-%02x-%02x-%02x-%02x-%02x.config.json", mac[0], mac[1], mac[2], mac[3], mac[4],
|
||
mac[5]);
|
||
Serial.print(F("Config URI: http://"));
|
||
Serial.print(configServer);
|
||
Serial.println(URI);
|
||
|
||
#if defined(__AVR__)
|
||
FILE *result;
|
||
//byte hserver[] = { 192,168,88,2 };
|
||
wdt_dis();
|
||
|
||
HTTPClient hclient(configServer, 80);
|
||
// FILE is the return STREAM type of the HTTPClient
|
||
result = hclient.getURI(URI);
|
||
responseStatusCode = hclient.getLastReturnCode();
|
||
wdt_en();
|
||
|
||
if (result != NULL) {
|
||
if (responseStatusCode == 200) {
|
||
|
||
Serial.println(F("got Config"));
|
||
aJsonFileStream as = aJsonFileStream(result);
|
||
noInterrupts();
|
||
aJson.deleteItem(root);
|
||
root = aJson.parse(&as);
|
||
interrupts();
|
||
// Serial.println(F("Parsed."));
|
||
hclient.closeStream(result); // this is very important -- be sure to close the STREAM
|
||
|
||
if (!root) {
|
||
Serial.println(F("Config parsing failed"));
|
||
lanCheck = millis() + 15000;
|
||
return -11;
|
||
} else {
|
||
// char *outstr = aJson.print(root);
|
||
// Serial.println(outstr);
|
||
// free(outstr);
|
||
Serial.println(F("Applying."));
|
||
applyConfig();
|
||
|
||
|
||
}
|
||
|
||
} else {
|
||
Serial.print(F("ERROR: Server returned "));
|
||
Serial.println(responseStatusCode);
|
||
lanCheck = millis() + 5000;
|
||
return -11;
|
||
}
|
||
|
||
} else {
|
||
Serial.println(F("failed to connect"));
|
||
Serial.println(F(" try again in 5 seconds"));
|
||
lanCheck = millis() + 5000;
|
||
return -11;
|
||
}
|
||
|
||
#else
|
||
//Non AVR code
|
||
String response;
|
||
EthernetClient configEthClient;
|
||
HttpClient htclient = HttpClient(configEthClient, configServer, 80);
|
||
//htclient.stop(); //_socket =MAX
|
||
htclient.setHttpResponseTimeout(4000);
|
||
wdt_res();
|
||
//Serial.println("making GET request");get
|
||
htclient.beginRequest();
|
||
htclient.get(URI);
|
||
htclient.endRequest();
|
||
|
||
|
||
// read the status code and body of the response
|
||
responseStatusCode = htclient.responseStatusCode();
|
||
response = htclient.responseBody();
|
||
htclient.stop();
|
||
wdt_res();
|
||
Serial.print(F("HTTP Status code: "));
|
||
Serial.println(responseStatusCode);
|
||
//Serial.print("GET Response: ");
|
||
|
||
if (responseStatusCode == 200) {
|
||
aJson.deleteItem(root);
|
||
root = aJson.parse((char *) response.c_str());
|
||
|
||
if (!root) {
|
||
Serial.println(F("Config parsing failed"));
|
||
// lanCheck=millis()+15000;
|
||
return -11; //Load from NVRAM
|
||
} else {
|
||
/*
|
||
char * outstr=aJson.print(root);
|
||
Serial.println(outstr);
|
||
free (outstr);
|
||
*/
|
||
Serial.println(response);
|
||
applyConfig();
|
||
|
||
|
||
}
|
||
} else {
|
||
Serial.println(F("Config retrieving failed"));
|
||
//lanCheck=millis()+15000;
|
||
return -11; //Load from NVRAM
|
||
}
|
||
|
||
|
||
#endif
|
||
return 2;
|
||
}
|
||
|
||
void preTransmission() {
|
||
#ifdef CONTROLLINO
|
||
// set DE and RE on HIGH
|
||
PORTJ |= B01100000;
|
||
#else
|
||
digitalWrite(TXEnablePin, 1);
|
||
#endif
|
||
}
|
||
|
||
void postTransmission() {
|
||
#ifdef CONTROLLINO
|
||
// set DE and RE on LOW
|
||
PORTJ &= B10011111;
|
||
#else
|
||
digitalWrite(TXEnablePin, 0);
|
||
#endif
|
||
}
|
||
//#define PIO_SRC_REV commit 8034a6b765229d94a94d90fd08dd9588acf5f3da Author: livello <livello@bk.ru> Date: Wed Mar 28 02:35:50 2018 +0300 refactoring
|
||
|
||
void setup_main() {
|
||
setupCmdArduino();
|
||
printFirmwareVersionAndBuildOptions();
|
||
|
||
#ifdef SD_CARD_INSERTED
|
||
sd_card_w5100_setup();
|
||
#endif
|
||
|
||
#ifdef __ESP__
|
||
espSetup();
|
||
#endif
|
||
|
||
setupMacAddress();
|
||
|
||
loadConfigFromEEPROM(0, NULL);
|
||
|
||
#ifdef _modbus
|
||
#ifdef CONTROLLINO
|
||
//set PORTJ pin 5,6 direction (RE,DE)
|
||
DDRJ |= B01100000;
|
||
//set RE,DE on LOW
|
||
PORTJ &= B10011111;
|
||
#else
|
||
pinMode(TXEnablePin, OUTPUT);
|
||
#endif
|
||
modbusSerial.begin(MODBUS_SERIAL_BAUD);
|
||
node.idle(&modbusIdle);
|
||
// Callbacks allow us to configure the RS485 transceiver correctly
|
||
node.preTransmission(preTransmission);
|
||
node.postTransmission(postTransmission);
|
||
#endif
|
||
|
||
delay(20);
|
||
owReady = 0;
|
||
|
||
#ifdef _owire
|
||
if (net) net->idle(&owIdle);
|
||
#endif
|
||
|
||
mqttClient.setCallback(mqttCallback);
|
||
|
||
#ifdef _artnet
|
||
ArtnetSetup();
|
||
#endif
|
||
/*
|
||
SPI.begin();
|
||
while (Ethernet.maintain() == NO_LINK && millis()<3000UL) {delay(500);Serial.print(F("."));}
|
||
*/
|
||
//delay(1000); //Wiz5500
|
||
//TODO: checkForRemoteSketchUpdate();
|
||
}
|
||
|
||
void printFirmwareVersionAndBuildOptions() {
|
||
Serial.print(F("\nLazyhome.ru LightHub controller "));
|
||
Serial.println(F(QUOTE(PIO_SRC_REV)));
|
||
#ifdef WATCH_DOG_TICKER_DISABLE
|
||
Serial.println(F("(-)WATCHDOG"));
|
||
#else
|
||
Serial.println(F("(+)WATCHDOG"));
|
||
#endif
|
||
Serial.print(F("Config server:"));
|
||
Serial.println(F(CONFIG_SERVER));
|
||
Serial.print(F("Firmware MAC Address "));
|
||
Serial.println(F(QUOTE(CUSTOM_FIRMWARE_MAC))); //Q Macros didn't working with 6 args
|
||
#ifdef DISABLE_FREERAM_PRINT
|
||
Serial.println(F("(-)FreeRam printing"));
|
||
#else
|
||
Serial.println(F("(+)FreeRam printing"));
|
||
#endif
|
||
|
||
#ifdef USE_1W_PIN
|
||
Serial.print(F("(-)DS2482-100 USE_1W_PIN="));
|
||
Serial.println(QUOTE(USE_1W_PIN));
|
||
#else
|
||
Serial.println(F("(+)DS2482-100"));
|
||
#endif
|
||
|
||
#ifdef Wiz5500
|
||
Serial.println(F("(+)WizNet5500"));
|
||
#endif
|
||
|
||
#ifdef DMX_DISABLE
|
||
Serial.println(F("(-)DMX"));
|
||
#else
|
||
Serial.println(F("(+)DMX"));
|
||
#endif
|
||
|
||
#ifdef MODBUS_DISABLE
|
||
Serial.println(F("(-)MODBUS"));
|
||
#else
|
||
Serial.println(F("(+)MODBUS"));
|
||
#endif
|
||
|
||
#ifdef OWIRE_DISABLE
|
||
Serial.println(F("(-)OWIRE"));
|
||
#else
|
||
Serial.println(F("(+)OWIRE"));
|
||
#endif
|
||
|
||
#ifdef SD_CARD_INSERTED
|
||
Serial.println(F("(+)SDCARD"));
|
||
#endif
|
||
|
||
|
||
}
|
||
|
||
void setupMacAddress() {
|
||
|
||
#ifdef DEFAULT_FIRMWARE_MAC
|
||
byte firmwareMacAddress[6] = DEFAULT_FIRMWARE_MAC;//comma(,) separated hex-array, hard-coded
|
||
#endif
|
||
|
||
#ifdef CUSTOM_FIRMWARE_MAC
|
||
byte firmwareMacAddress[6];
|
||
const char *macStr = QUOTE(CUSTOM_FIRMWARE_MAC);//colon(:) separated from build options
|
||
parseBytes(macStr, ':', firmwareMacAddress, 6, 16);
|
||
#endif
|
||
|
||
bool isMacValid = false;
|
||
for (short i = 0; i < 6; i++) {
|
||
mac[i] = EEPROM.read(i);
|
||
if (mac[i] != 0 && mac[i] != 0xff) isMacValid = true;
|
||
}
|
||
if (!isMacValid) {
|
||
Serial.println(F("Invalid MAC: set firmware's MAC"));
|
||
memcpy(mac, firmwareMacAddress, 6);
|
||
}
|
||
printMACAddress();
|
||
}
|
||
|
||
void setupCmdArduino() {
|
||
cmdInit(uint32_t(SERIAL_BAUD));
|
||
cmdAdd("help", cmdFunctionHelp);
|
||
cmdAdd("save", cmdFunctionSave);
|
||
cmdAdd("load", cmdFunctionLoad);
|
||
cmdAdd("get", cmdFunctionGet);
|
||
cmdAdd("mac", cmdFunctionSetMac);
|
||
cmdAdd("kill", cmdFunctionKill);
|
||
cmdAdd("req", cmdFunctionReq);
|
||
cmdAdd("ip", cmdFunctionIp);
|
||
cmdAdd("pwd", cmdFunctionPwd);
|
||
}
|
||
|
||
void loop_main() {
|
||
wdt_res();
|
||
cmdPoll();
|
||
if (lanLoop() > 1) {
|
||
mqttClient.loop();
|
||
#ifdef _artnet
|
||
if (artnet) artnet->read();
|
||
#endif
|
||
}
|
||
|
||
#ifdef _owire
|
||
if (owReady && owArr) owLoop();
|
||
#endif
|
||
|
||
#ifdef _dmxin
|
||
// unsigned long lastpacket = DMXSerial.noDataSince();
|
||
DMXCheck();
|
||
#endif
|
||
// if (lastpacket && (lastpacket%10==0)) Serial.println(lastpacket);
|
||
|
||
if (items) {
|
||
if (lanStatus != 4) pollingLoop();
|
||
#ifdef _owire
|
||
thermoLoop();
|
||
#endif
|
||
}
|
||
|
||
|
||
inputLoop();
|
||
|
||
#if defined (_espdmx)
|
||
dmxout.update();
|
||
#endif
|
||
}
|
||
|
||
void owIdle(void) {
|
||
#ifdef _artnet
|
||
if (artnet) artnet->read();
|
||
#endif
|
||
|
||
wdt_res();
|
||
return; //TODO: unreached code
|
||
Serial.print(F("o"));
|
||
if (lanLoop() == 1) mqttClient.loop();
|
||
//if (owReady) owLoop();
|
||
|
||
#ifdef _dmxin
|
||
DMXCheck();
|
||
#endif
|
||
|
||
#if defined (_espdmx)
|
||
dmxout.update();
|
||
#endif
|
||
}
|
||
void ethernetIdle(void){
|
||
wdt_res();
|
||
inputLoop();
|
||
// Serial.print(".");
|
||
};
|
||
|
||
void modbusIdle(void) {
|
||
wdt_res();
|
||
if (lanLoop() > 1) {
|
||
mqttClient.loop();
|
||
#ifdef _artnet
|
||
if (artnet) artnet->read();
|
||
#endif
|
||
inputLoop();
|
||
}
|
||
|
||
|
||
#ifdef _dmxin
|
||
DMXCheck();
|
||
#endif
|
||
|
||
#if defined (_espdmx)
|
||
dmxout.update();
|
||
#endif
|
||
}
|
||
|
||
void inputLoop(void) {
|
||
if (!inputs) return;
|
||
if (millis() > nextInputCheck) {
|
||
aJsonObject *input = inputs->child;
|
||
while (input) {
|
||
if ((input->type == aJson_Object)) {
|
||
Input in(input);
|
||
in.Poll();
|
||
}
|
||
input = input->next;
|
||
}
|
||
nextInputCheck = millis() + INTERVAL_CHECK_INPUT;
|
||
}
|
||
}
|
||
|
||
void pollingLoop(void) {
|
||
boolean done = false;
|
||
if (millis() > nextPollingCheck) {
|
||
while (pollingItem && !done) {
|
||
if (pollingItem->type == aJson_Array) {
|
||
Item it(pollingItem);
|
||
nextPollingCheck = millis() + it.Poll(); //INTERVAL_CHECK_MODBUS;
|
||
done = true;
|
||
}//if
|
||
pollingItem = pollingItem->next;
|
||
if (!pollingItem) {
|
||
pollingItem = items->child;
|
||
return;
|
||
} //start from 1-st element
|
||
} //while
|
||
}//if
|
||
}
|
||
|
||
|
||
//TODO: refactoring
|
||
|
||
void thermoLoop(void) {
|
||
if (millis() < nextThermostatCheck)
|
||
return;
|
||
|
||
bool thermostatCheckPrinted = false;
|
||
aJsonObject *item = items->child;
|
||
|
||
while (item) {
|
||
if ((item->type == aJson_Array) && (aJson.getArrayItem(item, 0)->valueint == CH_THERMO) &&
|
||
(aJson.getArraySize(item) > 4)) {
|
||
int itemPin = aJson.getArrayItem(item, I_ARG)->valueint;
|
||
int itemTempSetting = aJson.getArrayItem(item, I_VAL)->valueint;
|
||
int itemCommand = aJson.getArrayItem(item, I_CMD)->valueint;
|
||
aJsonObject *itemExtensionArray = aJson.getArrayItem(item, I_EXT);
|
||
|
||
if (itemExtensionArray && (aJson.getArraySize(itemExtensionArray) > 1)) {
|
||
int curtemp = aJson.getArrayItem(itemExtensionArray, IET_TEMP)->valueint;
|
||
if (!aJson.getArrayItem(itemExtensionArray, IET_ATTEMPTS)->valueint) {
|
||
Serial.print(item->name);
|
||
Serial.println(F(" Expired"));
|
||
|
||
} else {
|
||
if (!(--aJson.getArrayItem(itemExtensionArray, IET_ATTEMPTS)->valueint))
|
||
mqttClient.publish("/alarm/snsr", item->name);
|
||
|
||
}
|
||
if (curtemp > THERMO_OVERHEAT_CELSIUS) mqttClient.publish("/alarm/ovrht", item->name);
|
||
|
||
thermostatCheckPrinted = true;
|
||
Serial.print(item->name);
|
||
Serial.print(F(" Set:"));
|
||
Serial.print(itemTempSetting);
|
||
Serial.print(F(" Curtemp:"));
|
||
Serial.print(curtemp);
|
||
Serial.print(F(" cmd:"));
|
||
Serial.print(itemCommand), pinMode(itemPin, OUTPUT);
|
||
if (itemCommand == CMD_OFF || itemCommand == CMD_HALT ||
|
||
aJson.getArrayItem(itemExtensionArray, IET_ATTEMPTS)->valueint == 0) {
|
||
digitalWrite(itemPin, LOW);
|
||
Serial.println(F(" OFF"));
|
||
} else {
|
||
if (curtemp + THERMO_GIST_CELSIUS < itemTempSetting) {
|
||
digitalWrite(itemPin, HIGH);
|
||
Serial.println(F(" ON"));
|
||
} //too cold
|
||
else if (itemTempSetting <= curtemp) {
|
||
digitalWrite(itemPin, LOW);
|
||
Serial.println(F(" OFF"));
|
||
} //Reached settings
|
||
else Serial.println(F(" --")); // Nothing to do
|
||
}
|
||
}
|
||
}
|
||
item = item->next;
|
||
}
|
||
|
||
nextThermostatCheck = millis() + THERMOSTAT_CHECK_PERIOD;
|
||
|
||
#ifndef DISABLE_FREERAM_PRINT
|
||
(thermostatCheckPrinted) ? Serial.print(F("\nfree:")) : Serial.print(F(" "));
|
||
Serial.print(freeRam());
|
||
Serial.print(" ");
|
||
#endif
|
||
}
|
||
|
||
|
||
short thermoSetCurTemp(char *name, short t) {
|
||
if (items) {
|
||
aJsonObject *item = aJson.getObjectItem(items, name);
|
||
if (item && (item->type == aJson_Array) && (aJson.getArrayItem(item, I_TYPE)->valueint == CH_THERMO) &&
|
||
(aJson.getArraySize(item) >= 4)) {
|
||
aJsonObject *extArray = NULL;
|
||
|
||
if (aJson.getArraySize(item) == 4) //No thermo extension yet
|
||
{
|
||
extArray = aJson.createArray(); //Create Ext Array
|
||
|
||
aJsonObject *ocurt = aJson.createItem(t); //Create int
|
||
aJsonObject *oattempts = aJson.createItem(T_ATTEMPTS); //Create int
|
||
aJson.addItemToArray(extArray, ocurt);
|
||
aJson.addItemToArray(extArray, oattempts);
|
||
aJson.addItemToArray(item, extArray); //Adding to item
|
||
} //if
|
||
else if (extArray = aJson.getArrayItem(item, I_EXT)) {
|
||
aJsonObject *att = aJson.getArrayItem(extArray, IET_ATTEMPTS);
|
||
aJson.getArrayItem(extArray, IET_TEMP)->valueint = t;
|
||
if (att->valueint == 0) mqttClient.publish("/alarmoff/snsr", item->name);
|
||
att->valueint = (int) T_ATTEMPTS;
|
||
} //if
|
||
|
||
|
||
} //if
|
||
} // if items
|
||
|
||
} //proc
|