mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 03:39:49 +03:00
CAN: config retrieving from master
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
#
|
||||||
-DWIFI_ENABLE
|
-DWIFI_ENABLE
|
||||||
-DDMX_DISABLE
|
-DDMX_DISABLE
|
||||||
# - exeption in DMX.update/begin
|
# - exeption in DMX.update/begin
|
||||||
@@ -12,7 +13,7 @@
|
|||||||
-DARDUINO_OTA_MDNS_DISABLE
|
-DARDUINO_OTA_MDNS_DISABLE
|
||||||
-DMDNS_ENABLE
|
-DMDNS_ENABLE
|
||||||
#- ArduinoMDNS didnt working
|
#- ArduinoMDNS didnt working
|
||||||
|
-D CANDRV
|
||||||
-DMCP23017
|
-DMCP23017
|
||||||
-DMODBUS_TX_PIN=13
|
-DMODBUS_TX_PIN=13
|
||||||
#-DARTNET_ENABLE - udp rx errors ((
|
#-DARTNET_ENABLE - udp rx errors ((
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <candriver.h>
|
#include <candriver.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_STM32)
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
@@ -20,6 +21,9 @@ STM32_CAN STMCan( CAN1, ALT, RX_SIZE_64, TX_SIZE_16 );
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
//#include <systemconfigdata.h>
|
//#include <systemconfigdata.h>
|
||||||
extern systemConfig sysConf;
|
extern systemConfig sysConf;
|
||||||
|
extern canStream CANConfStream;
|
||||||
|
extern aJsonObject * root;
|
||||||
|
extern volatile int8_t configLocked;
|
||||||
|
|
||||||
|
|
||||||
void printFrame(datagram_t * frame, uint8_t len ) {
|
void printFrame(datagram_t * frame, uint8_t len ) {
|
||||||
@@ -91,22 +95,47 @@ bool canDriver::lookupMAC()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType )
|
||||||
|
{
|
||||||
|
canid_t id;
|
||||||
|
datagram_t packet;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
|
||||||
|
id.reserve=0;
|
||||||
|
id.status=0;
|
||||||
|
id.payloadType=_payloadType;
|
||||||
|
id.deviceId=devId;
|
||||||
|
id.itemId=0; //CRC?
|
||||||
|
packet.metric1 =0;
|
||||||
|
//memcpy(packet.mac,sysConf.mac,6);
|
||||||
|
|
||||||
|
debugSerial<<("Request frame ")<<_payloadType<<F(" for id ")<<devId<<endl;
|
||||||
|
res=write (id.id,&packet,1);
|
||||||
|
if (res) state=canState::FrameRequested;
|
||||||
|
else state=canState::Error;
|
||||||
|
responseTimer=millisNZ();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
bool canDriver::sendRemoteID(macAddress mac)
|
bool canDriver::sendRemoteID(macAddress mac)
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
//datagram_t packet;
|
//datagram_t packet;
|
||||||
bool res=false;
|
bool res=false;
|
||||||
|
id.deviceId=getIdByMac(mac); //Retrieved controllerID
|
||||||
|
if (!id.deviceId) return false;
|
||||||
|
|
||||||
id.reserve=0;
|
id.reserve=0;
|
||||||
id.status=1; //response
|
id.status=1; //response
|
||||||
id.payloadType=payloadType::lookupMAC;
|
id.payloadType=payloadType::lookupMAC;
|
||||||
id.deviceId=100; //Retrieved controllerID
|
|
||||||
id.itemId=200; //CRC of remote config
|
id.itemId=200; //CRC16 of remote config
|
||||||
//packet.data[0]=1;
|
//packet.data[0]=1;
|
||||||
|
|
||||||
debugSerial<<("Send remote ID")<<endl;
|
debugSerial<<("Send remote ID")<<endl;
|
||||||
res = write (id.id);//,&packet,8);
|
res = write (id.id);//,&packet,8);
|
||||||
if (res) state=canState::HaveId;
|
if (res) state=canState::Idle;
|
||||||
else state=canState::Error;
|
else state=canState::Error;
|
||||||
// responseTimer=millisNZ(); ????????
|
// responseTimer=millisNZ(); ????????
|
||||||
return res;
|
return res;
|
||||||
@@ -137,24 +166,27 @@ bool canDriver::begin()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
debugSerial<<"CAN initialized"<<endl;
|
debugSerial<<"CAN initialized"<<endl;
|
||||||
|
controllerId = getMyId();
|
||||||
ready=true;
|
ready=true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void canDriver::Poll()
|
int canDriver::readFrame()
|
||||||
{
|
{
|
||||||
// return ;
|
if (!ready) return -1;
|
||||||
if (!ready) return;
|
//STM32
|
||||||
//STM32
|
|
||||||
#if defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_STM32)
|
||||||
if (STMCan.read(CAN_RX_msg))
|
if (STMCan.read(CAN_RX_msg))
|
||||||
{
|
{
|
||||||
processPacket( CAN_RX_msg.id, (datagram_t*) CAN_RX_msg.buf,CAN_RX_msg.len);
|
if (CAN_RX_msg.len>8) CAN_RX_msg.len=8;
|
||||||
|
memcpy(RXpacket.data, CAN_RX_msg.buf,CAN_RX_msg.len);
|
||||||
|
RXlen = CAN_RX_msg.len;
|
||||||
|
RXid.id = CAN_RX_msg.id;
|
||||||
|
return RXlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
// try to parse packet
|
// try to parse packet
|
||||||
int packetSize = CAN.parsePacket();
|
int packetSize = CAN.parsePacket();
|
||||||
|
|
||||||
@@ -182,21 +214,22 @@ void canDriver::Poll()
|
|||||||
//debugSerialPort.println(packetSize);
|
//debugSerialPort.println(packetSize);
|
||||||
debugSerialPort.println(CAN.packetDlc());
|
debugSerialPort.println(CAN.packetDlc());
|
||||||
|
|
||||||
datagram_t packet;
|
|
||||||
// only print packet data for non-RTR packets
|
// only print packet data for non-RTR packets
|
||||||
int i=0;
|
RXlen=0;
|
||||||
while (CAN.available()) {
|
while (CAN.available()) {
|
||||||
packet.data[i++]=CAN.read();
|
RXpacket.data[RXlen++]=CAN.read();
|
||||||
//debugSerialPort.print((char)CAN.read());
|
if (RXlen>=8) break;
|
||||||
if (i>=8) break;
|
|
||||||
}
|
}
|
||||||
debugSerialPort.println();
|
RXid.id = CAN.packetId();
|
||||||
|
|
||||||
processPacket( CAN.packetId(), &packet,i);
|
debugSerialPort.println();
|
||||||
|
return RXlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//DUE
|
//DUE
|
||||||
#if defined(__SAM3X8E__)
|
#if defined(__SAM3X8E__)
|
||||||
CAN_FRAME incoming;
|
CAN_FRAME incoming;
|
||||||
@@ -207,12 +240,20 @@ void canDriver::Poll()
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void canDriver::Poll()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (readFrame()>=0) processPacket( RXid, &RXpacket, RXlen);
|
||||||
//State machine
|
//State machine
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case canState::MACLookup:
|
case canState::MACLookup:
|
||||||
|
// case canState::FrameRequested:
|
||||||
|
|
||||||
if (isTimeOver(responseTimer,millis(),1000UL))
|
if (isTimeOver(responseTimer,millis(),1000UL))
|
||||||
{
|
{
|
||||||
responseTimer=millisNZ();
|
responseTimer=millisNZ();
|
||||||
@@ -226,55 +267,189 @@ switch (state)
|
|||||||
lookupMAC();
|
lookupMAC();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case canState::HaveId:
|
case canState::ReadConfig:
|
||||||
|
{
|
||||||
|
//Blocking read config
|
||||||
|
if (configLocked) return; // only in safe moments
|
||||||
|
configLocked++;
|
||||||
|
|
||||||
|
infoSerial<<F("Requesting Config from CAN")<<endl;
|
||||||
|
|
||||||
|
CANConfStream.open(controllerId,payloadType::configFrame,'r');
|
||||||
|
|
||||||
|
if (CANConfStream.peek() == '{') {
|
||||||
|
debugSerial<<F("JSON detected")<<endl;
|
||||||
|
aJsonStream as = aJsonStream(&CANConfStream);
|
||||||
|
cleanConf(false);
|
||||||
|
root = aJson.parse(&as);
|
||||||
|
CANConfStream.close();
|
||||||
|
if (!root) {
|
||||||
|
errorSerial<<F("load failed")<<endl;
|
||||||
|
sysConf.setETAG("");
|
||||||
|
// sysConfStream.close();
|
||||||
|
configLocked--;
|
||||||
|
state = canState::Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
infoSerial<<F("Loaded from CAN")<<endl;
|
||||||
|
configLocked--;
|
||||||
|
applyConfig();
|
||||||
|
sysConf.loadETAG();
|
||||||
|
state = canState::Idle;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
CANConfStream.close();
|
||||||
|
infoSerial<<F("Config not loaded")<<endl;
|
||||||
|
state = canState::Error;
|
||||||
|
configLocked--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case canState::Idle:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canDriver::processPacket(uint32_t rawid, datagram_t *packet, uint8_t len, bool rtr)
|
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
||||||
{
|
{
|
||||||
canid_t id;
|
|
||||||
id.id = rawid;
|
|
||||||
debugSerial.print("CAN Received ");
|
debugSerial.print("CAN Received ");
|
||||||
debugSerialPort.print(len);
|
debugSerialPort.print(len);
|
||||||
debugSerialPort.print(" bytes id 0x");
|
debugSerialPort.print(" bytes id 0x");
|
||||||
debugSerialPort.println(id.id,HEX);
|
debugSerialPort.println(id.id,HEX);
|
||||||
|
|
||||||
printFrame(packet,len);
|
if (len) printFrame(packet,len);
|
||||||
if (id.status)
|
if (id.status)
|
||||||
//Responces
|
//Responces
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case canState::MACLookup:
|
case canState::MACLookup:
|
||||||
if ((id.payloadType == payloadType::lookupMAC) && (len>=6))
|
if ((id.payloadType == payloadType::lookupMAC))
|
||||||
{
|
{
|
||||||
debugSerial<<"Got Controller CAN addr: "<<id.deviceId<<endl;
|
debugSerial<<"Got Controller CAN addr: "<<id.deviceId<<endl;
|
||||||
controllerId=id.deviceId;
|
controllerId=id.deviceId;
|
||||||
|
state = canState::ReadConfig;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case canState::HaveId:
|
|
||||||
|
case canState::FrameRequested:
|
||||||
|
if ((id.payloadType == payloadType::configFrame) && (id.deviceId == controllerId))
|
||||||
|
{
|
||||||
|
errorSerial<<F("Config received when not expected")<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case canState::Idle:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case canState::Error:
|
case canState::Error:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else //Requests
|
else //Requests
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (id.payloadType == payloadType::lookupMAC)
|
if ((id.payloadType == payloadType::lookupMAC) && (len>=6))
|
||||||
{
|
{
|
||||||
return sendRemoteID(packet->mac);
|
return sendRemoteID(packet->mac);
|
||||||
//debugSerial<<"ID requested"<<endl;
|
//debugSerial<<"ID requested"<<endl;
|
||||||
}
|
}
|
||||||
|
else if (id.payloadType == payloadType::configFrame)
|
||||||
|
{
|
||||||
|
debugSerial<<F("Requested conf for dev#")<<id.deviceId<<endl;
|
||||||
|
aJsonObject * remoteConfObj = findConfbyID(id.deviceId);
|
||||||
|
if (remoteConfObj)
|
||||||
|
{
|
||||||
|
infoSerial<<F("Sending conf for dev#")<<id.deviceId<<endl;
|
||||||
|
CANConfStream.open(id.deviceId,payloadType::configFrame,'w');
|
||||||
|
aJsonStream outStream = aJsonStream(&CANConfStream);
|
||||||
|
aJson.print(remoteConfObj, &outStream);
|
||||||
|
CANConfStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
//debugSerial<<"ID requested"<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t canDriver::getMyId()
|
||||||
|
{
|
||||||
|
if (!root) return 0;
|
||||||
|
aJsonObject * canObj = aJson.getObjectItem(root, "can");
|
||||||
|
if (!canObj) return 0;
|
||||||
|
|
||||||
|
aJsonObject * addrObj = aJson.getObjectItem(canObj, "addr");
|
||||||
|
if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * canDriver::findConfbyID(uint8_t devId)
|
||||||
|
{
|
||||||
|
if (!root) return NULL;
|
||||||
|
aJsonObject * canObj = aJson.getObjectItem(root, "can");
|
||||||
|
if (!canObj) return NULL;
|
||||||
|
|
||||||
|
aJsonObject * remoteConfObj = aJson.getObjectItem(canObj, "conf");
|
||||||
|
|
||||||
|
if (!remoteConfObj) return NULL;
|
||||||
|
remoteConfObj=remoteConfObj->child;
|
||||||
|
while (remoteConfObj)
|
||||||
|
{
|
||||||
|
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
|
||||||
|
if (remoteCanObj)
|
||||||
|
{
|
||||||
|
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
|
||||||
|
if (addrObj && (addrObj->type == aJson_Int) && (addrObj->valueint == devId)) return remoteConfObj;
|
||||||
|
}
|
||||||
|
remoteConfObj=remoteConfObj->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t canDriver::getIdByMac(macAddress mac)
|
||||||
|
{
|
||||||
|
char macStr[19];
|
||||||
|
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';
|
||||||
|
|
||||||
|
SetBytes(&mac[i],1,&macStr[strptr]);
|
||||||
|
strptr+=2;
|
||||||
|
|
||||||
|
if (i < 5) macStr[strptr++]=':';
|
||||||
|
}
|
||||||
|
debugSerial<<F("Searching devId for ")<<macStr<<endl;
|
||||||
|
aJsonObject * remoteConfObj = aJson.getObjectItem(confObj, macStr);
|
||||||
|
|
||||||
|
if (!remoteConfObj) return 0;
|
||||||
|
|
||||||
|
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
|
||||||
|
if (!remoteCanObj) return 0;
|
||||||
|
|
||||||
|
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
|
||||||
|
if (!addrObj) return 0;
|
||||||
|
if (addrObj && (addrObj->type == aJson_Int))
|
||||||
|
{
|
||||||
|
debugSerial<<F("find dev#")<< addrObj->valueint << endl;
|
||||||
|
return addrObj->valueint;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
{ //return 0;
|
||||||
@@ -289,7 +464,7 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
CAN_TX_msg.id = msg_id;
|
CAN_TX_msg.id = msg_id;
|
||||||
CAN_TX_msg.flags.extended = 1; // To enable extended ID
|
CAN_TX_msg.flags.extended = 1; // To enable extended ID
|
||||||
CAN_TX_msg.len=size;
|
CAN_TX_msg.len=size;
|
||||||
if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN Wrote ")<<size<<" bytes"<<endl;
|
if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
||||||
else debugSerial.println("CAN Write error");
|
else debugSerial.println("CAN Write error");
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
@@ -299,7 +474,7 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
CAN.beginExtendedPacket(msg_id,size);
|
CAN.beginExtendedPacket(msg_id,size);
|
||||||
CAN.write(buf->data,size);
|
CAN.write(buf->data,size);
|
||||||
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
|
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
|
||||||
if (res=CAN.endPacket()) debugSerial.println("CAN Wrote");
|
if (res=CAN.endPacket()) debugSerial<< ("CAN Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;
|
||||||
else debugSerial.println("CAN Write error");
|
else debugSerial.println("CAN Write error");
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
@@ -319,4 +494,192 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool canDriver::sendStatus(char * itemName, itemCmd cmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////// Steream //////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
int canStream::send(uint8_t len)
|
||||||
|
{
|
||||||
|
canid_t id;
|
||||||
|
datagram_t packet;
|
||||||
|
bool res;
|
||||||
|
if (!driver) return 0;
|
||||||
|
id.reserve=0;
|
||||||
|
id.status=1;
|
||||||
|
id.payloadType=pType;
|
||||||
|
id.deviceId=devId;
|
||||||
|
id.itemId=0; // chunk?
|
||||||
|
|
||||||
|
res=driver->write (id.id, &writeBuffer, len);
|
||||||
|
writePos=0;
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
//Await check?
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int canStream::checkState()
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
if (!driver) return -1;
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case canState::StreamOpenedRead:
|
||||||
|
readPos = 0;
|
||||||
|
res= driver->requestFrame(devId,pType); //Requesting frame;
|
||||||
|
if (res)
|
||||||
|
state = canState::FrameRequested;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = canState::Error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//continue
|
||||||
|
|
||||||
|
case canState::FrameRequested:
|
||||||
|
{
|
||||||
|
uint32_t timer = millis();
|
||||||
|
int c;
|
||||||
|
|
||||||
|
do {
|
||||||
|
debugSerial.print(".");
|
||||||
|
yield();
|
||||||
|
|
||||||
|
if (c=driver->readFrame()>0 && (driver->RXid.deviceId == devId) && (driver ->RXid.payloadType == pType))
|
||||||
|
{
|
||||||
|
state = canState::FrameReceived;
|
||||||
|
debugSerial<<F("Payload received ")<< c << "|" <<driver->RXlen<< " "<<driver->RXpacket.payload<<endl;;
|
||||||
|
return driver->RXlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while((!isTimeOver(timer,millis(),1000UL)) );
|
||||||
|
|
||||||
|
debugSerial<<F("RX data awaiting timeout")<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case canState::FrameReceived:
|
||||||
|
return driver->RXlen;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case canState::waitingConfirm:
|
||||||
|
if (driver->readFrame()>=0)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(driver->RXid.deviceId == devId) &&
|
||||||
|
(driver->RXid.payloadType == pType) &&
|
||||||
|
(driver->RXid.status == 0)
|
||||||
|
)
|
||||||
|
state = canState::StreamOpenedWrite;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return driver->RXlen;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case canState::Idle:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Stream methods
|
||||||
|
int canStream::available()
|
||||||
|
{
|
||||||
|
if (!driver) return -1;
|
||||||
|
int avail = checkState();
|
||||||
|
return avail;
|
||||||
|
};
|
||||||
|
|
||||||
|
int canStream::read()
|
||||||
|
{
|
||||||
|
if (!driver) return -1;
|
||||||
|
int avail = checkState();
|
||||||
|
int ch;
|
||||||
|
if (avail>=0)
|
||||||
|
{
|
||||||
|
ch = driver->RXpacket.data[readPos++];
|
||||||
|
if (readPos>=8) state = canState::StreamOpenedRead;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
int canStream::peek()
|
||||||
|
{
|
||||||
|
if (!driver) return -1;
|
||||||
|
int avail = checkState();
|
||||||
|
int ch;
|
||||||
|
if (avail>=0)
|
||||||
|
{
|
||||||
|
ch = driver->RXpacket.data[readPos];
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t canStream::write(uint8_t c)
|
||||||
|
{
|
||||||
|
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
|
||||||
|
|
||||||
|
uint32_t timer = millis();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
checkState();
|
||||||
|
yield();
|
||||||
|
//debugSerial.print("*");
|
||||||
|
if (isTimeOver(timer,millis(),1000UL))
|
||||||
|
{
|
||||||
|
state = canState::Error;
|
||||||
|
errorSerial<<F("CAN write timeout")<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (!availableForWrite() );
|
||||||
|
|
||||||
|
writeBuffer.data[writePos++]=c;
|
||||||
|
if (writePos>=8)
|
||||||
|
{
|
||||||
|
bool res = send(8);
|
||||||
|
if (res) state = canState::waitingConfirm;
|
||||||
|
else state = canState::Error;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return 1; };
|
||||||
|
|
||||||
|
void canStream::flush()
|
||||||
|
{
|
||||||
|
send(writePos);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int canStream::availableForWrite()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case canState::waitingConfirm: return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <itemCmd.h>
|
#include <itemCmd.h>
|
||||||
|
|
||||||
|
#include <Stream.h>
|
||||||
|
#include <aJSON.h>
|
||||||
|
#include <streamlog.h>
|
||||||
//#include <config.h> NO!
|
//#include <config.h> NO!
|
||||||
|
|
||||||
typedef uint8_t macAddress[6];
|
typedef uint8_t macAddress[6];
|
||||||
@@ -28,7 +32,7 @@ typedef union
|
|||||||
} canid_t;
|
} canid_t;
|
||||||
|
|
||||||
enum payloadType
|
enum payloadType
|
||||||
{
|
{ unknown=0,
|
||||||
itemCommand=1,
|
itemCommand=1,
|
||||||
lookupMAC=2,
|
lookupMAC=2,
|
||||||
configFrame=3,
|
configFrame=3,
|
||||||
@@ -66,6 +70,7 @@ enum commandType
|
|||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint8_t data[8];
|
uint8_t data[8];
|
||||||
|
char payload[8];
|
||||||
struct {
|
struct {
|
||||||
itemCmdStore cmd;
|
itemCmdStore cmd;
|
||||||
itemArgStore param;
|
itemArgStore param;
|
||||||
@@ -87,13 +92,17 @@ typedef union {
|
|||||||
|
|
||||||
enum canState
|
enum canState
|
||||||
{
|
{
|
||||||
Unknown=0,
|
Unknown,
|
||||||
MACLookup=2,
|
MACLookup,
|
||||||
HaveId=3,
|
Idle,
|
||||||
ConfigFrameRequested=4,
|
StreamOpenedWrite,
|
||||||
ConfigFrameReceived=5,
|
StreamOpenedRead,
|
||||||
ConfigLoaded=6,
|
FrameRequested,
|
||||||
Error=7
|
FrameReceived,
|
||||||
|
ReadConfig,
|
||||||
|
ConfigLoaded,
|
||||||
|
waitingConfirm,
|
||||||
|
Error
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
@@ -101,25 +110,101 @@ class canDriver
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::Unknown;};
|
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::Unknown;};
|
||||||
|
uint8_t getMyId();
|
||||||
|
bool sendStatus(char * itemName, itemCmd cmd);
|
||||||
|
bool sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd);
|
||||||
bool upTime(uint32_t ut);
|
bool upTime(uint32_t ut);
|
||||||
bool salt(uint32_t salt);
|
bool salt(uint32_t salt);
|
||||||
bool lookupMAC();
|
bool lookupMAC();
|
||||||
|
bool requestFrame(uint8_t devId, payloadType _payloadType );
|
||||||
|
int readFrame();
|
||||||
bool sendRemoteID(macAddress mac);
|
bool sendRemoteID(macAddress mac);
|
||||||
bool begin();
|
bool begin();
|
||||||
void Poll();
|
void Poll();
|
||||||
bool processPacket(uint32_t rawid, 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);
|
||||||
private:
|
uint8_t getControllerID(){return controllerId;};
|
||||||
|
uint8_t getIdByMac(macAddress mac);
|
||||||
|
|
||||||
|
datagram_t RXpacket;
|
||||||
|
canid_t RXid;
|
||||||
|
uint8_t RXlen;
|
||||||
|
|
||||||
|
private:
|
||||||
|
aJsonObject * findConfbyID(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;
|
||||||
CAN_message_t CAN_TX_msg;
|
CAN_message_t CAN_TX_msg;
|
||||||
#endif
|
#endif
|
||||||
bool ready;
|
bool ready;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t controllerId;
|
uint8_t controllerId;
|
||||||
canState state;
|
canState state;
|
||||||
uint32_t responseTimer;
|
uint32_t responseTimer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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; }
|
||||||
|
int open(uint8_t controllerID, payloadType _pType, char _mode)
|
||||||
|
{
|
||||||
|
if (mode) close();
|
||||||
|
devId=controllerID;
|
||||||
|
pType = _pType;
|
||||||
|
mode = _mode;
|
||||||
|
if (mode == 'w') state=canState::StreamOpenedWrite;
|
||||||
|
else state=canState::StreamOpenedRead;
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
int close ()
|
||||||
|
{
|
||||||
|
if ((mode == 'w') && writePos) flush();
|
||||||
|
mode = '\0';
|
||||||
|
state=canState::Unknown;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Stream methods
|
||||||
|
virtual int available();
|
||||||
|
virtual int read();
|
||||||
|
virtual int peek();
|
||||||
|
|
||||||
|
virtual void flush();
|
||||||
|
// Print methods
|
||||||
|
virtual size_t write(uint8_t c) ;
|
||||||
|
virtual int availableForWrite();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
int send(uint8_t len);
|
||||||
|
int checkState();
|
||||||
|
canDriver * driver;
|
||||||
|
unsigned int readPos;
|
||||||
|
unsigned int writePos;
|
||||||
|
|
||||||
|
datagram_t writeBuffer;
|
||||||
|
|
||||||
|
uint8_t devId;
|
||||||
|
char mode;
|
||||||
|
payloadType pType;
|
||||||
|
canState state;
|
||||||
|
//bool writeBlocked;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //
|
#endif //
|
||||||
@@ -70,6 +70,7 @@ systemConfig sysConf(&sysConfStream);
|
|||||||
|
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
canDriver LHCAN;
|
canDriver LHCAN;
|
||||||
|
canStream CANConfStream(&LHCAN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern long timer0_overflow_count;
|
extern long timer0_overflow_count;
|
||||||
@@ -493,7 +494,7 @@ void printMACAddress() {
|
|||||||
//macAddress * mac = sysConf.getMAC();
|
//macAddress * mac = sysConf.getMAC();
|
||||||
infoSerial<<F("MAC:");
|
infoSerial<<F("MAC:");
|
||||||
for (byte i = 0; i < 6; i++)
|
for (byte i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (sysConf.mac[i]<16) infoSerial<<"0";
|
if (sysConf.mac[i]<16) infoSerial<<"0";
|
||||||
(i < 5) ?infoSerial<<_HEX(sysConf.mac[i])<<F(":"):infoSerial<<_HEX(sysConf.mac[i])<<endl;
|
(i < 5) ?infoSerial<<_HEX(sysConf.mac[i])<<F(":"):infoSerial<<_HEX(sysConf.mac[i])<<endl;
|
||||||
}
|
}
|
||||||
@@ -1572,6 +1573,44 @@ int loadConfigFromEEPROM()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int loadConfigFromCAN()
|
||||||
|
{
|
||||||
|
if (configLocked) return 0;
|
||||||
|
configLocked++;
|
||||||
|
|
||||||
|
infoSerial<<F("Loading Config from CAN")<<endl;
|
||||||
|
|
||||||
|
CANConfStream.open(LHCAN.getControllerID(),payloadType::configFrame,'r');
|
||||||
|
|
||||||
|
|
||||||
|
if (CANConfStream.peek() == '{') {
|
||||||
|
debugSerial<<F("JSON detected")<<endl;
|
||||||
|
aJsonStream as = aJsonStream(&CANConfStream);
|
||||||
|
cleanConf(false);
|
||||||
|
root = aJson.parse(&as);
|
||||||
|
CANConfStream.close();
|
||||||
|
if (!root) {
|
||||||
|
errorSerial<<F("load failed")<<endl;
|
||||||
|
sysConf.setETAG("");
|
||||||
|
// sysConfStream.close();
|
||||||
|
configLocked--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
infoSerial<<F("Loaded from CAN")<<endl;
|
||||||
|
configLocked--;
|
||||||
|
applyConfig();
|
||||||
|
sysConf.loadETAG();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
CANConfStream.close();
|
||||||
|
infoSerial<<F("No stored config")<<endl;
|
||||||
|
configLocked--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int cmdFunctionSave(int arg_cnt, char **args)
|
int cmdFunctionSave(int arg_cnt, char **args)
|
||||||
{
|
{
|
||||||
if (arg_cnt>1)
|
if (arg_cnt>1)
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ bool disabledDisconnected(const aJsonObject *thermoExtensionArray, int thermoLat
|
|||||||
|
|
||||||
void resetHard();
|
void resetHard();
|
||||||
|
|
||||||
|
bool cleanConf(bool wait);
|
||||||
|
|
||||||
void printCurentLanConfig();
|
void printCurentLanConfig();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user