diff --git a/build-flags/build_flags_esp32-wifi b/build-flags/build_flags_esp32-wifi index d0469e8..29b4291 100644 --- a/build-flags/build_flags_esp32-wifi +++ b/build-flags/build_flags_esp32-wifi @@ -1,3 +1,4 @@ +# -DWIFI_ENABLE -DDMX_DISABLE # - exeption in DMX.update/begin @@ -12,7 +13,7 @@ -DARDUINO_OTA_MDNS_DISABLE -DMDNS_ENABLE #- ArduinoMDNS didnt working - +-D CANDRV -DMCP23017 -DMODBUS_TX_PIN=13 #-DARTNET_ENABLE - udp rx errors (( diff --git a/lighthub/candriver.cpp b/lighthub/candriver.cpp index 25e1d6d..a66b91e 100644 --- a/lighthub/candriver.cpp +++ b/lighthub/candriver.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #if defined(ARDUINO_ARCH_STM32) #include @@ -20,6 +21,9 @@ STM32_CAN STMCan( CAN1, ALT, RX_SIZE_64, TX_SIZE_16 ); #include //#include extern systemConfig sysConf; +extern canStream CANConfStream; +extern aJsonObject * root; +extern volatile int8_t configLocked; void printFrame(datagram_t * frame, uint8_t len ) { @@ -91,22 +95,47 @@ bool canDriver::lookupMAC() 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<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 - #if defined(ARDUINO_ARCH_ESP32) + #if defined(ARDUINO_ARCH_ESP32) // try to parse packet int packetSize = CAN.parsePacket(); @@ -182,21 +214,22 @@ void canDriver::Poll() //debugSerialPort.println(packetSize); debugSerialPort.println(CAN.packetDlc()); - datagram_t packet; + // only print packet data for non-RTR packets - int i=0; + RXlen=0; while (CAN.available()) { - packet.data[i++]=CAN.read(); - //debugSerialPort.print((char)CAN.read()); - if (i>=8) break; + RXpacket.data[RXlen++]=CAN.read(); + if (RXlen>=8) break; } - debugSerialPort.println(); + RXid.id = CAN.packetId(); - processPacket( CAN.packetId(), &packet,i); + debugSerialPort.println(); + return RXlen; } } #endif + //DUE #if defined(__SAM3X8E__) CAN_FRAME incoming; @@ -207,12 +240,20 @@ void canDriver::Poll() #endif + return -1; +} +void canDriver::Poll() + { + +if (readFrame()>=0) processPacket( RXid, &RXpacket, RXlen); //State machine switch (state) { case canState::MACLookup: + // case canState::FrameRequested: + if (isTimeOver(responseTimer,millis(),1000UL)) { responseTimer=millisNZ(); @@ -226,55 +267,189 @@ switch (state) lookupMAC(); break; -// case canState::HaveId: + case canState::ReadConfig: + { + //Blocking read config + if (configLocked) return; // only in safe moments + configLocked++; + + infoSerial<=6)) + if ((id.payloadType == payloadType::lookupMAC)) { debugSerial<<"Got Controller CAN addr: "<=6)) { return sendRemoteID(packet->mac); //debugSerial<<"ID requested"<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<type == aJson_Int)) + { + debugSerial<valueint << endl; + return addrObj->valueint; + } + +return 0; +} bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size) { //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.flags.extended = 1; // To enable extended ID CAN_TX_msg.len=size; - if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN Wrote ")<data,size); //for(uint8_t i=0;iwrite (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<RXlen<< " "<RXpacket.payload<RXlen; + } + + } while((!isTimeOver(timer,millis(),1000UL)) ); + + debugSerial<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<=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 diff --git a/lighthub/candriver.h b/lighthub/candriver.h index bc67f27..d49c675 100644 --- a/lighthub/candriver.h +++ b/lighthub/candriver.h @@ -9,6 +9,10 @@ #endif #include + +#include +#include +#include //#include NO! typedef uint8_t macAddress[6]; @@ -28,7 +32,7 @@ typedef union } canid_t; enum payloadType -{ +{ unknown=0, itemCommand=1, lookupMAC=2, configFrame=3, @@ -66,6 +70,7 @@ enum commandType typedef union { uint8_t data[8]; + char payload[8]; struct { itemCmdStore cmd; itemArgStore param; @@ -87,13 +92,17 @@ typedef union { enum canState { -Unknown=0, -MACLookup=2, -HaveId=3, -ConfigFrameRequested=4, -ConfigFrameReceived=5, -ConfigLoaded=6, -Error=7 +Unknown, +MACLookup, +Idle, +StreamOpenedWrite, +StreamOpenedRead, +FrameRequested, +FrameReceived, +ReadConfig, +ConfigLoaded, +waitingConfirm, +Error }; #pragma pack(pop) @@ -101,25 +110,101 @@ class canDriver { public: 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 salt(uint32_t salt); bool lookupMAC(); +bool requestFrame(uint8_t devId, payloadType _payloadType ); +int readFrame(); bool sendRemoteID(macAddress mac); bool begin(); void Poll(); -bool processPacket(uint32_t rawid, datagram_t *packet, uint8_t len, bool rtr=false); -bool write(uint32_t msg_id, datagram_t * buf = NULL, uint8_t size=0); -private: +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); +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) CAN_message_t CAN_RX_msg; CAN_message_t CAN_TX_msg; #endif bool ready; + + + uint8_t controllerId; canState state; 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 // \ No newline at end of file diff --git a/lighthub/main.cpp b/lighthub/main.cpp index fca9086..c80dade 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -70,6 +70,7 @@ systemConfig sysConf(&sysConfStream); #ifdef CANDRV canDriver LHCAN; +canStream CANConfStream(&LHCAN); #endif extern long timer0_overflow_count; @@ -493,7 +494,7 @@ void printMACAddress() { //macAddress * mac = sysConf.getMAC(); infoSerial<1) diff --git a/lighthub/main.h b/lighthub/main.h index f03378d..ac7c2ff 100644 --- a/lighthub/main.h +++ b/lighthub/main.h @@ -332,6 +332,7 @@ bool disabledDisconnected(const aJsonObject *thermoExtensionArray, int thermoLat void resetHard(); +bool cleanConf(bool wait); void printCurentLanConfig();