scmd,rcmd in inputs may contain not only cmd but values, minimal dimmers volume treshhold for ON command, remote command execute on MQTT command (new Cmd.h required), bat-files to flash DUE and start CLI added

This commit is contained in:
2018-05-25 09:29:47 +03:00
parent b8861d895a
commit 8e38095177
10 changed files with 154 additions and 144 deletions

Binary file not shown.

3
compiled/DUE/upload.bat Normal file
View File

@@ -0,0 +1,3 @@
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

View File

@@ -0,0 +1,3 @@
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

1
compiled/mon.bat Normal file
View File

@@ -0,0 +1 @@
pio device monitor -b 115200

View File

@@ -27,11 +27,11 @@ extern PubSubClient mqttClient;
Input::Input(char * name) //Constructor Input::Input(char * name) //Constructor
{ {
if (name) if (name)
inputObj= aJson.getObjectItem(inputs, name); inputObj= aJson.getObjectItem(inputs, name);
else inputObj=NULL; else inputObj=NULL;
Parse(); Parse();
} }
@@ -42,34 +42,34 @@ Input::Input(int pin) //Constructor
Input::Input(aJsonObject * obj) //Constructor Input::Input(aJsonObject * obj) //Constructor
{ {
inputObj= obj; inputObj= obj;
Parse(); Parse();
} }
boolean Input::isValid () boolean Input::isValid ()
{ {
return (pin && store); return (pin && store);
} }
void Input::Parse() void Input::Parse()
{ {
store = NULL; store = NULL;
inType = 0; inType = 0;
pin = 0; pin = 0;
if (inputObj && (inputObj->type==aJson_Object)) if (inputObj && (inputObj->type==aJson_Object))
{ {
aJsonObject * s; aJsonObject * s;
s = aJson.getObjectItem(inputObj,"T"); s = aJson.getObjectItem(inputObj,"T");
if (s) inType = s->valueint; if (s) inType = s->valueint;
pin = atoi(inputObj->name); pin = atoi(inputObj->name);
s = aJson.getObjectItem(inputObj,"S"); s = aJson.getObjectItem(inputObj,"S");
if (!s) { Serial.print(F("In: "));Serial.print(pin);Serial.print(F("/"));Serial.println(inType); if (!s) { Serial.print(F("In: "));Serial.print(pin);Serial.print(F("/"));Serial.println(inType);
aJson.addNumberToObject(inputObj,"S", 0); aJson.addNumberToObject(inputObj,"S", 0);
@@ -81,40 +81,40 @@ void Input::Parse()
} }
int Input::Poll() int Input::Poll()
{ {
boolean v; boolean v;
if (!isValid()) return -1; if (!isValid()) return -1;
if (inType & IN_ACTIVE_HIGH) if (inType & IN_ACTIVE_HIGH)
{ pinMode(pin, INPUT); { pinMode(pin, INPUT);
v = (digitalRead(pin)==HIGH); v = (digitalRead(pin)==HIGH);
} }
else else
{ pinMode(pin, INPUT_PULLUP); { pinMode(pin, INPUT_PULLUP);
v = (digitalRead(pin)==LOW); v = (digitalRead(pin)==LOW);
} }
if (v!=store->cur) // value changed if (v!=store->cur) // value changed
{ {
if (store->bounce) store->bounce--; if (store->bounce) store->bounce--;
else //confirmed change else //confirmed change
{ {
Changed(v); Changed(v);
store->cur=v; store->cur=v;
} }
} }
else // no change else // no change
store->bounce=3; store->bounce=3;
return 0; return 0;
} }
void Input::Changed (int val) void Input::Changed (int val)
{ {
Serial.print(pin);Serial.print(F("="));Serial.println(val); Serial.print(F("IN:")); Serial.print(pin);Serial.print(F("="));Serial.println(val);
aJsonObject * item = aJson.getObjectItem(inputObj,"item"); aJsonObject * item = aJson.getObjectItem(inputObj,"item");
aJsonObject * scmd = aJson.getObjectItem(inputObj,"scmd"); aJsonObject * scmd = aJson.getObjectItem(inputObj,"scmd");
aJsonObject * rcmd = aJson.getObjectItem(inputObj,"rcmd"); aJsonObject * rcmd = aJson.getObjectItem(inputObj,"rcmd");
aJsonObject * emit = aJson.getObjectItem(inputObj,"emit"); aJsonObject * emit = aJson.getObjectItem(inputObj,"emit");
if (emit) if (emit)
{ {
@@ -126,7 +126,7 @@ void Input::Changed (int val)
else else
{ //send reset command { //send reset command
if (!rcmd) mqttClient.publish(emit->valuestring,"OFF",true); else if (strlen(rcmd->valuestring)) mqttClient.publish(emit->valuestring,rcmd->valuestring,true); if (!rcmd) mqttClient.publish(emit->valuestring,"OFF",true); else if (strlen(rcmd->valuestring)) mqttClient.publish(emit->valuestring,rcmd->valuestring,true);
} }
} }
if (item) if (item)
@@ -136,11 +136,11 @@ void Input::Changed (int val)
{ {
if (val) if (val)
{ //send set command { //send set command
if (!scmd) it.Ctrl(CMD_ON,0,NULL,true); else if (strlen(scmd->valuestring)) it.Ctrl(txt2cmd(scmd->valuestring),0,NULL,true); if (!scmd) it.Ctrl(CMD_ON,0,NULL,true); else if (strlen(scmd->valuestring)) it.Ctrl(scmd->valuestring,true);
} }
else else
{ //send reset command { //send reset command
if (!rcmd) it.Ctrl(CMD_OFF,0,NULL,true); else if (strlen(rcmd->valuestring)) it.Ctrl(txt2cmd(rcmd->valuestring),0,NULL,true); if (!rcmd) it.Ctrl(CMD_OFF,0,NULL,true); else if (strlen(rcmd->valuestring)) it.Ctrl(rcmd->valuestring,true);
} }
} }
} }

View File

@@ -20,7 +20,7 @@ e-mail anklimov@gmail.com
#include "aJSON.h" #include "aJSON.h"
#define IN_ACTIVE_HIGH 128 // High level = PUSHED/ CLOSED/ ON othervise :Low Level #define IN_ACTIVE_HIGH 2 // High level = PUSHED/ CLOSED/ ON othervise :Low Level
#define IN_ANALOG 64 // Analog input #define IN_ANALOG 64 // Analog input
#define IN_RE 32 // Rotary Encoder (for further use) #define IN_RE 32 // Rotary Encoder (for further use)
@@ -31,36 +31,36 @@ e-mail anklimov@gmail.com
// in syntaxis // in syntaxis
// "pin": { "T":"N", "emit":"out_emit", item:"out_item", "scmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd":"repeat_command" } // "pin": { "T":"N", "emit":"out_emit", item:"out_item", "scmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd":"repeat_command" }
// //
//Switch/Restore all //Switch/Restore all
//"pin": { "T":"1", "emit":"/all", item:"local_all", "scmd": "OFF", "rcmd": "RESTORE"} //"pin": { "T":"1", "emit":"/all", item:"local_all", "scmd": "OFF", "rcmd": "RESTORE"}
// //
//Normal (not button) Switch (toggled mode) //Normal (not button) Switch (toggled mode)
//"pin": { "T":"1", "emit":"/light1", item:"light1", "scmd": "TOGGLE", "rcmd": "TOGGLE"} //"pin": { "T":"1", "emit":"/light1", item:"light1", "scmd": "TOGGLE", "rcmd": "TOGGLE"}
// or // or
// "pin": { "T":"xx", "emit":"/light1", item:"light1"} // "pin": { "T":"xx", "emit":"/light1", item:"light1"}
//Normal (not button) Switch //Normal (not button) Switch
//"pin": { "T":"0", "emit":"/light1", item:"light1", "scmd": "ON", "rcmd": "OFF"} //"pin": { "T":"0", "emit":"/light1", item:"light1", "scmd": "ON", "rcmd": "OFF"}
// or // or
// "pin": { "T":"0", "emit":"/light1", item:"light1"} // "pin": { "T":"0", "emit":"/light1", item:"light1"}
//or //or
// "pin": { "emit":"/light1", item:"light1"} // "pin": { "emit":"/light1", item:"light1"}
//1-Button dimmer //1-Button dimmer
//"pin": { "T":"1", "emit":"/light1", item:"light1", "scmd": "ON", srcmd:"INCREASE",rrcmd:"DECREASE", "rcmd": "OFF"} //"pin": { "T":"1", "emit":"/light1", item:"light1", "scmd": "ON", srcmd:"INCREASE",rrcmd:"DECREASE", "rcmd": "OFF"}
// or // or
// "pin": { "T":"xx", "emit":"/light1", item:"light1"} // "pin": { "T":"xx", "emit":"/light1", item:"light1"}
//2-Buttons dimmer //2-Buttons dimmer
//"pin1": { "T":"0", "emit":"/light1", item:"light1", "scmd": "ON", repcmd:"INCREASE"} //"pin1": { "T":"0", "emit":"/light1", item:"light1", "scmd": "ON", repcmd:"INCREASE"}
//"pin2": { "T":"0", "emit":"/light1", item:"light1", "scmd": "OFF", repcmd:"INCREASE"} //"pin2": { "T":"0", "emit":"/light1", item:"light1", "scmd": "OFF", repcmd:"INCREASE"}
extern aJsonObject *inputs; extern aJsonObject *inputs;
typedef union
typedef union
{ {
long int aslong; long int aslong;
struct struct
@@ -68,7 +68,7 @@ typedef union
int8_t reserve; int8_t reserve;
int8_t logicState; int8_t logicState;
int8_t bounce; int8_t bounce;
int8_t cur; int8_t cur;
}; };
} inStore; } inStore;
@@ -83,15 +83,11 @@ class Input
Input(int pin); Input(int pin);
Input(aJsonObject * obj); Input(aJsonObject * obj);
Input(char * name); Input(char * name);
boolean isValid (); boolean isValid ();
void Changed (int val); void Changed (int val);
int Poll(); int Poll();
protected: protected:
void Parse(); void Parse();
}; };

View File

@@ -199,6 +199,53 @@ boolean Item::getEnableCMD(int delta) {
} }
#define MAXCTRLPAR 3 #define MAXCTRLPAR 3
int Item::Ctrl(char * payload, boolean send){
int cmd = txt2cmd(payload);
switch (cmd) {
case 0: {
short i = 0;
int Par[3];
while (payload && i < 3)
Par[i++] = getInt((char **) &payload);
Ctrl(0, i, Par, send);
}
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);
Ctrl(0, 3, Par, send);
}
break;
}
case CMD_ON:
// 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"));
break;
default: //some known command
Ctrl(cmd, 0, NULL, send);
} //ctrl
}
int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) { int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
@@ -286,6 +333,20 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
setCmd(cmd); setCmd(cmd);
//retrive stored values //retrive stored values
st.aslong = getVal(); st.aslong = getVal();
// If command is ON but saved volume to low - setup mimimum volume
switch (itemType) {
case CH_DIMMER:
case CH_MODBUS:
if (st.aslong<MIN_VOLUME) st.aslong=INIT_VOLUME;
setVal(st.aslong);
break;
case CH_RGB:
case CH_RGBW:
if (st.aslong && (st.v<MIN_VOLUME)) st.v=INIT_VOLUME;
setVal(st.aslong);
}
if (st.aslong > 0) //Stored smthng if (st.aslong > 0) //Stored smthng
switch (itemType) { switch (itemType) {
@@ -295,8 +356,6 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
Par[0] = st.h; Par[0] = st.h;
Par[1] = st.s; Par[1] = st.s;
Par[2] = st.v; Par[2] = st.v;
if (!Par[2]) Par[2]=80; //If RGB value==0 set to 80%
setVal(st.aslong);
params = 3; params = 3;
SendStatus(0, params, Par,true); // Send restored triplet. In any cases SendStatus(0, params, Par,true); // Send restored triplet. In any cases
break; break;
@@ -306,8 +365,6 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) {
case CH_DIMMER: //Everywhere, in flat VAL case CH_DIMMER: //Everywhere, in flat VAL
case CH_MODBUS: case CH_MODBUS:
case CH_VC: case CH_VC:
Par[0] = st.aslong; Par[0] = st.aslong;
params = 1; params = 1;
SendStatus(0, params, Par, true); // Send restored parameter, even if send=false - no problem, loop will be supressed at next hop SendStatus(0, params, Par, true); // Send restored parameter, even if send=false - no problem, loop will be supressed at next hop
@@ -616,8 +673,8 @@ int Item::isActive() {
case CH_PWM: case CH_PWM:
val = st.aslong; val = st.aslong;
} //switch } //switch
Serial.print(F(":=")); //Serial.print(F(":="));
Serial.println(val); //Serial.println(val);
if (val) return 1; else return 0; if (val) return 1; else return 0;
} }
@@ -712,8 +769,8 @@ int Item::VacomSetFan(int8_t val, int8_t cmd) {
} }
modbusBusy = 1; modbusBusy = 1;
uint8_t j, result; uint8_t j;//, result;
uint16_t data[1]; //uint16_t data[1];
modbusSerial.begin(9600, fmPar); modbusSerial.begin(9600, fmPar);
node.begin(addr, modbusSerial); node.begin(addr, modbusSerial);
@@ -987,7 +1044,7 @@ int Item::checkModbusDimmer() {
uint16_t addr = getArg(0); uint16_t addr = getArg(0);
uint16_t reg = getArg(1); uint16_t reg = getArg(1);
short mask = getArg(2); // short mask = getArg(2);
int data; int data;

View File

@@ -19,17 +19,17 @@ e-mail anklimov@gmail.com
*/ */
#include "options.h" #include "options.h"
#define CH_DIMMER 0 //DMX 1 ch #define CH_DIMMER 0 //DMX 1 ch
#define CH_RGBW 1 //DMX 4 ch #define CH_RGBW 1 //DMX 4 ch
#define CH_RGB 2 //DMX 3 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
#define CH_MODBUS 4 //Modbus AC Dimmer #define CH_MODBUS 4 //Modbus AC Dimmer
#define CH_THERMO 5 //Simple ON/OFF thermostat #define CH_THERMO 5 //Simple ON/OFF thermostat
#define CH_RELAY 6 //ON_OFF relay output #define CH_RELAY 6 //ON_OFF relay output
#define CH_GROUP 7 //Group pseudochannel #define CH_GROUP 7 //Group pseudochannel
#define CH_VCTEMP 8 //Vacom PID regulator #define CH_VCTEMP 8 //Vacom PID regulator
#define CH_VC 9 //Vacom modbus motor regulator #define CH_VC 9 //Vacom modbus motor regulator
#define CH_WHITE 127// #define CH_WHITE 127//
#define CMD_ON 1 #define CMD_ON 1
#define CMD_OFF 2 #define CMD_OFF 2
@@ -42,7 +42,7 @@ e-mail anklimov@gmail.com
#define CMD_REPORT 32 #define CMD_REPORT 32
#define I_TYPE 0 //Type of item #define I_TYPE 0 //Type of item
#define I_ARG 1 //Chanel-type depended argument or array of arguments (pin, address etc) #define I_ARG 1 //Chanel-type depended argument or array of arguments (pin, address etc)
#define I_VAL 2 //Latest preset (int or array of presets) #define I_VAL 2 //Latest preset (int or array of presets)
#define I_CMD 3 //Latest CMD received #define I_CMD 3 //Latest CMD received
#define I_EXT 4 //Chanell-depended extension - array #define I_EXT 4 //Chanell-depended extension - array
@@ -50,22 +50,22 @@ e-mail anklimov@gmail.com
#include "aJSON.h" #include "aJSON.h"
extern aJsonObject *items; extern aJsonObject *items;
int txt2cmd (char * payload); int txt2cmd (char * payload);
typedef union typedef union
{ {
long int aslong; long int aslong;
struct struct
{ {
int16_t h; int16_t h;
int8_t s; int8_t s;
int8_t v; int8_t v;
}; };
} HSVstore; } HSVstore;
typedef union typedef union
{ {
long int aslong; long int aslong;
struct struct
@@ -73,21 +73,23 @@ typedef union
int8_t r; int8_t r;
int8_t g; int8_t g;
int8_t b; int8_t b;
int8_t v; int8_t v;
}; };
} RGBVstore; } RGBVstore;
class Item class Item
{ {
public: public:
aJsonObject *itemArr, *itemArg,*itemVal; aJsonObject *itemArr, *itemArg,*itemVal;
uint8_t itemType; uint8_t itemType;
Item(char * name); Item(char * name);
Item(aJsonObject * obj); Item(aJsonObject * obj);
boolean isValid (); boolean isValid ();
virtual int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true); virtual int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true);
virtual int Ctrl(char * payload, boolean send=true);
int getArg(short n=0); int getArg(short n=0);
boolean getEnableCMD(int delta); boolean getEnableCMD(int delta);
//int getVal(short n); //From VAL array. Negative if no array //int getVal(short n); //From VAL array. Negative if no array
@@ -102,8 +104,8 @@ class Item
inline int Toggle(){Ctrl(CMD_TOGGLE);}; inline int Toggle(){Ctrl(CMD_TOGGLE);};
int Poll(); int Poll();
int SendStatus(short cmd, short n=0, int * Par=NULL, boolean deferred = false); int SendStatus(short cmd, short n=0, int * Par=NULL, boolean deferred = false);
protected: protected:
int VacomSetFan (int8_t val, int8_t cmd=0); int VacomSetFan (int8_t val, int8_t cmd=0);
int VacomSetHeat(int addr, int8_t val, int8_t cmd=0); int VacomSetHeat(int addr, int8_t val, int8_t cmd=0);
int modbusDimmerSet(int addr, uint16_t _reg, int _mask, uint16_t value); int modbusDimmerSet(int addr, uint16_t _reg, int _mask, uint16_t value);
@@ -131,7 +133,7 @@ class PooledItem : public Item
int PoolingInterval; int PoolingInterval;
unsigned long next; unsigned long next;
virtual int Pool() =0; virtual int Pool() =0;
}; };
@@ -143,7 +145,7 @@ class Vacon : public Item
public: public:
int Pool (); int Pool ();
virtual int Ctrl(short cmd, short n=0, int * Par=NULL); virtual int Ctrl(short cmd, short n=0, int * Par=NULL);
protected: protected:
}; };
*/ */

View File

@@ -141,6 +141,11 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) {
} }
Serial.println(); Serial.println();
if(!strcmp(topic,CMDTOPIC)) {
cmd_parse((char *)payload);
return;
}
boolean retaining = (lanStatus == 4); //Todo - named constant boolean retaining = (lanStatus == 4); //Todo - named constant
//Check if topic = Command topic //Check if topic = Command topic
short intopic = 0; short intopic = 0;
@@ -149,86 +154,23 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) {
strncpy_P(buf, inprefix, sizeof(buf)); strncpy_P(buf, inprefix, sizeof(buf));
intopic = strncmp(topic, buf, strlen(inprefix)); intopic = strncmp(topic, buf, strlen(inprefix));
} }
// in Retaining status - trying to restore previous state from retained output topic. Retained input topics are not relevant. // in Retaining status - trying to restore previous state from retained output topic. Retained input topics are not relevant.
if (retaining && !intopic) { if (retaining && !intopic) {
Serial.println(F("Skipping..")); Serial.println(F("Skipping.."));
return; return;
} }
char subtopic[MQTT_SUBJECT_LENGTH] = ""; char subtopic[MQTT_SUBJECT_LENGTH] = "";
int cmd = 0; // int cmd = 0;
//cmd = txt2cmd((char *) payload);
cmd = txt2cmd((char *) payload);
char *t; char *t;
if (t = strrchr(topic, '/')) if (t = strrchr(topic, '/'))
strncpy(subtopic, t + 1, MQTT_SUBJECT_LENGTH - 1); 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); Item item(subtopic);
if (item.isValid()) { if (item.isValid()) {
if (item.itemType == CH_GROUP && retaining) if (item.itemType == CH_GROUP && retaining)
return; //Do not restore group channels - they consist not relevant data return; //Do not restore group channels - they consist not relevant data
switch (cmd) { item.Ctrl((char *)payload, !retaining);
case 0: { } //valid item
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__ #ifndef __ESP__

View File

@@ -17,6 +17,8 @@
#define THERMO_OVERHEAT_CELSIUS 38 #define THERMO_OVERHEAT_CELSIUS 38
#define FM_OVERHEAT_CELSIUS 40. #define FM_OVERHEAT_CELSIUS 40.
#define MIN_VOLUME 10
#define INIT_VOLUME 30
#define OFFSET_MAC 0 #define OFFSET_MAC 0
#define OFFSET_IP OFFSET_MAC+6 #define OFFSET_IP OFFSET_MAC+6
@@ -57,6 +59,10 @@
#define OUTTOPIC "/myhome/s_out/" #define OUTTOPIC "/myhome/s_out/"
#endif #endif
#ifndef CMDTOPIC
#define CMDTOPIC "/myhome/in/command/"
#endif
#ifndef INTOPIC #ifndef INTOPIC
#define INTOPIC "/myhome/in/" #define INTOPIC "/myhome/in/"
#endif #endif