CAN DUE, relative items, CAN-MQTT brige

This commit is contained in:
2024-03-30 08:29:53 +03:00
parent 242db1552e
commit 4fff338482
7 changed files with 128 additions and 48 deletions

View File

@@ -8,7 +8,7 @@
#if defined(ARDUINO_ARCH_STM32)
#include <STM32_CAN.h>
STM32_CAN STMCan( CAN1, ALT, RX_SIZE_64, TX_SIZE_16 );
STM32_CAN STMCan( CAN1, CAN_PINS::DEF, RX_SIZE_64, TX_SIZE_16 );
#endif
#if defined(ARDUINO_ARCH_ESP32)
@@ -24,6 +24,7 @@ extern systemConfig sysConf;
extern canStream CANConfStream;
extern aJsonObject * root;
extern volatile int8_t configLocked;
extern bool configLoaded;
void printFrame(datagram_t * frame, uint8_t len ) {
@@ -163,6 +164,13 @@ bool canDriver::begin()
#if defined(__SAM3X8E__)
Can0.begin(CAN_BPS_125K);
int filter;
//extended
for (filter = 0; filter < 3; filter++) {
Can0.setRXFilter(filter, 0, 0, true);
//Can1.setRXFilter(filter, 0, 0, true);
}
#endif
debugSerial<<"CAN initialized"<<endl;
@@ -232,10 +240,15 @@ int canDriver::readFrame()
//DUE
#if defined(__SAM3X8E__)
CAN_FRAME incoming;
CAN_FRAME CAN_RX_msg;
if (Can0.available() > 0) {
Can0.read(incoming);
printFrame(incoming);
Can0.read(CAN_RX_msg);
if (CAN_RX_msg.length>8) CAN_RX_msg.length=8;
memcpy(RXpacket.data, CAN_RX_msg.data.bytes,CAN_RX_msg.length);
RXlen = CAN_RX_msg.length;
RXid.id = CAN_RX_msg.id;
return RXlen;
}
#endif
@@ -263,8 +276,10 @@ switch (state)
break;
case canState::Error:
if (isTimeOver(responseTimer,millis(),10000UL))
lookupMAC();
if (configLoaded) state=canState::ConfigLoaded;
else
if (isTimeOver(responseTimer,millis(),10000UL))
lookupMAC();
break;
case canState::ReadConfig:
@@ -314,13 +329,51 @@ bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool
{
debugSerial.print("CAN Received ");
debugSerialPort.print(len);
debugSerialPort.print(" bytes id 0x");
debugSerialPort.println(id.id,HEX);
debugSerial.print(len);
debugSerial.print(" bytes id 0x");
debugSerial.print(id.id,HEX);
if (len) printFrame(packet,len);
if (id.status)
if (id.status){
//Responces
//@ any state
switch (id.payloadType)
{
case payloadType::itemCommand:
{
if (len!=8) return false;
aJsonObject *confObj = findConfbyID(id.deviceId);
if (confObj)
{
debugSerial<<F("CAN: status received for dev ")<<id.deviceId<<endl;
//char * itemNName = findItemName(id.itemId);
aJsonObject *itemsObj = aJson.getObjectItem(confObj,"items");
if (!itemsObj) return false;;
Item it(id.itemId, itemsObj);
if (it.isValid())
{
itemCmd ic;
uint16_t flags = 0;
ic.cmd = packet->cmd;
ic.param = packet->param;
debugSerial<<F("CAN: item ")<<it.itemArr->name;
ic.debugOut();
if (ic.isCommand()) flags |= FLAG_COMMAND;
if (ic.isValue()) flags |= FLAG_PARAMETERS;
ic.saveItem(&it,flags);
it.SendStatusImmediate(ic,flags | FLAG_NOT_SEND_CAN);
return true;
}
}
}
break;
}
switch (state)
{
case canState::MACLookup:
@@ -346,8 +399,19 @@ if (id.status)
case canState::Error:
return false;
}
}
else //Requests
{
/*
switch (id.payloadType)
{
case payloadType::itemCommand:
break;
case payloadType::sysCmd:
break;
}*/
if ((id.payloadType == payloadType::itemCommand) && (len ==8))
{
Item it(id.itemId);
@@ -439,7 +503,7 @@ uint8_t canDriver::getIdByMac(macAddress mac)
memset(macStr,0,sizeof(macStr));
for (byte i = 0; i < 6; i++)
{
if (mac[i]<16) macStr[strptr++]='0';
// if (mac[i]<16) macStr[strptr++]='0';
SetBytes(&mac[i],1,&macStr[strptr]);
strptr+=2;
@@ -494,16 +558,16 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
#endif
#if defined(__SAM3X8E__)
CAN_FRAME outGoting;
outgoing.id = 0x400;
outgoing.extended = true;
outgoing.priority = 4; //0-15 lower is higher priority
outgoing.data.s0 = 0xFEED;
outgoing.data.byte[2] = 0xDD;
outgoing.data.byte[3] = 0x55;
outgoing.data.high = 0xDEADBEEF;
Can0.sendFrame(outgoing);
CAN_FRAME CAN_TX_msg;
CAN_TX_msg.id = msg_id;
CAN_TX_msg.extended = true;
CAN_TX_msg.length=size;
//outgoing.priority = 4; //0-15 lower is higher priority
if (buf) for(uint8_t i=0;i<size; i++) CAN_TX_msg.data.bytes[i]=buf->data[i];
res=Can0.sendFrame(CAN_TX_msg);
if (res) debugSerial<<("CAN Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
else debugSerial.println("CAN Write error");
return res;
#endif
}
@@ -519,8 +583,10 @@ bool canDriver::sendStatus(uint8_t itemNum, itemCmd cmd)
bool canDriver::sendCommand(aJsonObject * can,itemCmd cmd, bool status)
{
debugSerial<<"CAN: sendCommand ";
cmd.debugOut();
// debugSerial<<"CAN: ";
// if (status) debugSerial<<F("sendStatus ");
// else debugSerial<<F("sendCommand ");
// cmd.debugOut();
if (can && (can->type == aJson_Array))
{
@@ -549,7 +615,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
packet.cmd = cmd.cmd;
packet.param = cmd.param;
debugSerial << ((status)?"CAN: Status":"CAN: Command");
debugSerial << ((status)?"CAN: send Status":"CAN: send Command");
debugSerial<<F(" for dev:item ")<<devID<<":"<<itemID<<" ";
cmd.debugOut();

View File

@@ -93,7 +93,7 @@ typedef union {
enum canState
{
Unknown,
stateUnknown,
MACLookup,
Idle,
StreamOpenedWrite,
@@ -110,7 +110,7 @@ Error
class canDriver
{
public:
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::Unknown;};
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::stateUnknown;};
uint8_t getMyId();
bool sendStatus(uint8_t itemNum, itemCmd cmd);
bool sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool status=false);
@@ -139,6 +139,11 @@ private:
CAN_message_t CAN_RX_msg;
CAN_message_t CAN_TX_msg;
#endif
#if defined(__SAM3X8E__)
//CAN_FRAME CAN_RX_msg;
#endif
bool ready;
@@ -156,7 +161,7 @@ extern aJsonObject * topics;
class canStream : public Stream
{
public:
canStream(canDriver * _driver) : readPos(0),writePos(0),devId(0), pType(payloadType::unknown),state(canState::Unknown){driver=_driver; }
canStream(canDriver * _driver) : readPos(0),writePos(0),devId(0), pType(payloadType::unknown),state(canState::stateUnknown){driver=_driver; }
int open(uint8_t controllerID, payloadType _pType, char _mode)
{
if (mode) close();
@@ -171,7 +176,7 @@ public:
{
if ((mode == 'w') && writePos) flush();
mode = '\0';
state=canState::Unknown;
state=canState::stateUnknown;
return 1;
}

View File

@@ -141,8 +141,9 @@ int txt2subItem(char *payload) {
//const short defval[4] = {0, 0, 0, 0}; //Type,Arg,Val,Cmd
Item::Item(aJsonObject *obj)//Constructor
Item::Item(aJsonObject *obj, aJsonObject *_items)//Constructor
{
rootItems=_items;
itemArr = obj;
driver = NULL;
*defaultSubItem = 0;
@@ -291,13 +292,14 @@ Item::~Item()
}
}
Item::Item(char *name) //Constructor
Item::Item(char *name, aJsonObject *_items) //Constructor
{
char * pDefaultSubItem = defaultSubItem;
rootItems=_items;
driver = NULL;
defaultSubItem[0] =0;
defaultSuffixCode = 0;
if (name && items)
if (name && rootItems)
{ char* sub;
if (sub=strchr(name,'/'))
{
@@ -306,7 +308,7 @@ Item::Item(char *name) //Constructor
for(i=0;(name[i] && (name[i]!='/') && (i<MQTT_SUBJECT_LENGTH));i++)
buf[i]=name[i];
buf[i]=0;
itemArr = aJson.getObjectItem(items, buf);
itemArr = aJson.getObjectItem(rootItems, buf);
sub++;
strncpy(defaultSubItem,sub,sizeof(defaultSubItem)-1);
defaultSuffixCode = retrieveCode (&pDefaultSubItem);
@@ -314,7 +316,7 @@ Item::Item(char *name) //Constructor
//debugSerial<<F("defaultSubItem: ")<<defaultSubItem<<F(" defaultSuffixCode:")<<defaultSuffixCode<<endl;
}
else
itemArr = aJson.getObjectItem(items, name);
itemArr = aJson.getObjectItem(rootItems, name);
}
else itemArr = NULL;
Parse();
@@ -341,20 +343,21 @@ uint8_t getCanNum(aJsonObject* verb)
return 0;
}
Item::Item(uint16_t num)
Item::Item(uint16_t num, aJsonObject *_items)
{
itemArr = NULL;
itemArg = NULL;
itemVal = NULL;
itemExt = NULL;
rootItems=_items;
driver = NULL;
defaultSubItem[0] =0;
defaultSuffixCode = 0;
if (!items) return;
itemArr = items->child;
if (!rootItems) return;
itemArr = rootItems->child;
while (itemArr)
{
if (getCanNum(itemArr->child) == num)
@@ -778,7 +781,7 @@ return 0;
// Recursive function with small stack consumption
// 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
bool digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized)
bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized)
{ if (!itemArr || itemArr->type!=aJson_Array) return false;
// Iterate across array of names
aJsonObject *i = itemArr->child;
@@ -786,7 +789,7 @@ bool digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorize
while (i) {
if (i->type == aJson_String)
{ //debugSerial<< i->valuestring<<endl;
aJsonObject *nextItem = aJson.getObjectItem(items, i->valuestring);
aJsonObject *nextItem = aJson.getObjectItem(rootItems, i->valuestring);
if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item
{
Item it(nextItem);
@@ -1789,7 +1792,7 @@ int Item::SendStatus(int sendFlags) {
st.debugOut();
#ifdef CANDRV
LHCAN.sendStatus(getCanNum(itemArr->child),st);
if (!(sendFlags & FLAG_NOT_SEND_CAN)) LHCAN.sendStatus(getCanNum(itemArr->child),st);
#endif
if (sendFlags & FLAG_COMMAND)
@@ -2501,7 +2504,7 @@ int Item::checkModbusDimmer() {
nextItem.checkModbusDimmer(data);
pollingItem = pollingItem->next;
if (!pollingItem)
pollingItem = items->child;
pollingItem = rootItems->child;
}
} else
debugSerial << F("MB: polling ") << itemArr->name<< F(" error=") << _HEX(result) << endl;

View File

@@ -98,17 +98,17 @@ extern aJsonObject *items;
extern short thermoSetCurTemp(char *name, float t);
int txt2cmd (char * payload);
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false);
class Item
{
public:
aJsonObject *itemArr, *itemArg,*itemVal,*itemExt;
aJsonObject *rootItems, *itemArr, *itemArg,*itemVal,*itemExt;
uint8_t itemType;
abstractOut * driver;
Item(char * name);
Item(aJsonObject * obj);
Item(uint16_t num);
Item(char * name, aJsonObject *_items = items);
Item(aJsonObject * obj, aJsonObject *_items = items);
Item(uint16_t num, aJsonObject *_items = items);
~Item();
boolean isValid ();
@@ -148,7 +148,9 @@ class Item
int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized);
int isScheduled();
protected:
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false);
long int limitSetValue();
int VacomSetFan (itemCmd st);
int VacomSetHeat(itemCmd st);

View File

@@ -119,7 +119,7 @@ const ch_type ch_type_P[] PROGMEM =
#define FLAG_HALTED 0x40000UL
#define FLAG_XON 0x80000UL
#define FLAG_NOT_SEND_CAN 0x2UL
int txt2cmd (char * payload);

View File

@@ -766,7 +766,9 @@ switch (cmdType)
if (mqttClient.connected() && !ethernetIdleCount)
{
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); ///ChangeMe - if no '/' in addr - template not working
debugSerial << F("MQTT: ")<<addrstr<< F(" -> ")<<emitCommand<<endl;
mqttClient.publish(addrstr, emitCommand , true);
}
} // emit

View File

@@ -733,6 +733,8 @@ lib_deps =
https://github.com/khoih-prog/TimerInterrupt_Generic.git
https://github.com/rlogiacco/CircularBuffer
rweather/Crypto
https://github.com/collin80/due_can.git
https://github.com/collin80/can_common.git
monitor_speed = 115200
[env:controllino]