14 Commits

Author SHA1 Message Date
fae1bd4dcc pre-rel bins 2024-08-23 18:59:58 +03:00
e5e24943a6 critical relability fix 2024-08-23 18:35:39 +03:00
f672878873 pre-release-binaries 2024-08-23 00:30:59 +03:00
ff8997fb02 post-refactoring fixes: $command, Items-Parse 2024-08-23 00:12:12 +03:00
96a9c59add nrf bin 2024-08-22 00:56:21 +03:00
7759d51b31 Cross comp & binaries 2024-08-22 00:55:31 +03:00
e21541aa7a cleanup and odd cleanConf fix 2024-08-22 00:35:47 +03:00
806e99eb92 NO-IP devices persistence
STM Flash cfg fix
 CAN GROUP chan fix
 CRC16 fix
2024-08-21 14:01:06 +03:00
2b638b1310 MQTT->CAN proxy. CRC16 for CAN config 2024-08-19 22:35:20 +03:00
82f729216e mapping constrain fix & more mbus relability 2024-08-16 21:41:13 +03:00
dc6e310b10 MBUS fix for requrent def# reg less main reg
Now it can working for empty action for def# reg
2024-08-15 00:36:14 +03:00
baad75fde7 bins 2024-08-14 20:04:11 +03:00
7040d9bf93 MBUS no write if prefetched value == target
Removed constrain 255 for mapping
2024-08-14 19:43:24 +03:00
0a4e70479b Modbus attempts counter reset & silence timer fix 2024-08-14 00:00:22 +03:00
31 changed files with 54373 additions and 53950 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
#!/bin/sh
../tools/mac/arduinoOTA -address 192.168.11.10 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -P net:192.168.88.2:23000 -v -V -patmega2560 -cwiring -b115200 -D -Uflash:w:firmware.hex:i avrdude -P net:192.168.88.2:23000 -v -V -patmega2560 -cwiring -b115200 -D -Uflash:w:firmware.hex:i

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -132,14 +132,18 @@ bool canDriver::sendRemoteID(macAddress mac)
canid_t id; canid_t id;
//datagram_t packet; //datagram_t packet;
bool res=false; bool res=false;
id.subjId=0;
id.deviceId=getIdByMac(mac); //Retrieved controllerID id.deviceId=getIdByMac(mac); //Retrieved controllerID
if (!id.deviceId) return false; if (!id.deviceId) return false;
aJsonObject * config=getConfbyID(id.deviceId);
if (config) id.subjId=getCRC(config); //CRC16 of remote config
id.reserve=0; id.reserve=0;
id.status=1; //response id.status=1; //response
id.payloadType=payloadType::lookupMAC; id.payloadType=payloadType::lookupMAC;
id.subjId=200; //CRC16 of remote config
debugSerial<<("CAN: Send remote ID")<<endl; debugSerial<<("CAN: Send remote ID")<<endl;
res = write (id.id,(datagram_t*)mac,6); res = write (id.id,(datagram_t*)mac,6);
@@ -152,7 +156,21 @@ return res;
bool canDriver::begin() bool canDriver::begin()
{ {
if (root)
{
canConfigObj = aJson.getObjectItem(root, "can");
if (canConfigObj)
{
canRemoteConfigObj= aJson.getObjectItem(canConfigObj, "conf");
controllerId = getMyId(); controllerId = getMyId();
}
confCRC=getCRC(root);
}
#ifndef NOIP
if (!canConfigObj) return false;
#endif
if (!ready) // not reInitialization if (!ready) // not reInitialization
{ {
@@ -304,8 +322,8 @@ switch (state)
if (CANConfStream.peek() == '{') { if (CANConfStream.peek() == '{') {
debugSerial<<F("CAN: JSON detected")<<endl; debugSerial<<F("CAN: JSON detected")<<endl;
cleanConf(1);
aJsonStream as = aJsonStream(&CANConfStream); aJsonStream as = aJsonStream(&CANConfStream);
cleanConf(false);
root = aJson.parse(&as); root = aJson.parse(&as);
CANConfStream.close(); CANConfStream.close();
if (!root) { if (!root) {
@@ -318,7 +336,9 @@ switch (state)
} }
infoSerial<<F("CAN: config Loaded")<<endl; infoSerial<<F("CAN: config Loaded")<<endl;
configLocked--; configLocked--;
applyConfig(); cmdFunctionSave(0,NULL);
if (applyConfig()) ;
// debugSerial.print(aJson.print(root,false));
sysConf.loadETAG(); sysConf.loadETAG();
state = canState::Idle; state = canState::Idle;
return ; return ;
@@ -419,7 +439,7 @@ if (id.status){
case payloadType::itemCommand: case payloadType::itemCommand:
{ {
if (len!=8) return false; if (len!=8) return false;
aJsonObject *confObj = findConfbyID(id.deviceId); aJsonObject *confObj = getConfbyID(id.deviceId);
if (confObj) if (confObj)
{ {
debugSerial<<F("CAN: status received for dev ")<<id.deviceId<<endl; debugSerial<<F("CAN: status received for dev ")<<id.deviceId<<endl;
@@ -434,13 +454,15 @@ if (id.status){
ic.cmd = packet->cmd; ic.cmd = packet->cmd;
ic.param = packet->param; ic.param = packet->param;
debugSerial<<F("CAN: item ")<<it.itemArr->name; debugSerial<<F("CAN: item ")<<it.itemArr->name<<" ";
ic.debugOut(); ic.debugOut();
if (ic.isCommand()) flags |= FLAG_COMMAND;
if (ic.isValue()) flags |= FLAG_PARAMETERS; if (ic.isValue()) flags |= FLAG_PARAMETERS;
if (ic.getSuffix()==S_DELAYED) flags |= FLAG_SEND_DELAYED;
else if (ic.isCommand()) flags |= FLAG_COMMAND;
ic.saveItem(&it,flags); ic.saveItem(&it,flags);
it.SendStatusImmediate(ic,flags | FLAG_NOT_SEND_CAN,it.getSubItemStrById(id.subItemId)); it.SendStatusImmediate(ic,flags | FLAG_NOT_SEND_CAN, it.getSubItemStrById(id.subItemId));
return true; return true;
} }
@@ -456,9 +478,17 @@ if (id.status){
case canState::MACLookup: case canState::MACLookup:
if ((id.payloadType == payloadType::lookupMAC)) if ((id.payloadType == payloadType::lookupMAC))
{ {
debugSerial<<"\nCAN: Got Controller addr: "<<id.deviceId<<endl; if (root && (id.subjId == confCRC)) ///?
controllerId=id.deviceId; {
infoSerial << (F("Valid config already onboard")) << endl;
state = canState::Idle;
}
else
{
infoSerial<<"\nCAN: Got Controller addr: "<<id.deviceId<<endl;
state = canState::ReadConfig; state = canState::ReadConfig;
controllerId=id.deviceId;
}
} }
return true; return true;
@@ -511,7 +541,7 @@ else //Requests
else if ((id.payloadType == payloadType::configFrame) && (id.subjId == 0xFFFF)) else if ((id.payloadType == payloadType::configFrame) && (id.subjId == 0xFFFF))
{ {
debugSerial<<F("CAN: Requested conf for dev#")<<id.deviceId<<endl; debugSerial<<F("CAN: Requested conf for dev#")<<id.deviceId<<endl;
aJsonObject * remoteConfObj = findConfbyID(id.deviceId); aJsonObject * remoteConfObj = getConfbyID(id.deviceId);
if (remoteConfObj) if (remoteConfObj)
{ {
infoSerial<<F("CAN: Sending conf for dev#")<<id.deviceId<<endl; infoSerial<<F("CAN: Sending conf for dev#")<<id.deviceId<<endl;
@@ -531,26 +561,17 @@ return false;
uint8_t canDriver::getMyId() uint8_t canDriver::getMyId()
{ {
if (!root) return 0; if (!canConfigObj) return 0;
aJsonObject * canObj = aJson.getObjectItem(root, "can"); aJsonObject * addrObj = aJson.getObjectItem(canConfigObj, "addr");
if (!canObj) return 0;
aJsonObject * addrObj = aJson.getObjectItem(canObj, "addr");
if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint; if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint;
return 0; return 0;
} }
aJsonObject * canDriver::findConfbyID(uint8_t devId) aJsonObject * canDriver::getConfbyID(uint8_t devId)
{ {
if (!root) return NULL; if (!canConfigObj) return NULL;
aJsonObject * canObj = aJson.getObjectItem(root, "can"); if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object) return NULL;
if (!canObj) return NULL; aJsonObject * remoteConfObj=canRemoteConfigObj->child;
aJsonObject * remoteConfObj = aJson.getObjectItem(canObj, "conf");
if (!remoteConfObj) return NULL;
remoteConfObj=remoteConfObj->child;
while (remoteConfObj) while (remoteConfObj)
{ {
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can"); aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
@@ -564,30 +585,77 @@ while (remoteConfObj)
return NULL; return NULL;
} }
aJsonObject * canDriver::findConfbyName(char* devName, int * devAddr)
{
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object || !devName ) return NULL;
aJsonObject * remoteConfObj=canRemoteConfigObj->child;
while (remoteConfObj)
{
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
if (remoteCanObj)
{
aJsonObject * nameObj = aJson.getObjectItem(remoteCanObj, "name");
if (nameObj && (nameObj->type == aJson_String) && nameObj->valuestring && (strncasecmp(nameObj->valuestring,devName,strlen(nameObj->valuestring)) == 0))
{
if (devAddr)
{
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
if (addrObj && (addrObj->type == aJson_Int)) *devAddr=addrObj->valueint;
}
return remoteConfObj;
}
}
remoteConfObj=remoteConfObj->next;
}
return NULL;
}
#if not defined (NOIP)
extern PubSubClient mqttClient;
bool canDriver::subscribeTopics(char * root, size_t buflen)
{
if (!root) return false;
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object) return false;
int rootLen = strlen(root);
aJsonObject * remoteConfObj=canRemoteConfigObj->child;
while (remoteConfObj)
{
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
if (remoteCanObj)
{
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "name");
if (addrObj && (addrObj->type == aJson_String) && addrObj->valuestring)
{
strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1);
strncat(root+rootLen, "/", buflen-rootLen-1);
strncat(root+rootLen, "#", buflen-rootLen-1);
debugSerial.println(root);
mqttClient.subscribe(root);
}
}
remoteConfObj=remoteConfObj->next;
}
}
#endif
uint8_t canDriver::getIdByMac(macAddress mac) uint8_t canDriver::getIdByMac(macAddress mac)
{ {
char macStr[19]; char macStr[19];
uint8_t strptr = 0; uint8_t strptr = 0;
if (!root) return 0;
aJsonObject * canObj = aJson.getObjectItem(root, "can");
if (!canObj) return 0;
aJsonObject * confObj = aJson.getObjectItem(canObj, "conf");
if (!confObj) return 0;
memset(macStr,0,sizeof(macStr));
for (byte i = 0; i < 6; i++)
{
// if (mac[i]<16) macStr[strptr++]='0';
if (!canRemoteConfigObj) return 0;
memset(macStr,0,sizeof(macStr));
for (byte i = 0; i < 6; i++)
{
SetBytes(&mac[i],1,&macStr[strptr]); SetBytes(&mac[i],1,&macStr[strptr]);
strptr+=2; strptr+=2;
if (i < 5) macStr[strptr++]=':'; if (i < 5) macStr[strptr++]=':';
} }
debugSerial<<F("CAN: Searching devId for ")<<macStr<<endl; debugSerial<<F("CAN: Searching devId for ")<<macStr<<endl;
aJsonObject * remoteConfObj = aJson.getObjectItem(confObj, macStr); aJsonObject * remoteConfObj = aJson.getObjectItem(canRemoteConfigObj, macStr);
if (!remoteConfObj) return 0; if (!remoteConfObj) return 0;
@@ -606,8 +674,11 @@ return 0;
} }
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size) bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
{ //return 0; { //
if (!ready) errorSerial<<"CAN: not initialized"<<endl; if (!ready) {
errorSerial<<"CAN: not initialized"<<endl;
return false;
}
bool res; bool res;
if (size>8) size = 8; if (size>8) size = 8;

View File

@@ -119,7 +119,7 @@ Error
class canDriver class canDriver
{ {
public: public:
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::stateUnknown;}; canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::stateUnknown;canConfigObj=NULL;canRemoteConfigObj=NULL;confCRC=0xFFFF;};
uint8_t getMyId(); uint8_t getMyId();
bool sendStatus(uint16_t itemNum, itemCmd cmd, int subItem = NO_SUBITEM); bool sendStatus(uint16_t itemNum, itemCmd cmd, int subItem = NO_SUBITEM);
bool sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool status=false, int subItemID=NO_SUBITEM ); bool sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool status=false, int subItemID=NO_SUBITEM );
@@ -134,15 +134,22 @@ bool begin();
void Poll(); void Poll();
bool processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr=false); bool processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr=false);
bool write(uint32_t msg_id, datagram_t * buf = NULL, uint8_t size=0); bool write(uint32_t msg_id, datagram_t * buf = NULL, uint8_t size=0);
aJsonObject * findConfbyName(char* devName, int * devAddr=NULL);
#if not defined (NOIP)
bool subscribeTopics(char * root, size_t buflen);
#endif
uint8_t getControllerID(){return controllerId;}; uint8_t getControllerID(){return controllerId;};
uint8_t getIdByMac(macAddress mac); uint8_t getIdByMac(macAddress mac);
aJsonObject * canConfigObj;
aJsonObject * canRemoteConfigObj;
uint16_t confCRC;
datagram_t RXpacket; datagram_t RXpacket;
canid_t RXid; canid_t RXid;
uint8_t RXlen; uint8_t RXlen;
private: private:
aJsonObject * findConfbyID(uint8_t devId); aJsonObject * getConfbyID(uint8_t devId);
#if defined(ARDUINO_ARCH_STM32) #if defined(ARDUINO_ARCH_STM32)
CAN_message_t CAN_RX_msg; CAN_message_t CAN_RX_msg;

View File

@@ -287,6 +287,10 @@ NRFFlashStorage EEPROM;
putEOF(); putEOF();
debugSerial<<F("EOF")<<endl; debugSerial<<F("EOF")<<endl;
} }
#if defined (ARDUINO_ARCH_STM32)
eeprom_buffer_flush();
#endif
#if defined(__SAM3X8E__) #if defined(__SAM3X8E__)
if (samBufferPos) flush(); if (samBufferPos) flush();
#endif #endif

View File

@@ -156,13 +156,23 @@ void Item::Parse() {
if (isValid()) { if (isValid()) {
// Todo - avoid static enlarge for every types // Todo - avoid static enlarge for every types
for (int i = aJson.getArraySize(itemArr); i < 4; i++) for (int i = aJson.getArraySize(itemArr); i < 4; i++)
aJson.addItemToArray(itemArr, aJson.createNull());//( (long int) 0)); aJson.addItemToArray(itemArr, aJson.createNull());
// int(defval[i]) )); //Enlarge item to 4 elements. VAL=int if no other definition in conf
//itemType = aJson.getArrayItem(itemArr, I_TYPE)->valueint; /*
itemType = replaceTypeToInt (aJson.getArrayItem(itemArr, I_TYPE)); itemType = replaceTypeToInt (aJson.getArrayItem(itemArr, I_TYPE));
itemArg = aJson.getArrayItem(itemArr, I_ARG); itemArg = aJson.getArrayItem(itemArr, I_ARG);
itemVal = aJson.getArrayItem(itemArr, I_VAL); itemVal = aJson.getArrayItem(itemArr, I_VAL);
itemExt = aJson.getArrayItem(itemArr, I_EXT); itemExt = aJson.getArrayItem(itemArr, I_EXT); */
aJsonObject * cmdObj = NULL;
aJsonObject * itemTypeObj = itemArr->child;
if (itemTypeObj) itemArg = itemTypeObj->next;
if (itemArg) itemVal = itemArg->next;
if (itemVal) cmdObj = itemVal->next;
if (cmdObj) itemExt = cmdObj->next;
itemType = replaceTypeToInt (itemTypeObj);
switch (itemType) switch (itemType)
{ {
#ifndef PWM_DISABLE #ifndef PWM_DISABLE
@@ -331,13 +341,13 @@ uint16_t getCanNum(aJsonObject* verb)
case aJson_Array: case aJson_Array:
{ {
aJsonObject *canNumObj=aJson.getArrayItem(verb,1); aJsonObject *canNumObj=aJson.getArrayItem(verb,1);
if (canNumObj->type == aJson_Int) return canNumObj->valueint; if (canNumObj && canNumObj->type == aJson_Int) return canNumObj->valueint;
return 0; return 0;
} }
case aJson_Object: case aJson_Object:
{ {
aJsonObject *canNumObj=aJson.getObjectItem(verb, "can"); aJsonObject *canNumObj=aJson.getObjectItem(verb, "can");
if (canNumObj->type == aJson_Int) return canNumObj->valueint; if (canNumObj && canNumObj->type == aJson_Int) return canNumObj->valueint;
return 0; return 0;
} }
} }
@@ -649,7 +659,7 @@ if (suffix = strrchr(*psubItem, '/')) //Trying to retrieve right part
*suffix= 0; //Truncate subItem string *suffix= 0; //Truncate subItem string
suffix++; suffix++;
suffixCode = txt2subItem(suffix); suffixCode = txt2subItem(suffix);
debugSerial<<F("suffixCode:")<<suffixCode<<endl; // debugSerial<<F("suffixCode:")<<suffixCode<<endl;
// myhome/dev/item/sub.....Item/suffix // myhome/dev/item/sub.....Item/suffix
} }
else else
@@ -684,7 +694,7 @@ long int Item::limitSetValue()
// myhome/dev/item/subItem // myhome/dev/item/subItem
int Item::Ctrl(char * payload, char * subItem) int Item::Ctrl(char * payload, char * subItem, int remoteID)
{ {
if (!payload) return 0; if (!payload) return 0;
int fr = freeRam(); int fr = freeRam();
@@ -709,13 +719,16 @@ if (suffixCode == S_RAW)
{ itemCmd ic; { itemCmd ic;
ic.Str(payload); ic.Str(payload);
ic.setSuffix(suffixCode); ic.setSuffix(suffixCode);
if (remoteID) return remoteCtrl(ic,remoteID,subItem);
return Ctrl(ic,subItem); return Ctrl(ic,subItem);
} }
bool authorized = false; bool authorized = false;
char * authPos = strchr(payload,'@'); char * authToken = NULL;
char * authPos = strchr(payload,'@'); //token@command
if (authPos) if (authPos)
{ {
authToken = payload;
*authPos=0; *authPos=0;
authorized = checkToken(payload,authPos+1); authorized = checkToken(payload,authPos+1);
payload=authPos+1; payload=authPos+1;
@@ -782,7 +795,7 @@ st.setSuffix(suffixCode);
default: errorSerial<<F("Wrong paylad")<<endl; default: errorSerial<<F("Wrong paylad")<<endl;
} }
} }
if (remoteID) return remoteCtrl(st,remoteID,subItem,authToken);
return Ctrl(st,subItem,true,authorized); return Ctrl(st,subItem,true,authorized);
} //Void command } //Void command
break; break;
@@ -806,7 +819,7 @@ st.setSuffix(suffixCode);
case 4: st.RGBW(Par[0],Par[1],Par[2],Par[3]); case 4: st.RGBW(Par[0],Par[1],Par[2],Par[3]);
default:; default:;
} }
if (remoteID) return remoteCtrl(st,remoteID,subItem,authToken);
return Ctrl(st,subItem,true,authorized); return Ctrl(st,subItem,true,authorized);
} }
case CMD_UP: case CMD_UP:
@@ -815,18 +828,40 @@ st.setSuffix(suffixCode);
itemCmd Par0 = getNumber((char **) &payload); itemCmd Par0 = getNumber((char **) &payload);
Par0.Cmd(cmd); Par0.Cmd(cmd);
Par0.setSuffix(suffixCode); Par0.setSuffix(suffixCode);
if (remoteID) return remoteCtrl(Par0,remoteID,subItem,authToken);
return Ctrl(Par0, subItem,true,authorized); return Ctrl(Par0, subItem,true,authorized);
} }
default: //some known command default: //some known command
{ {
int32_t intParam = getIntFromStr((char **) &payload); int32_t intParam = getIntFromStr((char **) &payload);
if (intParam) st.Int(intParam); if (intParam) st.Int(intParam);
if (remoteID) return remoteCtrl(st,remoteID,NULL,authToken);
return Ctrl(st,NULL, true, authorized); return Ctrl(st,NULL, true, authorized);
} }
} //ctrl } //ctrl
return 0; return 0;
} }
int Item::remoteCtrl(itemCmd cmd, int remoteID, char* subItem, char * authToken)
{
#ifdef CANDRV
// Retrieve remote item id
if (!itemArr) return 0;
aJsonObject * itemHandler = itemArr->child;
if (!itemHandler || itemHandler->type!=aJson_Array) return 0;
aJsonObject * itemIdObj=aJson.getArrayItem(itemHandler,1);
if (itemIdObj->type != aJson_Int) return 0;
//Retrieve target controller ID
if (!remoteID) return 0;
//TODO - translate subItem & auth token
short subitemNum = NO_SUBITEM;
return LHCAN.sendCommand(remoteID,itemIdObj->valueint,cmd,false,subitemNum);
#endif
return 0;
}
// Recursive function with small stack consumption // Recursive function with small stack consumption
// if cmd defined - execute Ctrl for any group members recursively // if cmd defined - execute Ctrl for any group members recursively
// else performs Activity check for group members and return true if any member is active // else performs Activity check for group members and return true if any member is active
@@ -836,7 +871,9 @@ bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool aut
aJsonObject *i = itemArr->child; aJsonObject *i = itemArr->child;
configLocked++; configLocked++;
while (i) { while (i) {
if (i->type == aJson_String) switch (i->type)
{
case aJson_String:
{ //debugSerial<< i->valuestring<<endl; { //debugSerial<< i->valuestring<<endl;
aJsonObject *nextItem = aJson.getObjectItem(rootItems, i->valuestring); aJsonObject *nextItem = aJson.getObjectItem(rootItems, i->valuestring);
if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item
@@ -844,8 +881,9 @@ bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool aut
Item it(nextItem); Item it(nextItem);
if (cmd && it.isValid()) it.Ctrl(*cmd,subItem,false,authorized); //Execute (non recursive) if (cmd && it.isValid()) it.Ctrl(*cmd,subItem,false,authorized); //Execute (non recursive)
//Retrieve itemType //Retrieve itemType
aJsonObject * itemtype = aJson.getArrayItem(nextItem,0); //aJsonObject * itemtype = aJson.getArrayItem(nextItem,0);
if (itemtype && itemtype->type == aJson_Int && itemtype->valueint == CH_GROUP) //if (itemtype && itemtype->type == aJson_Int && itemtype->valueint == CH_GROUP)
if (it.itemType == CH_GROUP)
{ //is Group { //is Group
aJsonObject * itemSubArray = aJson.getArrayItem(nextItem,1); aJsonObject * itemSubArray = aJson.getArrayItem(nextItem,1);
short res = digGroup(itemSubArray,cmd,subItem,authorized); short res = digGroup(itemSubArray,cmd,subItem,authorized);
@@ -863,6 +901,11 @@ bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool aut
} }
} }
} }
break;
case aJson_Object:
case aJson_Array:
executeCommand(i,-1,*cmd);
}//switch
i = i->next; i = i->next;
} //while } //while
configLocked--; configLocked--;
@@ -1663,7 +1706,7 @@ int Item::isActive() {
itemCmd st; itemCmd st;
int val = 0; int val = 0;
debugSerial<<itemArr->name<<F(" "); debugSerial<<F("ACTIVE:")<<itemArr->name<<F(" ");
if (!isValid()) if (!isValid())
{ {
debugSerial<<F(" invalid")<<endl; debugSerial<<F(" invalid")<<endl;
@@ -1841,7 +1884,8 @@ int Item::SendStatus(int sendFlags) {
st.debugOut(); st.debugOut();
#ifdef CANDRV #ifdef CANDRV
if (!(sendFlags & FLAG_NOT_SEND_CAN)) LHCAN.sendStatus(getCanNum(itemArr->child),st, getSubitemId(subItem)); if (!(sendFlags & FLAG_NOT_SEND_CAN))
LHCAN.sendStatus(getCanNum(itemArr->child),(sendFlags & FLAG_SEND_DELAYED)?st.setSuffix(S_DELAYED):st, getSubitemId(subItem));
#endif #endif
if (sendFlags & FLAG_COMMAND) if (sendFlags & FLAG_COMMAND)

View File

@@ -117,8 +117,8 @@ class Item
void Stop(); void Stop();
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL); //int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL);
int Ctrl(itemCmd cmd, char* subItem=NULL, bool allowRecursion = true, bool authorized=false); int Ctrl(itemCmd cmd, char* subItem=NULL, bool allowRecursion = true, bool authorized=false);
int Ctrl(char * payload, char * subItem=NULL); int Ctrl(char * payload, char * subItem=NULL, int remoteID = 0);
int remoteCtrl(itemCmd cmd, int remoteID, char* subItem=NULL, char * authToken=NULL);
int getArg(short n=0); int getArg(short n=0);
float getFloatArg(short n=0); float getFloatArg(short n=0);
short getArgCount(); short getArgCount();

View File

@@ -1454,7 +1454,9 @@ if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMappi
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0); if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
int diff = ((b-a)/(d-c))/2; int diff = ((b-a)/(d-c))/2;
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255)); //return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,b));
//return itemCmd().Int((uint32_t) map(getInt(),c,d,a,b)+diff);
} }
if (valMapping && valMapping->type == aJson_NULL) return itemCmd(); if (valMapping && valMapping->type == aJson_NULL) return itemCmd();
return *this; return *this;

View File

@@ -115,24 +115,24 @@ UID UniqueID;
#endif #endif
uint8_t brokers = 0; uint8_t brokers = 0;
char *deviceName = NULL; char *deviceName = NULL;
aJsonObject *topics = NULL; aJsonObject *topics = NULL;
aJsonObject *root = NULL; aJsonObject *root = NULL;
aJsonObject *items = NULL; aJsonObject *items = NULL;
aJsonObject *inputs = NULL; aJsonObject *inputs = NULL;
aJsonObject *brokersArr = NULL; aJsonObject *brokersArr = NULL;
aJsonObject *mqttArr = NULL; aJsonObject *mqttArr = NULL;
#ifdef _modbus #ifdef _modbus
aJsonObject *modbusObj = NULL; aJsonObject *modbusObj = NULL;
#endif #endif
#ifdef _owire #ifdef _owire
aJsonObject *owArr = NULL; aJsonObject *owArr = NULL;
#endif #endif
#ifdef _dmxout #ifdef _dmxout
aJsonObject *dmxArr = NULL; aJsonObject *dmxArr = NULL;
#endif #endif
#ifdef SYSLOG_ENABLE #ifdef SYSLOG_ENABLE
bool syslogInitialized = false; volatile bool syslogInitialized = false;
#endif #endif
#ifdef WIFI_ENABLE #ifdef WIFI_ENABLE
@@ -153,11 +153,11 @@ volatile uint32_t ultrasonicInputCheck=0;
aJsonObject *pollingItem = NULL; aJsonObject *pollingItem = NULL;
bool owReady = false; volatile bool owReady = false;
bool configOk = false; // At least once connected to MQTT volatile bool configOk = false; // At least once connected to MQTT
bool configLoaded = false; volatile bool configLoaded = false;
bool initializedListeners = false; volatile bool initializedListeners = false;
uint8_t DHCP_failures = 0; volatile uint8_t DHCP_failures = 0;
volatile int8_t ethernetIdleCount =0; volatile int8_t ethernetIdleCount =0;
volatile int8_t configLocked = 0; volatile int8_t configLocked = 0;
@@ -177,45 +177,19 @@ int8_t mqttErrorRate=0;
void watchdogSetup(void) {} //Do not remove - strong re-definition WDT Init for DUE void watchdogSetup(void) {} //Do not remove - strong re-definition WDT Init for DUE
#endif #endif
bool cleanConf(bool wait) bool cleanConf(short locksAlowed )
{ {
if (!root) return true; if (!root)
bool clean = true; {
if (configLocked) //debugSerial<<F("No root")<<endl;
return true;
}
if (configLocked>locksAlowed)
{ {
errorSerial<<F("Can not clean - locked")<<endl; errorSerial<<F("Can not clean - locked")<<endl;
return false; return false;
} }
/*
No more unsafe operations
if (wait)
{
debugSerial<<F("Unlocking config ...")<<endl;
uint32_t stamp=millis();
while (configLocked && !isTimeOver(stamp,millis(),10000))
{
//wdt_res();
cmdPoll();
#ifdef _owire
if (owReady && owArr) owLoop();
#endif
#ifdef _dmxin
DMXCheck();
#endif
if (isNotRetainingStatus()) pollingLoop();
thermoLoop();
inputLoop(CHECK_INPUT);
yield();
}
if (configLocked)
{
errorSerial<<F("Not unlocked in 10s - continue ...")<<endl;
clean = false;
}
} //wait
*/
debugSerial<<F("Stopping channels ...")<<endl; debugSerial<<F("Stopping channels ...")<<endl;
timerHandlerBusy++; timerHandlerBusy++;
//Stoping the channels //Stoping the channels
@@ -265,7 +239,7 @@ debugSerial<<F("Deleting conf. RAM was:")<<freeRam();
configOk=false; configOk=false;
timerHandlerBusy--; timerHandlerBusy--;
return clean; return true;
} }
bool isNotRetainingStatus() { bool isNotRetainingStatus() {
@@ -434,8 +408,11 @@ void mqttCallback(char *topic, byte *payload, unsigned int length)
short pfxlen = 0; short pfxlen = 0;
char * itemName = NULL; char * itemName = NULL;
char * subItem = NULL;
char savedTopic[MQTT_TOPIC_LENGTH] = ""; char savedTopic[MQTT_TOPIC_LENGTH] = "";
bool forLocal=false;
bool forBcast=false;
aJsonObject * remoteConfig = NULL;
int remoteID=0;
// 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 (lanStatus == RETAINING_COLLECTING) if (lanStatus == RETAINING_COLLECTING)
@@ -455,17 +432,53 @@ if (lanStatus == RETAINING_COLLECTING)
} }
return; return;
} }
else forLocal = true;
} }
else else
{ {
pfxlen=inTopic(topic,T_DEV); /* pfxlen=inTopic(topic,T_DEV);
if (!pfxlen) pfxlen = inTopic(topic,T_BCST); if (!pfxlen) pfxlen = inTopic(topic,T_BCST);
else // Personal device topic else // Personal device topic
strncpy(savedTopic,topic,sizeof(savedTopic)-1); strncpy(savedTopic,topic,sizeof(savedTopic)-1); //Save topic to delete after exec
*/
pfxlen=inTopic(topic,T_DEV);
if (pfxlen)
{
strncpy(savedTopic,topic,sizeof(savedTopic)-1); //Save topic to delete after exec
forLocal=true;
}
else
{
pfxlen = inTopic(topic,T_BCST);
if (pfxlen) forBcast = true;
}
//if (pfxlen) forLocal=true;
#ifdef CANDRV
// else //Nor local or bcst name, try can names
if (!forLocal && !forBcast)
{
pfxlen=inTopic(topic,T_ROOT); //check root
if (pfxlen)
{
remoteConfig = LHCAN.findConfbyName(topic+pfxlen,&remoteID);
if (remoteConfig)
{
while(*(topic+pfxlen) && *(topic+pfxlen)!='/') pfxlen++; //skip controller name
if (*(topic+pfxlen)=='/') pfxlen++;
debugSerial<<F("MQTT: remote command Item:")<<topic+pfxlen<<endl;
strncpy(savedTopic,topic,sizeof(savedTopic)-1); //Save topic to delete after exec
}
else pfxlen=0;
}
}
#endif
} }
if (!pfxlen) { if (!pfxlen) {
debugSerial<<F("Skipping..")<<endl; // debugSerial<<F("Skipping..")<<endl;
return;// -3; return;// -3;
} }
@@ -473,12 +486,15 @@ else
// debugSerial<<itemName<<endl; // debugSerial<<itemName<<endl;
if(!strcmp_P(itemName,CMDTOPIC_P) && payload && (strlen((char*) payload)>1)) { if(!strcmp_P(itemName,CMDTOPIC_P) && payload && (strlen((char*) payload)>1)) {
mqttClient.deleteTopic(topic); mqttClient.deleteTopic(topic);
cmd_parse((char *)payload); if (forLocal || forBcast) cmd_parse ((char *)payload);
//TODO implement for remote
return;// -4; return;// -4;
} }
//if (itemName[0]=='$') return;// -6; //Skipping homie stuff //if (itemName[0]=='$') return;// -6; //Skipping homie stuff
if (strrchr(topic,'$')) return; if (strrchr(topic,'$')) return;
/*
Item item(itemName); Item item(itemName);
if (item.isValid() && (item.Ctrl((char *)payload)>0) && savedTopic[0] && lanStatus != RETAINING_COLLECTING) if (item.isValid() && (item.Ctrl((char *)payload)>0) && savedTopic[0] && lanStatus != RETAINING_COLLECTING)
@@ -487,7 +503,37 @@ else
debugSerial<<F("MQTT: Complete. Remove topic ")<<savedTopic<<endl; debugSerial<<F("MQTT: Complete. Remove topic ")<<savedTopic<<endl;
mqttClient.deleteTopic(savedTopic); mqttClient.deleteTopic(savedTopic);
} }
*/
bool succeeded = false;
if (forLocal || forBcast)
{
Item item(itemName);
if (item.isValid()) //Local item
{
if (item.Ctrl((char *)payload)>0) succeeded = true;
}
}
#ifdef CANDRV
if (remoteConfig)
{
aJsonObject * remoteItems = aJson.getObjectItem(remoteConfig,"items");
if (remoteItems)
{
Item remoteItem(itemName,remoteItems);
if (remoteItem.Ctrl((char *)payload,NULL,remoteID)>0) succeeded = true;
}
}
/// TODO bcast - scan CAN
#endif
if (succeeded && savedTopic[0] && lanStatus != RETAINING_COLLECTING)
{
debugSerial<<F("MQTT: Complete. Remove topic ")<<savedTopic<<endl;
mqttClient.deleteTopic(savedTopic);
}
return;// -7; return;// -7;
} }
@@ -714,11 +760,16 @@ lan_status lanLoop() {
strncat(buf, "+/+/#", sizeof(buf)); // Subscribing only on separated command/parameters topics strncat(buf, "+/+/#", sizeof(buf)); // Subscribing only on separated command/parameters topics
mqttClient.unsubscribe(buf); mqttClient.unsubscribe(buf);
#ifdef CANDRV
setTopic(buf,sizeof(buf),T_ROOT);
LHCAN.subscribeTopics(buf,sizeof(buf));
#endif
onMQTTConnect(); onMQTTConnect();
#ifdef CRYPT #ifdef CRYPT
//setTopic(buf,sizeof(buf),T_OUT); setTopic(buf,sizeof(buf),T_ROOT);
strncpy(buf, "+/+/$salt", sizeof(buf)); // Only on separated cmd/val topics strncat(buf, "+/$salt", sizeof(buf)); // Only on separated cmd/val topics
mqttClient.subscribe(buf); mqttClient.subscribe(buf);
#endif #endif
@@ -1385,8 +1436,8 @@ return 200;
} }
#endif #endif
void applyConfig() { bool applyConfig() {
if (!root || configLocked) return; if (!root || configLocked) return false;
configLocked++; configLocked++;
infoSerial<<F("Applying config")<<endl; infoSerial<<F("Applying config")<<endl;
items = aJson.getObjectItem(root, "items"); items = aJson.getObjectItem(root, "items");
@@ -1532,6 +1583,7 @@ lanStatus=IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; ///change
if (lanStatus == OPERATION_NO_MQTT) lanStatus=IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; if (lanStatus == OPERATION_NO_MQTT) lanStatus=IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
configLocked--; configLocked--;
return configLoaded;
} }
void printConfigSummary() { void printConfigSummary() {
@@ -1593,8 +1645,9 @@ int loadConfigFromEEPROM()
if (sysConfStream.peek() == '{') { if (sysConfStream.peek() == '{') {
debugSerial<<F("JSON detected")<<endl; debugSerial<<F("JSON detected")<<endl;
if (root) cleanConf(1);
aJsonStream as = aJsonStream(&sysConfStream); aJsonStream as = aJsonStream(&sysConfStream);
cleanConf(false);
root = aJson.parse(&as); root = aJson.parse(&as);
sysConfStream.close(); sysConfStream.close();
if (!root) { if (!root) {
@@ -1605,6 +1658,7 @@ int loadConfigFromEEPROM()
return 0; return 0;
} }
infoSerial<<F("Loaded from EEPROM")<<endl; infoSerial<<F("Loaded from EEPROM")<<endl;
// debugSerial.print(aJson.print(root));
configLocked--; configLocked--;
applyConfig(); applyConfig();
sysConf.loadETAG(); sysConf.loadETAG();
@@ -1895,7 +1949,7 @@ if (!sysConf.getServer(configServer,sizeof(configServer)))
infoSerial<<F("got Config\n"); delay(500); infoSerial<<F("got Config\n"); delay(500);
aJsonFileStream as = aJsonFileStream(configStream); aJsonFileStream as = aJsonFileStream(configStream);
noInterrupts(); noInterrupts();
if (!cleanConf(true)) if (!cleanConf(0))
{ {
errorSerial<<F("Get aborted")<<endl; errorSerial<<F("Get aborted")<<endl;
hclient.closeStream(configStream); hclient.closeStream(configStream);
@@ -1972,7 +2026,7 @@ if (!sysConf.getServer(configServer,sizeof(configServer)))
if (responseStatusCode == 200) { if (responseStatusCode == 200) {
aJsonStream socketStream = aJsonStream(&htclient); aJsonStream socketStream = aJsonStream(&htclient);
debugSerial<<F("Free:")<<freeRam()<<endl; debugSerial<<F("Free:")<<freeRam()<<endl;
if (!cleanConf(true)) if (!cleanConf(0))
{ {
errorSerial<<F("Get aborted")<<endl; errorSerial<<F("Get aborted")<<endl;
htclient.stop(); htclient.stop();
@@ -2051,7 +2105,7 @@ if (!sysConf.getServer(configServer,sizeof(configServer)))
sysConf.setETAG(httpClient.header("ETag")); sysConf.setETAG(httpClient.header("ETag"));
//String response = httpClient.getString(); //String response = httpClient.getString();
//debugSerial<<response; //debugSerial<<response;
if (!cleanConf(true)) if (!cleanConf(0))
{ {
errorSerial<<F("Get aborted")<<endl; errorSerial<<F("Get aborted")<<endl;
httpClient.end(); httpClient.end();
@@ -2458,10 +2512,14 @@ WiFi.onEvent(WiFiEvent);
#endif #endif
#endif //NOIP #endif //NOIP
loadConfigFromEEPROM();
#ifdef CANDRV #ifdef CANDRV
LHCAN.begin(); LHCAN.begin();
#endif
loadConfigFromEEPROM();
#ifdef CANDRV
LHCAN.lookupMAC(); LHCAN.lookupMAC();
#endif #endif
} }
@@ -2659,6 +2717,18 @@ infoSerial<<F("\n(+)CAN");
#else #else
infoSerial<<F("\n(-)CAN"); infoSerial<<F("\n(-)CAN");
#endif #endif
#ifdef PULSEPIN12
infoSerial<<F("\n(+)PULSE on PIN12");
#else
infoSerial<<F("\n(-)PULSE on PIN12");
#endif
#ifdef CRYPT
infoSerial<<F("\n(+)CRYPT");
#else
infoSerial<<F("\n(-)CRYPT");
#endif
//#ifdef IPMODBUS //#ifdef IPMODBUS
//infoSerial<<F("\n(+)IPMODBUS"); //infoSerial<<F("\n(+)IPMODBUS");
//#endif //#endif
@@ -2733,7 +2803,6 @@ LHCAN.upTime(ut);
#endif #endif
} }
//#if not defined (NOIP)
void setupMacAddress() { void setupMacAddress() {
//Check MAC, stored in NVRAM //Check MAC, stored in NVRAM
@@ -2765,12 +2834,7 @@ if (!sysConf.getMAC()) {
#endif #endif
} }
printMACAddress(); printMACAddress();
#ifdef CANDRV
// LHCAN.lookupMAC();
#endif
} }
//#endif //NOIP
void setupCmdArduino() { void setupCmdArduino() {
//cmdInit(uint32_t(SERIAL_BAUD)); //cmdInit(uint32_t(SERIAL_BAUD));

View File

@@ -268,7 +268,7 @@ int cmdFunctionHelp(int arg_cnt, char **args);
int cmdFunctionKill(int arg_cnt, char **args); int cmdFunctionKill(int arg_cnt, char **args);
void applyConfig(); bool applyConfig();
int cmdFunctionLoad(int arg_cnt, char **args); int cmdFunctionLoad(int arg_cnt, char **args);
@@ -283,6 +283,8 @@ int cmdFunctionGet(int arg_cnt, char **args);
int cmdFunctionLoglevel(int arg_cnt, char **args); int cmdFunctionLoglevel(int arg_cnt, char **args);
void printBool(bool arg); void printBool(bool arg);
int cmdFunctionSave(int arg_cnt, char **args);
/* /*
void saveFlash(short n, char *str); void saveFlash(short n, char *str);
@@ -333,7 +335,7 @@ bool disabledDisconnected(const aJsonObject *thermoExtensionArray, int thermoLat
void resetHard(); void resetHard();
bool cleanConf(bool wait); bool cleanConf(short locksAlowed=0);
void printCurentLanConfig(); void printCurentLanConfig();

View File

@@ -303,11 +303,12 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
switch (defMappingObj->type) switch (defMappingObj->type)
{ {
case aJson_Int: //register/coil/.. number case aJson_Int: //register/coil/.. number
traceSerial<<F("Searching reg#")<<defMappingObj->valueint<<endl; traceSerial<<F("MBUSD: Searching reg#")<<defMappingObj->valueint<<endl;
if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo)) if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo))
{ {
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut); mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
executeWithoutCheck=true; executeWithoutCheck=true;
debugSerial<<"MBUSD: recurrent check res: "<<"SRO:"<<submitRecurrentOut<<endl;
} }
else else
{ {
@@ -410,8 +411,30 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name); aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
if (execObj) if (execObj)
{ {
bool storeLastValue = true;
if (doExecution)
{
storeLastValue=false;
// Check - if no action configured for object - not need to store last value - let requrent process do it
aJsonObject * i = execObj->child;
while (i && !storeLastValue)
{
if (i->name && *i->name && (*i->name != '@')) storeLastValue = true;
i=i->next;
}
}
aJsonObject * markObj = execObj; aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child; if (execObj->type == aJson_Array)
{
markObj = execObj->child;
storeLastValue = true;
}
if (storeLastValue)
{
//Retrive previous data //Retrive previous data
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S"); aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
if (lastMeasured) if (lastMeasured)
@@ -433,13 +456,14 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl; debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl;
aJson.addNumberToObject(markObj, "@S", (long) param); aJson.addNumberToObject(markObj, "@S", (long) param);
} }
}
if (executeWithoutCheck) if (executeWithoutCheck)
{ {
if (doExecution && (submitRecurrentOut || *submitParam)) if (doExecution && (submitRecurrentOut || *submitParam))
{ {
//debugSerial<<F("MBUS: exec ");mappedParam.debugOut();
executeCommand(execObj, -1, mappedParam); executeCommand(execObj, -1, mappedParam);
*submitParam=true; //if requrrent check has submit smth - report it. *submitParam=true; //if requrrent check has submit smth - report it.
} }
@@ -447,7 +471,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
return mappedParam; return mappedParam;
} }
if (*submitParam) if (*submitParam && doExecution)
{ {
// Compare with last submitted val (if @V NOT marked as NULL in config) // Compare with last submitted val (if @V NOT marked as NULL in config)
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V"); aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
@@ -458,7 +482,11 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
} }
else else
{ {
if (doExecution) executeCommand(execObj, -1, mappedParam); if (doExecution)
{
//debugSerial<<F("MBUS: exec ");mappedParam.debugOut();
executeCommand(execObj, -1, mappedParam);
}
// if param updated by device and no new value queued to send - update @V to avoid "Ignored - equal with setted val" // if param updated by device and no new value queued to send - update @V to avoid "Ignored - equal with setted val"
if (settedValue && !(execObj->subtype & MB_NEED_SEND)) if (settedValue && !(execObj->subtype & MB_NEED_SEND))
settedValue->valueint=param; settedValue->valueint=param;
@@ -556,13 +584,14 @@ int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valuebool) if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valuebool)
{ {
int modbusRegType = (outValue->subtype == PAR_COIL) ? MODBUS_COIL_REG_TYPE:MODBUS_HOLDING_REG_TYPE; int modbusRegType = (outValue->subtype == PAR_COIL) ? MODBUS_COIL_REG_TYPE:MODBUS_HOLDING_REG_TYPE;
debugSerial<<F("\nMBUS: prefetching ")<<paramName<<F(" #") <<regObj->valueint << " type:" << modbusRegType << " "; debugSerial<<F(" prefetch ")<<paramName<<F(" #") <<regObj->valueint << " type:" << modbusRegType << " ";
/// to prevent CORRUPTIOIN if using same buffer /// to prevent CORRUPTIOIN if using same buffer
uint16_t localBuffer; uint16_t localBuffer;
node.setResponseBuffer(&localBuffer,1); node.setResponseBuffer(&localBuffer,1);
bool successRead = readModbus(regObj->valueint,modbusRegType,1); bool successRead = readModbus(regObj->valueint,modbusRegType,1);
mbusSlenceTimer = millisNZ();
if (successRead) if (successRead)
@@ -607,6 +636,13 @@ if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valueboo
} }
else else
{ {
if (outValue->valueint == localBuffer)
{
debugSerial << F("MBUS:")<<paramName<< F("=")<<localBuffer<<F(": equal targert.")<<endl;
node.setDefaultResponseBuffer();
return -4;
}
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl; debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
} }
} }
@@ -664,7 +700,7 @@ int out_Modbus::Poll(short cause)
if (cause==POLLING_SLOW) return 0; if (cause==POLLING_SLOW) return 0;
bool lineInitialized = false; bool lineInitialized = false;
if (modbusBusy || (Status() != CST_INITIALIZED) || ( mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),100))) return 0; if (modbusBusy || (Status() != CST_INITIALIZED) || ( mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200))) return 0;
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2); aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
@@ -692,18 +728,23 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
int sendRes; int sendRes;
int savedValue; int savedValue;
bool needResend;
do do
{ {
savedValue = outValue->valueint; savedValue = outValue->valueint;
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" "; debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
sendRes = sendModbus(execObj->name,outValue); sendRes = sendModbus(execObj->name,outValue);
needResend = (savedValue != outValue->valueint);
while(needResend && mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200)) modbusIdle();
} }
while (savedValue != outValue->valueint); //repeat sending if target value changed while we're waited for mbus responce while (needResend); //repeat sending if target value changed while we're waited for mbus responce
switch (sendRes) switch (sendRes)
{ {
case 1: //success case 1: //success
execObj->subtype&=~ MB_NEED_SEND; case -4: //equal tatget
//execObj->subtype&=~ MB_NEED_SEND;
execObj->subtype = 0;
onceSendOk=true; onceSendOk=true;
///return 1; //relax ///return 1; //relax
break; break;
@@ -716,7 +757,8 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
case -3: case -3:
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" sending cancelled")<<endl; errorSerial<<F("MBUS: param ")<<execObj->name<<F(" sending cancelled")<<endl;
//outValue->valueint= //outValue->valueint=
execObj->subtype&=~ MB_NEED_SEND; //execObj->subtype&=~ MB_NEED_SEND;
execObj->subtype = 0;
break; break;
default: //param not found default: //param not found
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl; errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
@@ -730,7 +772,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
} }
if (isTimeOver(store->timestamp,millis(),store->pollingInterval) && ( !mbusSlenceTimer || isTimeOver(mbusSlenceTimer,millis(),100))) if (isTimeOver(store->timestamp,millis(),store->pollingInterval) && ( !mbusSlenceTimer || isTimeOver(mbusSlenceTimer,millis(),200)))
{ {
// Clean_up FLAG_SEND_ERROR flag // Clean_up FLAG_SEND_ERROR flag

View File

@@ -531,9 +531,12 @@ if (_l2 && _l2->type == aJson_String) strncat(buf,_l2->valuestring,buflen);
strncat_P(buf,inTopic,buflen); ///// strncat_P(buf,inTopic,buflen); /////
break; break;
} }
strncat(buf,"/",buflen);
if (suffix) strncat(buf,suffix,buflen);
if (tt!=T_ROOT)
{
strncat(buf,"/",buflen);
if (suffix) strncat(buf,suffix,buflen);
}
return buf; return buf;
} }
@@ -974,7 +977,19 @@ return true;
} }
#ifdef CANDRV
uint16_t getCRC(aJsonObject * in)
{
if (!in) return 0;
CRCStream crcStream;
aJsonStream aJsonCrcStream = aJsonStream(&crcStream);
//debugSerial<<"CRC: in";
//debugSerial.print(aJson.print(in));
aJson.print(in,&aJsonCrcStream,false);
//debugSerial<<"\nCRC:"<<crcStream.getCRC16();
return crcStream.getCRC16();
}
#endif
#pragma message(VAR_NAME_VALUE(debugSerial)) #pragma message(VAR_NAME_VALUE(debugSerial))
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD)) #pragma message(VAR_NAME_VALUE(SERIAL_BAUD))

View File

@@ -38,6 +38,7 @@ using namespace ios;
#endif #endif
enum topicType { enum topicType {
T_ROOT = 4,
T_DEV = 1, T_DEV = 1,
T_BCST= 2, T_BCST= 2,
T_OUT = 3 T_OUT = 3
@@ -80,4 +81,26 @@ int str2regSize(char * str);
bool checkToken(char * token, char * data); bool checkToken(char * token, char * data);
bool isProtectedPin(short pin); bool isProtectedPin(short pin);
bool i2cReset(); bool i2cReset();
uint16_t getCRC(aJsonObject * in);
#ifdef CANDRV
#include "util/crc16_.h"
class CRCStream : public Stream
{
public:
CRCStream() : CRC16(0xFFFF){}
uint16_t CRC16;
uint16_t getCRC16() {return CRC16;}
// Stream methods
virtual int available(){return 0;};
virtual int read(){return 0;};
virtual int peek(){return 0;};
virtual void flush(){};
// Print methods
virtual size_t write(uint8_t c) {CRC16 = crc16_update(CRC16, c);return 1;};
virtual int availableForWrite(){return 1;};
};
#endif

View File

@@ -359,6 +359,8 @@ lib_ignore =
ModbusMaster ModbusMaster
ClosedCube HDC1080 ClosedCube HDC1080
SparkFun CCS811 Arduino Library SparkFun CCS811 Arduino Library
;ArduinoOTA
ArduinoMDNS
;Adafruit BusIO ;Adafruit BusIO
;Adafruit MCP23017 Arduino Library ;Adafruit MCP23017 Arduino Library
;Adafruit Unified Sensor ;Adafruit Unified Sensor
@@ -388,7 +390,7 @@ lib_deps =
Adafruit MCP23017 Arduino Library Adafruit MCP23017 Arduino Library
Adafruit BusIO Adafruit BusIO
br3ttb/PID@^1.2.1 br3ttb/PID@^1.2.1
ArduinoMDNS ;ArduinoMDNS
;https://github.com/khoih-prog/TimerInterrupt_Generic.git ;https://github.com/khoih-prog/TimerInterrupt_Generic.git
monitor_speed = 115200 monitor_speed = 115200
@@ -820,7 +822,6 @@ lib_ignore =
DallasTemperature DallasTemperature
Adafruit Unified Sensor Adafruit Unified Sensor
DS2482_OneWire DS2482_OneWire
ModbusMaster
Syslog Syslog
;EEPROM ;EEPROM
ClosedCube HDC1080 ClosedCube HDC1080
@@ -843,6 +844,7 @@ lib_deps =
br3ttb/PID@^1.2.1 br3ttb/PID@^1.2.1
ArduinoMDNS ArduinoMDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
https://github.com/anklimov/ModbusMaster
monitor_speed = 115200 monitor_speed = 115200
@@ -888,7 +890,6 @@ lib_ignore =
DallasTemperature DallasTemperature
Adafruit Unified Sensor Adafruit Unified Sensor
DS2482_OneWire DS2482_OneWire
ModbusMaster
Syslog Syslog
NRFFlashStorage NRFFlashStorage
ClosedCube HDC1080 ClosedCube HDC1080
@@ -911,7 +912,8 @@ lib_deps =
br3ttb/PID@^1.2.1 br3ttb/PID@^1.2.1
ArduinoMDNS ArduinoMDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
;https://github.com/anklimov/ModbusMaster https://github.com/anklimov/ModbusMaster
https://github.com/anklimov/ModbusMaster
monitor_speed = 115200 monitor_speed = 115200
@@ -957,7 +959,6 @@ lib_ignore =
DallasTemperature DallasTemperature
Adafruit Unified Sensor Adafruit Unified Sensor
DS2482_OneWire DS2482_OneWire
ModbusMaster
Syslog Syslog
NRFFlashStorage NRFFlashStorage
ClosedCube HDC1080 ClosedCube HDC1080
@@ -980,7 +981,7 @@ lib_deps =
br3ttb/PID@^1.2.1 br3ttb/PID@^1.2.1
; ArduinoMDNS ; ArduinoMDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
;https://github.com/anklimov/ModbusMaster https://github.com/anklimov/ModbusMaster
pazi88/STM32_CAN pazi88/STM32_CAN
ericksimoes/Ultrasonic ericksimoes/Ultrasonic