Merge pull request #35 from livello/IS-ENC

1wire domoticz support, dht22, contact,uptime refactoring
This commit is contained in:
2018-11-10 01:48:18 +03:00
committed by GitHub
10 changed files with 260 additions and 303 deletions

View File

@@ -92,17 +92,17 @@ void Input::Parse()
inType = 0;
pin = 0;
if (inputObj && (inputObj->type == aJson_Object)) {
aJsonObject *s;
s = aJson.getObjectItem(inputObj, "T");
if (s) inType = static_cast<uint8_t>(s->valueint);
aJsonObject *itemBuffer;
itemBuffer = aJson.getObjectItem(inputObj, "T");
if (itemBuffer) inType = static_cast<uint8_t>(itemBuffer->valueint);
pin = static_cast<uint8_t>(atoi(inputObj->name));
s = aJson.getObjectItem(inputObj, "S");
if (!s) {
itemBuffer = aJson.getObjectItem(inputObj, "S");
if (!itemBuffer) {
debugSerial<<F("In: ")<<pin<<F("/")<<inType<<endl;
aJson.addNumberToObject(inputObj, "S", 0);
s = aJson.getObjectItem(inputObj, "S");
itemBuffer = aJson.getObjectItem(inputObj, "S");
}
if (s) store = (inStore *) &s->valueint;
if (itemBuffer) store = (inStore *) &itemBuffer->valueint;
}
}
@@ -222,15 +222,8 @@ void Input::dht22Poll() {
if (emit && temp && humidity && temp == temp && humidity == humidity) {
char addrstr[100] = "";
#ifdef WITH_DOMOTICZ
aJsonObject *idx = aJson.getObjectItem(inputObj, "idx");
if (idx && idx->valuestring) {//DOMOTICZ json format support
debugSerial << endl << idx->valuestring << F(" Domoticz valstr:");
char valstr[50];
sprintf(valstr, "{\"idx\":%s,\"svalue\":\"%.1f;%.0f;0\"}", idx->valuestring, temp, humidity);
debugSerial << valstr;
mqttClient.publish(emit->valuestring, valstr);
setNextPollTime(millis() + DHT_POLL_DELAY_DEFAULT);
debugSerial << F(" NextPollMillis=") << nextPollTime() << endl;
if(getIdxField()){
publishDataToDomoticz(DHT_POLL_DELAY_DEFAULT, emit, "{\"idx\":%s,\"svalue\":\"%.1f;%.0f;0\"}", getIdxField(), temp, humidity);
return;
}
#endif
@@ -276,16 +269,23 @@ void Input::setNextPollTime(unsigned long pollTime) {
}
void Input::uptimePoll() {
if(nextPollTime()>millis())
if (nextPollTime() > millis())
return;
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
if (emit) {
#ifdef WITH_DOMOTICZ
if(getIdxField()){
publishDataToDomoticz(DHT_POLL_DELAY_DEFAULT, emit, "{\"idx\":%s,\"svalue\":\"%d\"}", getIdxField(), millis());
return;
}
#endif
char valstr[11];
// printUlongValueToStr(valstr,millis());
printUlongValueToStr(valstr,millis());
printUlongValueToStr(valstr, millis());
mqttClient.publish(emit->valuestring, valstr);
}
setNextPollTime(millis() +UPTIME_POLL_DELAY_DEFAULT);
setNextPollTime(millis() + UPTIME_POLL_DELAY_DEFAULT);
}
void Input::onCounterChanged(int i) {
@@ -370,15 +370,9 @@ void Input::onContactChanged(int newValue) {
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
if (emit) {
#ifdef WITH_DOMOTICZ
aJsonObject *idx = aJson.getObjectItem(inputObj, "idx");
if (idx->valuestring) {
debugSerial << endl << idx->valuestring << F(" Domoticz valstr:");
char valstr[80];
char *switchCmd;
(newValue)? sprintf(valstr, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}", idx->valuestring)
: sprintf(valstr,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",idx->valuestring);
debugSerial << valstr;
mqttClient.publish(emit->valuestring, valstr);
if (getIdxField()) {
(newValue)? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}", getIdxField())
: publishDataToDomoticz(0,emit,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",getIdxField());
} else
#endif
if (newValue) { //send set command
@@ -423,3 +417,28 @@ void Input::printUlongValueToStr(char *valstr, unsigned long value) {
}
valstr[i]='\0';
}
bool Input::publishDataToDomoticz(int pollTimeIncrement, aJsonObject *emit, const char *format, ...)
{
#ifdef WITH_DOMOTICZ
debugSerial << F("\nDomoticz valstr:");
char valstr[50];
va_list args;
va_start(args, format);
vsnprintf(valstr, sizeof(valstr) - 1, format, args);
va_end(args);
debugSerial << valstr;
mqttClient.publish(emit->valuestring, valstr);
if (pollTimeIncrement)
setNextPollTime(millis() + pollTimeIncrement);
debugSerial << F(" NextPollMillis=") << nextPollTime() << endl;
#endif
return true;
}
char* Input::getIdxField() {
aJsonObject *idx = aJson.getObjectItem(inputObj, "idx");
if(idx&&idx->valuestring)
return idx->valuestring;
return nullptr;
}

View File

@@ -124,4 +124,7 @@ protected:
void uptimePoll();
void printUlongValueToStr(char *valstr, unsigned long value);
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
char* getIdxField();
};

View File

@@ -23,16 +23,17 @@ e-mail anklimov@gmail.com
#include "utils.h"
#ifdef _dmxout
#include "dmx.h"
#include "FastLED.h"
#endif
#ifndef MODBUS_DISABLE
#include <ModbusMaster.h>
#endif
#include <PubSubClient.h>
short modbusBusy = 0;
extern aJsonObject *pollingItem;
@@ -80,20 +81,10 @@ void Item::Parse() {
for (int i = aJson.getArraySize(itemArr); i < 4; i++)
aJson.addItemToArray(itemArr, aJson.createItem(
int(defval[i]))); //Enlarge item to 4 elements. VAL=int if no other definition in conf
itemType = aJson.getArrayItem(itemArr, I_TYPE)->valueint;
itemArg = aJson.getArrayItem(itemArr, I_ARG);
itemVal = aJson.getArrayItem(itemArr, I_VAL);
/*
Serial.print(F(" Item:"));
Serial.print(itemArr->name);
Serial.print(F(" T:"));
Serial.print(itemType);
Serial.print(F(" ="));
Serial.println(getArg());
*/
debugSerial << F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << eol;
}
}
@@ -116,13 +107,12 @@ uint8_t Item::getCmd(bool ext) {
}
void Item::setCmd(uint8_t cmd) {
aJsonObject *t = aJson.getArrayItem(itemArr, I_CMD);
if (t)
void Item::setCmd(uint8_t cmdValue) {
aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD);
if (itemCmd)
{
t->valueint = cmd;
Serial.print(F("SetCmd:"));
Serial.println(cmd);
itemCmd->valueint = cmdValue;
debugSerial<<F("SetCmd:")<<cmdValue<<eol;
}
}
@@ -164,7 +154,7 @@ long int Item::getVal() //Return Val if val is int or first elem of Value array
void Item::setVal(short n, int par) // Only store if VAL is array defined in config to avoid waste of RAM
{
if (!itemVal || itemVal->type!=aJson_Array) return;
Serial.print(F(" Store p="));Serial.print(n);Serial.print(F(" Val="));Serial.println(par);
debugSerial<<F(" Store p="));debugSerial<<n);debugSerial<<F(" Val="));debugSerial<<par);
for (int i=aJson.getArraySize(itemVal);i<=n;i++) aJson.addItemToArray(itemVal,aJson.createItem(int(0))); //Enlarge array of Values
aJsonObject *t = aJson.getArrayItem(itemVal,n);
@@ -175,9 +165,7 @@ void Item::setVal(short n, int par) // Only store if VAL is array defined in c
void Item::setVal(long int par) // Only store if VAL is int (autogenerated or config-defined)
{
if (!itemVal || itemVal->type != aJson_Int) return;
// Serial.print(F(" Store "));
// Serial.print(F(" Val="));
// Serial.println(par);
debugSerial<<F(" Store ")<<F(" Val=")<<par<<eol;
itemVal->valueint = par;
}
@@ -248,7 +236,7 @@ int Item::Ctrl(char * payload, boolean send){
// if (item.getEnableCMD(500) || lanStatus == 4)
Ctrl(cmd, 0, NULL,
send); //Accept ON command not earlier then 500 ms after set settings (Homekit hack)
// else Serial.println(F("on Skipped"));
// else debugSerial<<F("on Skipped"));
break;
default: //some known command
@@ -261,7 +249,7 @@ int Item::Ctrl(char * payload, boolean send){
int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
Serial.print(F("Cmd="));Serial.print(cmd);Serial.print(F(" MEM="));Serial.println(freeRam());
debugSerial<<F("Cmd=")<<cmd<<F(" MEM=")<<freeRam()<<eol;
int Par[MAXCTRLPAR] = {0, 0, 0};
if (Parameters)
@@ -280,29 +268,26 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
if (itemType != CH_GROUP) //individual threating of channels. Ignore restore command for groups
switch (t = getCmd()) {
case CMD_HALT: //previous command was HALT ?
Serial.print(F("Restored from:"));
Serial.println(t);
debugSerial << F("Restored from:") << t << eol;
cmd = CMD_ON; //turning on
break;
default:
return -3;
}//switch old cmd
break;
case CMD_XOFF:
if (itemType != CH_GROUP) //individual threating of channels. Ignore restore command for groups
switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ?
Serial.print(F("Turned off from:"));
Serial.println(t);
cmd = CMD_OFF; //turning Off
break;
default:
Serial.print(F("XOFF skipped. Prev cmd:"));
Serial.println(t);
}
break;
case CMD_XOFF:
if (itemType != CH_GROUP) //individual threating of channels. Ignore restore command for groups
switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ?
debugSerial << F("Turned off from:") << t << eol;
cmd = CMD_OFF; //turning Off
break;
default:
debugSerial<<F("XOFF skipped. Prev cmd:")<<t<<eol;
return -3;
}//switch old cmd
}
break;
} //switch cmd
}
switch (cmd) {
case 0: //no command
@@ -352,18 +337,18 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
case CMD_XON:
if (!isActive()) //if channel was'nt active before CMD_XON
{
Serial.println(F("Turning XON"));
debugSerial<<F("Turning XON\n");
// setCmd(cmd);
}
else
{ //cmd = CMD_ON;
Serial.println(F("Already Active"));
debugSerial<<F("Already Active\n");
if (itemType != CH_GROUP) return -3;
}
case CMD_ON:
if (itemType==CH_RGBW && getCmd() == CMD_ON && getEnableCMD(500)) {
Serial.println(F("Force White"));
debugSerial<<F("Force White\n");
itemType = CH_WHITE;
Par[1] = 0; //Zero saturation
Par[2] = 100; //Full power
@@ -428,9 +413,7 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
if (send) SendStatus(cmd); // Just send ON
}//itemtype switch
else {// Default settings, values not stored yet
Serial.print(st.aslong);
Serial.println(F(": No stored values - default"));
debugSerial<<st.aslong<<F(": No stored values - default\n");
switch (itemType) {
case CH_VCTEMP:
case CH_THERMO:
@@ -466,16 +449,13 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
}
} // default handler
for (short i = 0; i < params; i++) {
Serial.print(F("Restored: "));
Serial.print(i);
Serial.print(F("="));
Serial.println(Par[i]);
debugSerial<<F("Restored: ")<<i<<F("=")<<Par[i]<<eol;
}
/*
} else { //Double ON - apply special preset - clean white full power
if (getEnableCMD(500)) switch (itemType) {
case CH_RGBW:
Serial.println(F("Force White"));
debugSerial<<F("Force White"));
itemType = CH_WHITE;
Par[1] = 0; //Zero saturation
Par[2] = 100; //Full power
@@ -492,7 +472,7 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
} //itemtype
} //else
*/
//Serial.print("Sa:");Serial.println(Par[1]);
//debugSerial<<"Sa:");debugSerial<<Par[1]);
if ((itemType == CH_RGBW) && (Par[1] == 0)) itemType = CH_WHITE;
}
@@ -518,7 +498,7 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
if (getCmd() == CMD_XON) setCmd(CMD_OFF); //Prevent restoring temporary turned on channels (by XON)
else setCmd(cmd);
SendStatus(CMD_OFF); //HALT to OFF mapping - send in any cases
Serial.println(F(" Halted"));
debugSerial<<F(" Halted\n");
}
@@ -531,37 +511,22 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
#ifdef _dmxout
case CH_DIMMER: //Dimmed light
DmxWrite(iaddr, map(Par[0], 0, 100, 0, 255));
break;
case CH_RGBW: //Colour RGBW
{
int k;
DmxWrite(iaddr + 3, k = map((100 - Par[1]) * Par[2], 0, 10000, 0, 255));
Serial.print(F("W:"));
Serial.println(k);
debugSerial<<F("W:")<<k<<eol;
}
case CH_RGB: // RGB
{
CRGB rgb = CHSV(map(Par[0], 0, 365, 0, 255), map(Par[1], 0, 100, 0, 255), map(Par[2], 0, 100, 0, 255));
DmxWrite(iaddr, rgb.r);
DmxWrite(iaddr + 1, rgb.g);
DmxWrite(iaddr + 2, rgb.b);
break;
}
case CH_WHITE:
DmxWrite(iaddr, 0);
DmxWrite(iaddr + 1, 0);
@@ -607,10 +572,7 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
int k;
pinMode(iaddr, OUTPUT);
digitalWrite(iaddr, k = ((cmd == CMD_ON || cmd == CMD_XON) ? HIGH : LOW));
Serial.print(F("Pin:"));
Serial.print(iaddr);
Serial.print(F("="));
Serial.println(k);
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<eol;
break;
case CH_THERMO:
///thermoSet(name,cmd,Par1); all cativities done - update temp & cmd
@@ -646,19 +608,13 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
if (inverse) k = map(Par[0], 100, 0, 0, 255);
else k = map(Par[0], 0, 100, 0, 255);
analogWrite(iaddr, k);
Serial.print(F("Pin:"));
Serial.print(iaddr);
Serial.print(F("="));
Serial.println(k);
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<eol;
break;
}
#ifdef _modbus
case CH_VC:
VacomSetFan(Par[0], cmd);
break;
case CH_VCTEMP: {
Item it(itemArg->valuestring);
if (it.isValid() && it.itemType == CH_VC)
@@ -666,12 +622,7 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
break;
}
#endif
} // switch itemtype
// break;
}
}
int Item::isActive() {
@@ -679,7 +630,7 @@ int Item::isActive() {
int val = 0;
if (!isValid()) return -1;
//Serial.print(itemArr->name);
//debugSerial<<itemArr->name);
int cmd = getCmd();
@@ -689,12 +640,12 @@ int Item::isActive() {
switch (cmd) {
case CMD_ON:
case CMD_XON:
//Serial.println(" active");
//debugSerial<<" active");
return 1;
case CMD_OFF:
case CMD_HALT:
case -1: ///// No last command
//Serial.println(" inactive");
//debugSerial<<" inactive");
return 0;
}
@@ -704,13 +655,13 @@ int Item::isActive() {
switch (itemType) {
case CH_GROUP: //make recursive calculation - is it some active in group
if (itemArg->type == aJson_Array) {
Serial.println(F("Grp check: "));
debugSerial<<F("Grp check:\n");
aJsonObject *i = itemArg->child;
while (i) {
Item it(i->valuestring);
if (it.isValid() && it.isActive()) {
Serial.println(F("Active"));
debugSerial<<F("Active\n");
return 1;
}
i = i->next;
@@ -735,8 +686,8 @@ int Item::isActive() {
case CH_PWM:
val = st.aslong;
} //switch
//Serial.print(F(":="));
//Serial.println(val);
//debugSerial<<F(":="));
//debugSerial<<val);
if (val) return 1; else return 0;
}
@@ -808,7 +759,7 @@ POLL 2101x10
*/
void Item::mb_fail(short addr, short op, int val, int cmd) {
Serial.println(F("Modbus op failed"));
debugSerial<<F("Modbus op failed\n");
// int cmd = getCmd();
// if (cmd<0) return;
setCmd(cmd | CMD_RETRY);
@@ -822,18 +773,12 @@ extern ModbusMaster node;
int Item::VacomSetFan(int8_t val, int8_t cmd) {
int addr = getArg();
Serial.print(F("VC#"));
Serial.print(addr);
Serial.print(F("="));
Serial.println(val);
debugSerial<<F("VC#")<<addr<<F("=")<<val<<eol;
if (modbusBusy) {
mb_fail(1, addr, val, cmd);
return -1;
}
modbusBusy = 1;
uint8_t j;//, result;
//uint16_t data[1];
@@ -846,22 +791,15 @@ int Item::VacomSetFan(int8_t val, int8_t cmd) {
} else node.writeSingleRegister(2001 - 1, 0);
delay(50);
node.writeSingleRegister(2003 - 1, val * 100);
modbusBusy = 0;
}
#define a 0.1842
#define b -36.68
#define a 0.1842f
#define b -36.68f
int Item::VacomSetHeat(int addr, int8_t val, int8_t cmd) {
Serial.print(F("VC_heat#"));
Serial.print(addr);
Serial.print(F("="));
Serial.print(val);
Serial.print(F(" cmd="));
Serial.println(cmd);
debugSerial<<F("VC_heat#")<<addr<<F("=")<<val<<F(" cmd=")<<cmd<<eol;
if (modbusBusy) {
mb_fail(2, addr, val, cmd);
return -1;
@@ -883,7 +821,7 @@ int Item::VacomSetHeat(int addr, int8_t val, int8_t cmd) {
regval = round(((float) val - b) * 10 / a);
}
//Serial.println(regval);
//debugSerial<<regval);
node.writeSingleRegister(2004 - 1, regval);
modbusBusy = 0;
}
@@ -903,8 +841,6 @@ int Item::modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint
modbusSerial.begin(MODBUS_SERIAL_BAUD, dimPar);
node.begin(addr, modbusSerial);
switch (_mask) {
case 1:
value <<= 8;
@@ -914,15 +850,7 @@ int Item::modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint
value &= 0xff;
value |= (0xff00);
}
Serial.print(addr);
Serial.print(F("=>"));
Serial.print(_reg, HEX);
Serial.print(F("(T:"));
Serial.print(_regType);
Serial.print(F("):"));
Serial.println(value, HEX);
debugSerial<<addr<<F("=>")<<_HEX(_reg)<<F("(T:")<<_regType<<F("):")<<_HEX(value)<<eol;
switch (_regType) {
case MODBUS_HOLDING_REG_TYPE:
node.writeSingleRegister(_reg, value);
@@ -931,9 +859,8 @@ int Item::modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint
node.writeSingleCoil(_reg, value);
break;
default:
Serial.println(F("Not supported reg type"));
debugSerial<<F("Not supported reg type\n");
}
modbusBusy = 0;
}
@@ -965,13 +892,12 @@ int Item::checkFM() {
// do something with data if read is successful
if (result == node.ku8MBSuccess) {
Serial.print(F(" FM Val :"));
debugSerial<<F(" FM Val :");
for (j = 0; j < 10; j++) {
data = node.getResponseBuffer(j);
Serial.print(data, HEX);
Serial.print(F("-"));
debugSerial<<_HEX(data)<<F("-");
}
debugSerial<<eol;
int RPM;
// aJson.addNumberToObject(out,"gsw", (int) node.getResponseBuffer(1));
aJson.addNumberToObject(out, "V", (int) node.getResponseBuffer(2) / 100.);
@@ -983,20 +909,17 @@ int Item::checkFM() {
// aJson.addNumberToObject(out,"U", (int) node.getResponseBuffer(8)/10.);
// aJson.addNumberToObject(out,"Ui", (int) node.getResponseBuffer(9));
aJson.addNumberToObject(out, "sw", (int) node.getResponseBuffer(0));
if (RPM && itemArg->type == aJson_Array)
{ aJsonObject *airGateObj = aJson.getArrayItem(itemArg, 1);
if (airGateObj) {
int val = 100;
Item item(airGateObj->valuestring);
if (item.isValid()) item.Ctrl(0,1,&val);
}
}
Serial.println();
} else {
Serial.print(F("Modbus polling error="));
Serial.println(result, HEX);
}
if (RPM && itemArg->type == aJson_Array) {
aJsonObject *airGateObj = aJson.getArrayItem(itemArg, 1);
if (airGateObj) {
int val = 100;
Item item(airGateObj->valuestring);
if (item.isValid())
item.Ctrl(0, 1, &val);
}
}
} else
debugSerial << F("Modbus polling error=") << _HEX(result) << eol;
if (node.getResponseBuffer(0) & 8) //Active fault
{
@@ -1009,40 +932,33 @@ int Item::checkFM() {
// do something with data if read is successful
if (result == node.ku8MBSuccess) {
Serial.print(F(" PI Val :"));
debugSerial << F(" PI Val :");
for (j = 0; j < 4; j++) {
data = node.getResponseBuffer(j);
Serial.print(data);
Serial.print(F("-"));
debugSerial << data << F("-");
}
debugSerial << eol;
int set = node.getResponseBuffer(0);
float fset;
float ftemp;
if (set) aJson.addNumberToObject(out, "set", fset =set * a + b);
aJson.addNumberToObject(out, "t", ftemp =(int) node.getResponseBuffer(1) * a + b);
float ftemp, fset = set * a + b;
if (set)
aJson.addNumberToObject(out, "set", fset);
aJson.addNumberToObject(out, "t", ftemp = (int) node.getResponseBuffer(1) * a + b);
// aJson.addNumberToObject(out,"d", (int) node.getResponseBuffer(2)*a+b);
int pwr = node.getResponseBuffer(3);
if (pwr > 0) aJson.addNumberToObject(out, "pwr", pwr / 10.); else aJson.addNumberToObject(out, "pwr", 0);
if (pwr > 0)
aJson.addNumberToObject(out, "pwr", pwr / 10.);
else aJson.addNumberToObject(out, "pwr", 0);
if (ftemp>FM_OVERHEAT_CELSIUS && set)
{
if (ftemp > FM_OVERHEAT_CELSIUS && set) {
mqttClient.publish("/alarm/ovrht", itemArr->name);
Ctrl(CMD_OFF); //Shut down
}
Serial.println();
} else {
Serial.print(F("Modbus polling error="));
Serial.println(result, HEX);
}
}
} else
debugSerial << F("Modbus polling error=") << _HEX(result);
outch = aJson.print(out);
mqttClient.publish(addrstr, outch);
free(outch);
aJson.deleteItem(out);
modbusBusy = 0;
}
@@ -1050,7 +966,7 @@ boolean Item::checkModbusRetry() {
int cmd = getCmd(true);
if (cmd & CMD_RETRY) { // if last sending attempt of command was failed
int val = getVal();
Serial.println(F("Retrying CMD"));
debugSerial<<F("Retrying CMD\n");
cmd &= ~CMD_RETRY; // Clean retry flag
Ctrl(cmd,1,&val); // Execute command again
@@ -1065,7 +981,7 @@ int Item::checkModbusDimmer() {
short numpar = 0;
if ((itemArg->type != aJson_Array) || ((numpar = aJson.getArraySize(itemArg)) < 2)) {
Serial.println(F("Illegal arguments"));
debugSerial<<F("Illegal arguments\n");
return -3;
}
@@ -1078,13 +994,13 @@ int Item::checkModbusDimmer() {
int _regType = MODBUS_HOLDING_REG_TYPE;
if (numpar >= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint;
// short mask = getArg(2);
// Serial.print(F("Modbus polling "));
// Serial.print(addr);
// Serial.print(F("=>"));
// Serial.print(reg, HEX);
// Serial.print(F("(T:"));
// Serial.print(_regType);
// Serial.println(F(")"));
// debugSerial<<F("Modbus polling "));
// debugSerial<<addr);
// debugSerial<<F("=>"));
// debugSerial<<reg, HEX);
// debugSerial<<F("(T:"));
// debugSerial<<_regType);
// debugSerial<<F(")"));
int data;
@@ -1107,21 +1023,15 @@ int Item::checkModbusDimmer() {
result = node.readInputRegisters(reg, 1);
break;
default:
Serial.println(F("Not supported reg type"));
debugSerial<<F("Not supported reg type\n");
}
if (result == node.ku8MBSuccess) {
data = node.getResponseBuffer(0);
Serial.print(F("MB: "));
Serial.print(itemArr->name);
Serial.print(F(" Val: "));
Serial.println(data, HEX);
debugSerial << F("MB: ") << itemArr->name << F(" Val: ") << _HEX(data) << eol;
checkModbusDimmer(data);
} else {
Serial.print(F("Modbus polling error="));
Serial.println(result, HEX);
}
} else
debugSerial << F("Modbus polling error=") << _HEX(result) << eol;
modbusBusy = 0;
// Looking 1 step ahead for modbus item, which uses same register
@@ -1130,9 +1040,9 @@ int Item::checkModbusDimmer() {
nextItem.getArg(1) == reg) {
nextItem.checkModbusDimmer(data);
pollingItem = pollingItem->next;
if (!pollingItem) pollingItem = items->child;
if (!pollingItem)
pollingItem = items->child;
}
}
@@ -1150,7 +1060,7 @@ int Item::checkModbusDimmer(int data) {
if (maxVal) d = map(d, 0, maxVal, 0, 100);
int cmd = getCmd();
//Serial.println(d);
//debugSerial<<d);
if (getVal() != d || d && cmd == CMD_OFF || d && cmd == CMD_HALT) //volume changed or turned on manualy
{
if (d) { // Actually turned on
@@ -1237,7 +1147,7 @@ int Item::SendStatus(short cmd, short n, int *Par, boolean deffered) {
int chancmd=getCmd(true);
if (deffered) {
setCmd(chancmd | CMD_REPORT);
Serial.println(F("Status deffered"));
debugSerial<<F("Status deffered\n");
// mqttClient.publish("/push", "1");
return 0;
// Todo: Parameters? Now expected that parameters already stored by setVal()
@@ -1266,7 +1176,11 @@ int Item::SendStatus(short cmd, short n, int *Par, boolean deffered) {
if (Par)
for (short i = 0; i < n; i++) {
char num[4];
#ifndef FLASH_64KB
snprintf(num, sizeof(num), "%d", Par[i]);
#else
itoa(Par[i],num,10);
#endif
strncat(valstr, num, sizeof(valstr));
if (i != n - 1) {
strcpy(num, ",");
@@ -1275,13 +1189,10 @@ int Item::SendStatus(short cmd, short n, int *Par, boolean deffered) {
}
break;
default:
Serial.println(F("Unknown cmd "));
debugSerial<<F("Unknown cmd \n");
return -1;
}
Serial.print(F("Pub: "));
Serial.print(addrstr);
Serial.print(F("->"));
Serial.println(valstr);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<eol;
mqttClient.publish(addrstr, valstr,true);
return 0;
}

View File

@@ -112,7 +112,7 @@ class Item
//int getVal(short n); //From VAL array. Negative if no array
long int getVal(); //From int val OR array
uint8_t getCmd(bool ext = false);
void setCmd(uint8_t cmd);
void setCmd(uint8_t cmdValue);
//void setVal(uint8_t n, int par);
void setVal(long int par);
//void copyPar (aJsonObject *itemV);

View File

@@ -94,12 +94,13 @@ WiFiClient ethClient;
#endif
#ifdef ARDUINO_ARCH_STM32F1
#include "HttpClient.h"
//#include <EthernetClient.h>
//#include "UIPEthernet.h"
//#include "UIPUdp.h"
#include <SPI.h>
#include <Ethernet_STM.h>
#include "HttpClient.h"
#include "Dns.h"
//#include "utility/logging.h"
#include <EEPROM.h>
@@ -126,10 +127,18 @@ aJsonObject *items = NULL;
aJsonObject *inputs = NULL;
aJsonObject *mqttArr = NULL;
#ifndef MODBUS_DISABLE
aJsonObject *modbusArr = NULL;
#endif
#ifdef _owire
aJsonObject *owArr = NULL;
#endif
#ifdef _dmxout
aJsonObject *dmxArr = NULL;
#endif
#ifdef SYSLOG_ENABLE
aJsonObject *udpSyslogArr = NULL;
#endif
unsigned long nextPollingCheck = 0;
unsigned long nextInputCheck = 0;
@@ -378,7 +387,6 @@ void ip_ready_config_loaded_connecting_to_broker() {
mqttClient.setCallback(mqttCallback);
debugSerial<<F("\nAttempting MQTT connection to ")<<servername<<F(":")<<port<<F(" user:")<<user<<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)) {
mqttErrorRate = 0;
@@ -554,11 +562,11 @@ void resetHard() {
#ifdef _owire
void Changed(int i, DeviceAddress addr, float val) {
void Changed(int i, DeviceAddress addr, float currentTemp) {
char addrstr[32] = "NIL";
//char addrbuf[17];
char valstr[16] = "NIL";
char *owEmit = NULL;
char *owEmitString = NULL;
char *owItem = NULL;
SetBytes(addr, 8, addrstr);
@@ -566,25 +574,33 @@ void Changed(int i, DeviceAddress addr, float val) {
aJsonObject *owObj = aJson.getObjectItem(owArr, addrstr);
if (owObj) {
owEmit = aJson.getObjectItem(owObj, "emit")->valuestring;
owEmitString = aJson.getObjectItem(owObj, "emit")->valuestring;
if (owEmit) {
printFloatValueToStr(val,valstr);
debugSerial<<owEmit<<F("=")<<valstr<<eol;
if (owEmitString) {
printFloatValueToStr(currentTemp,valstr);
debugSerial<<owEmitString<<F("=")<<valstr<<eol;
if ((currentTemp == -127.0) || (currentTemp == 85.0) || (currentTemp == 0.0)) //ToDo: 1-w short circuit mapped to "0" celsium
return;
#ifdef WITH_DOMOTICZ
aJsonObject *idx = aJson.getObjectItem(owObj, "idx");
if (idx && idx->valuestring) {//DOMOTICZ json format support
debugSerial << endl << idx->valuestring << F(" Domoticz valstr:");
char valstr[50];
sprintf(valstr, "{\"idx\":%s,\"svalue\":\"%.1f\"}", idx->valuestring, currentTemp);
debugSerial << valstr;
mqttClient.publish(owEmitString, valstr);
return;
}
#endif
if ((val == -127.0) || (val == 85.0) || (val == 0.0)) { //ToDo: 1-w short circuit mapped to "0" celsium
return;
}
strcpy_P(addrstr, outprefix);
strncat(addrstr, owEmit, sizeof(addrstr));
//strncat(addrstr, addrbuf, sizeof(addrstr));
strncat(addrstr, owEmitString, sizeof(addrstr));
mqttClient.publish(addrstr, valstr);
}
owItem = aJson.getObjectItem(owObj, "item")->valuestring;
if (owItem) {
thermoSetCurTemp(owItem, val); ///TODO: Refactore using Items interface
}
if (owItem)
thermoSetCurTemp(owItem, currentTemp); ///TODO: Refactore using Items interface
else debugSerial<<F("1w-item not found in config")<<eol;
}
@@ -611,7 +627,6 @@ void cmdFunctionHelp(int arg_cnt, char **args)
"'clear' - clear EEPROM\n"
"'reboot' - reboot controller");
}
void printCurentLanConfig() {
debugSerial << F("Current LAN config(ip,dns,gw,subnet):");
printIPAddress(Ethernet.localIP());
@@ -704,7 +719,9 @@ void applyConfig() {
}
inputs = aJson.getObjectItem(root, "in");
mqttArr = aJson.getObjectItem(root, "mqtt");
#ifdef SYSLOG_ENABLE
udpSyslogArr = aJson.getObjectItem(root, "syslog");
#endif
printConfigSummary();
}
@@ -713,14 +730,20 @@ void printConfigSummary() {
printBool(items);
debugSerial<<F("\ninputs ");
printBool(inputs);
#ifndef MODBUS_DISABLE
debugSerial<<F("\nmodbus ");
printBool(modbusArr);
#endif
debugSerial<<F("\nmqtt ");
printBool(mqttArr);
#ifdef _owire
debugSerial<<F("\n1-wire ");
printBool(owArr);
#endif
#ifdef SYSLOG_ENABLE
debugSerial<<F("\nudp syslog ");
printBool(udpSyslogArr);
#endif
debugSerial << eol;
}
@@ -751,6 +774,7 @@ int loadConfigFromEEPROM()
debugSerial<<F("\nNo stored config\n");
return 0;
}
return 0;
}
void cmdFunctionReq(int arg_cnt, char **args) {
@@ -865,8 +889,7 @@ void cmdFunctionGet(int arg_cnt, char **args) {
//restoreState();
}
void printBool(bool arg) { (arg) ? debugSerial<<F("on") : debugSerial<<F("off"); }
void printBool(bool arg) { (arg) ? debugSerial<<F("+") : debugSerial<<F("-"); }
void saveFlash(short n, char *str) {
short i;
@@ -894,7 +917,6 @@ int ipLoadFromFlash(short n, IPAddress &ip) {
ip[i] = EEPROM.read(n++);
return (ip[0] && (ip[0] != 0xff));
}
lan_status loadConfigFromHttp(int arg_cnt, char **args)
{
int responseStatusCode = 0;
@@ -910,7 +932,13 @@ lan_status loadConfigFromHttp(int arg_cnt, char **args)
snprintf(URI, sizeof(URI), "/%02x-%02x-%02x-%02x-%02x-%02x.config.json", mac[0], mac[1], mac[2], mac[3], mac[4],
mac[5]);
#else
#ifndef FLASH_64KB
snprintf(URI, sizeof(URI), "/%s_config.json",QUOTE(DEVICE_NAME));
#else
strncpy_P(URI, "/", sizeof(URI));
strncat(URI, QUOTE(DEVICE_NAME), sizeof(URI));
strncat(URI, "_config.json", sizeof(URI));
#endif
#endif
debugSerial<<F("Config URI: http://")<<configServer<<URI<<eol;
@@ -994,22 +1022,13 @@ lan_status loadConfigFromHttp(int arg_cnt, char **args)
if (!root) {
debugSerial<<F("Config parsing failed\n");
// nextLanCheckTime=millis()+15000;
return READ_RE_CONFIG;//-11; //Load from NVRAM
} else {
/*
char * outstr=aJson.print(root);
debugSerial<<outstr);
free (outstr);
*/
debugSerial<<response;
applyConfig();
}
} else {
debugSerial<<F("Config retrieving failed\n");
//nextLanCheckTime=millis()+15000;
return READ_RE_CONFIG;//-11; //Load from NVRAM
}
#endif
@@ -1217,7 +1236,9 @@ void setupCmdArduino() {
cmdAdd("save", cmdFunctionSave);
cmdAdd("load", cmdFunctionLoad);
cmdAdd("get", cmdFunctionGet);
#ifndef FLASH_64KB
cmdAdd("mac", cmdFunctionSetMac);
#endif
cmdAdd("kill", cmdFunctionKill);
cmdAdd("req", cmdFunctionReq);
cmdAdd("ip", cmdFunctionIp);
@@ -1360,7 +1381,6 @@ void thermoLoop(void) {
if (millis() < nextThermostatCheck)
return;
bool thermostatCheckPrinted = false;
for (aJsonObject *thermoItem = items->child; thermoItem; thermoItem = thermoItem->next) {
if (isThermostatWithMinArraySize(thermoItem, 5)) {
aJsonObject *thermoExtensionArray = aJson.getArrayItem(thermoItem, I_EXT);

View File

@@ -55,13 +55,17 @@
#include <SPI.h>
#include "utils.h"
#include <string.h>
#include <ModbusMaster.h>
#include "aJSON.h"
#include <Cmd.h>
#include "stdarg.h"
#include "item.h"
#include "inputs.h"
#ifndef MODBUS_DISABLE
#include <ModbusMaster.h>
#endif
#ifndef ARDUINO_ARCH_STM32F1
#include "FastLED.h"
#endif
@@ -156,7 +160,7 @@ void restoreState();
lan_status lanLoop();
#ifndef OWIRE_DISABLE
void Changed(int i, DeviceAddress addr, float val);
void Changed(int i, DeviceAddress addr, float currentTemp);
#endif
void modbusIdle(void);

View File

@@ -158,6 +158,8 @@
#ifndef Wiz5500
#define W5100_ETHERNET_SHIELD
#else
#define W5500_ETHERNET_SHIELD
#endif
#define eol "\n"

View File

@@ -63,9 +63,7 @@ int owUpdate() {
}; //alive
if (ifind < 0 && sensors) {
wstat[t_count] = SW_FIND; //Newly detected
debugSerial.print(F("dev#"));
debugSerial.print(t_count);
debugSerial.print(F(" Addr:"));
debugSerial<<F("dev#")<<t_count<<F(" Addr:");
PrintBytes(term[t_count], 8,0);
debugSerial.println();
if (term[t_count][0] == 0x28) {
@@ -78,8 +76,7 @@ int owUpdate() {
}//if
} //while
debugSerial.print(F("1-wire count: "));
debugSerial.println(t_count);
debugSerial<<F("1-wire count: ")<<t_count;
#endif
}
@@ -89,7 +86,7 @@ int owSetup(owChangedType owCh) {
//// todo - move memory allocation to here
if (net) return true; // Already initialized
#ifdef DS2482_100_I2C_TO_1W_BRIDGE
debugSerial.println(F("DS2482_100_I2C_TO_1W_BRIDGE init"));
debugSerial<<F("DS2482_100_I2C_TO_1W_BRIDGE init");
net = new OneWire;
#else
debugSerial.print(F("One wire setup on PIN:"));
@@ -190,9 +187,7 @@ void owAdd(DeviceAddress addr) {
memcpy(term[t_count], addr, 8);
//term[t_count]=addr;
debugSerial.print(F("dev#"));
debugSerial.print(t_count);
debugSerial.print(F(" Addr:"));
debugSerial<<F("dev#")<<t_count<<F(" Addr:");
PrintBytes(term[t_count], 8,0);
debugSerial.println();
if (term[t_count][0] == 0x28) {

View File

@@ -33,11 +33,11 @@ extern "C" {
void PrintBytes(uint8_t *addr, uint8_t count, bool newline) {
for (uint8_t i = 0; i < count; i++) {
Serial.print(addr[i] >> 4, HEX);
Serial.print(addr[i] & 0x0f, HEX);
debugSerial<<_HEX(addr[i] >> 4);
debugSerial<<_HEX(addr[i] & 0x0f);
}
if (newline)
Serial.println();
debugSerial<<eol;
}
const char HEXSTR[] = "0123456789ABCDEF";
@@ -103,7 +103,6 @@ unsigned long freeRam() {
char *heapend = sbrk(0);
register char *stack_ptr asm( "sp" );
struct mallinfo mi = mallinfo();
return stack_ptr - heapend + mi.fordblks;
}
@@ -156,6 +155,8 @@ void printFloatValueToStr(float value, char *valstr) {
#define ARDBUFFER 16 //Buffer for storing intermediate strings. Performance may vary depending on size.
#ifndef ARDUINO_ARCH_STM32F1
int log(const char *str, ...)//TODO: __FlashStringHelper str support
{
int i, count=0, j=0, flag=0;
@@ -170,7 +171,7 @@ int log(const char *str, ...)//TODO: __FlashStringHelper str support
{
//Clear buffer
temp[j] = '\0';
Serial.print(temp);
debugSerial<<temp;
j=0;
temp[0] = '\0';
@@ -204,9 +205,10 @@ int log(const char *str, ...)//TODO: __FlashStringHelper str support
}
};
Serial.println(); //Print trailing newline
debugSerial<<eol;
return count + 1; //Return number of arguments detected
}
#endif
#pragma message(VAR_NAME_VALUE(debugSerial))

View File

@@ -246,36 +246,37 @@ lib_deps =
Streaming
https://github.com/livello/PrintEx#is-select-redecl
;TODO:STM32 compilation problems
;[env:stm32]
;platform = ststm32
;framework = arduino
;board = nucleo_f103rb
;upload_protocol = stlink
;debug_tool = stlink
;build_flags = !bash check_custom_build_flags_stm32.sh
;lib_ignore =
; DHT sensor library for ESPx
; DmxDue
; DueFlashStorage
; ESP-Dmx
; WifiManager
; FastLED
; Ethernet
;lib_deps =
[env:stm32]
platform = ststm32
framework = arduino
board = nucleo_f103rb
upload_protocol = stlink
debug_tool = stlink
build_flags = !bash check_custom_build_flags_stm32.sh
lib_ignore =
DHT sensor library for ESPx
DmxDue
DueFlashStorage
ESP-Dmx
WifiManager
FastLED
Ethernet
https://github.com/anklimov/Ethernet
DMXSerial
DmxSimple
httpClient
SD
PrintEx
Ethernet2
Artnet
lib_deps =
; DallasTemperature
; https://github.com/anklimov/aJson
; https://github.com/anklimov/CmdArduino
; ArduinoHttpClient
; https://github.com/anklimov/ModbusMaster
;; https://github.com/Serasidis/Ethernet_STM.git
;; https://github.com/livello/Ethernet_STM.git
; https://github.com/knolleary/pubsubclient.git
; Adafruit Unified Sensor
; DHT sensor library
;; https://github.com/anklimov/DMXSerial
;; Syslog
;; https://github.com/No3x/Syslog.git
; https://github.com/arcao/Syslog.git
;; UIPEthernet
; Streaming
https://github.com/anklimov/aJson
https://github.com/anklimov/CmdArduino
ArduinoHttpClient
https://github.com/knolleary/pubsubclient.git
Adafruit Unified Sensor
DHT sensor library
Streaming