mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 03:39:49 +03:00
Ultrasonic sensor added
CAN driver logic/relability improved string -> itemCmd functionality added, cold boot w/o config procedure improved
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
-D CANDRV
|
||||
-D THERMOSTAT_CHECK_PERIOD=5000
|
||||
-D ULTRASONIC
|
||||
|
||||
|
||||
-DENABLE_HWSERIAL1
|
||||
|
||||
Binary file not shown.
@@ -52,7 +52,7 @@ bool canDriver::upTime(uint32_t ut)
|
||||
|
||||
packet.metric1=ut;
|
||||
|
||||
debugSerial<<("UpTime")<<endl;
|
||||
debugSerial<<("CAN: UpTime")<<endl;
|
||||
return write (id.id, &packet, 4);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ bool canDriver::salt(uint32_t salt)
|
||||
|
||||
packet.metric1=salt;
|
||||
|
||||
debugSerial<<("Salt")<<endl;
|
||||
debugSerial<<("CAN: Salt")<<endl;
|
||||
return write (id.id, &packet, 4);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ bool canDriver::lookupMAC()
|
||||
|
||||
memcpy(packet.mac,sysConf.mac,6);
|
||||
|
||||
debugSerial<<("Lookup MAC")<<endl;
|
||||
debugSerial<<("CAN: Lookup MAC")<<endl;
|
||||
res=write (id.id, &packet, 6);
|
||||
if (res) state=canState::MACLookup;
|
||||
else state=canState::Error;
|
||||
@@ -96,7 +96,7 @@ bool canDriver::lookupMAC()
|
||||
return res;
|
||||
}
|
||||
|
||||
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType )
|
||||
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
|
||||
{
|
||||
canid_t id;
|
||||
datagram_t packet;
|
||||
@@ -107,11 +107,11 @@ bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType )
|
||||
id.status=0;
|
||||
id.payloadType=_payloadType;
|
||||
id.deviceId=devId;
|
||||
id.itemId=0; //CRC?
|
||||
id.itemId=seqNo;
|
||||
packet.metric1 =0;
|
||||
//memcpy(packet.mac,sysConf.mac,6);
|
||||
|
||||
debugSerial<<("Request frame ")<<_payloadType<<F(" for id ")<<devId<<endl;
|
||||
//delay (100);
|
||||
debugSerial<<("CAN: Request frame ")<<_payloadType<<F(" for id ")<<devId<<F(" seq:")<<seqNo<<endl;
|
||||
res=write (id.id,&packet,1);
|
||||
if (res) state=canState::FrameRequested;
|
||||
else state=canState::Error;
|
||||
@@ -134,7 +134,7 @@ bool canDriver::sendRemoteID(macAddress mac)
|
||||
id.itemId=200; //CRC16 of remote config
|
||||
//packet.data[0]=1;
|
||||
|
||||
debugSerial<<("Send remote ID")<<endl;
|
||||
debugSerial<<("CAN: Send remote ID")<<endl;
|
||||
res = write (id.id);//,&packet,8);
|
||||
if (res) state=canState::Idle;
|
||||
else state=canState::Error;
|
||||
@@ -173,7 +173,7 @@ bool canDriver::begin()
|
||||
}
|
||||
#endif
|
||||
|
||||
debugSerial<<"CAN initialized"<<endl;
|
||||
debugSerial<<"CAN: initialized"<<endl;
|
||||
controllerId = getMyId();
|
||||
ready=true;
|
||||
return true;
|
||||
@@ -200,7 +200,7 @@ int canDriver::readFrame()
|
||||
|
||||
if (packetSize ){//|| CAN.packetId() != -1) {
|
||||
// received a packet
|
||||
debugSerialPort.print("Received ");
|
||||
debugSerialPort.print("CAN: Received ");
|
||||
|
||||
if (CAN.packetExtended()) {
|
||||
debugSerialPort.print("extended ");
|
||||
@@ -271,7 +271,7 @@ switch (state)
|
||||
{
|
||||
responseTimer=millisNZ();
|
||||
state=canState::Error;
|
||||
errorSerial<<"CAN Timeout"<<endl;
|
||||
errorSerial<<"CAN: lookup Timeout"<<endl;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -288,25 +288,25 @@ switch (state)
|
||||
if (configLocked) return; // only in safe moments
|
||||
configLocked++;
|
||||
|
||||
infoSerial<<F("Requesting Config from CAN")<<endl;
|
||||
infoSerial<<F("CAN: Requesting Config")<<endl;
|
||||
|
||||
CANConfStream.open(controllerId,payloadType::configFrame,'r');
|
||||
|
||||
if (CANConfStream.peek() == '{') {
|
||||
debugSerial<<F("JSON detected")<<endl;
|
||||
debugSerial<<F("CAN: JSON detected")<<endl;
|
||||
aJsonStream as = aJsonStream(&CANConfStream);
|
||||
cleanConf(false);
|
||||
root = aJson.parse(&as);
|
||||
CANConfStream.close();
|
||||
if (!root) {
|
||||
errorSerial<<F("load failed")<<endl;
|
||||
errorSerial<<F("CAN: config load failed")<<endl;
|
||||
sysConf.setETAG("");
|
||||
// sysConfStream.close();
|
||||
configLocked--;
|
||||
state = canState::Error;
|
||||
return;
|
||||
}
|
||||
infoSerial<<F("Loaded from CAN")<<endl;
|
||||
infoSerial<<F("CAN: config Loaded")<<endl;
|
||||
configLocked--;
|
||||
applyConfig();
|
||||
sysConf.loadETAG();
|
||||
@@ -314,7 +314,7 @@ switch (state)
|
||||
return ;
|
||||
}
|
||||
CANConfStream.close();
|
||||
infoSerial<<F("Config not loaded")<<endl;
|
||||
infoSerial<<F("CAN: Config not loaded")<<endl;
|
||||
state = canState::Error;
|
||||
configLocked--;
|
||||
}
|
||||
@@ -328,7 +328,7 @@ switch (state)
|
||||
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
||||
{
|
||||
|
||||
debugSerial.print("CAN Received ");
|
||||
debugSerial.print("CAN: Received ");
|
||||
debugSerial.print(len);
|
||||
debugSerial.print(" bytes id 0x");
|
||||
debugSerial.print(id.id,HEX);
|
||||
@@ -379,7 +379,7 @@ if (id.status){
|
||||
case canState::MACLookup:
|
||||
if ((id.payloadType == payloadType::lookupMAC))
|
||||
{
|
||||
debugSerial<<"Got Controller CAN addr: "<<id.deviceId<<endl;
|
||||
debugSerial<<"\nCAN: Got Controller addr: "<<id.deviceId<<endl;
|
||||
controllerId=id.deviceId;
|
||||
state = canState::ReadConfig;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ if (id.status){
|
||||
case canState::FrameRequested:
|
||||
if ((id.payloadType == payloadType::configFrame) && (id.deviceId == controllerId))
|
||||
{
|
||||
errorSerial<<F("Config received when not expected")<<endl;
|
||||
errorSerial<<F("CAN: Config received when not expected")<<endl;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -432,13 +432,13 @@ else //Requests
|
||||
return sendRemoteID(packet->mac);
|
||||
//debugSerial<<"ID requested"<<endl;
|
||||
}
|
||||
else if (id.payloadType == payloadType::configFrame)
|
||||
else if ((id.payloadType == payloadType::configFrame) && (id.itemId == 0xFFFF))
|
||||
{
|
||||
debugSerial<<F("Requested conf for dev#")<<id.deviceId<<endl;
|
||||
debugSerial<<F("CAN: Requested conf for dev#")<<id.deviceId<<endl;
|
||||
aJsonObject * remoteConfObj = findConfbyID(id.deviceId);
|
||||
if (remoteConfObj)
|
||||
{
|
||||
infoSerial<<F("Sending conf for dev#")<<id.deviceId<<endl;
|
||||
infoSerial<<F("CAN: Sending conf for dev#")<<id.deviceId<<endl;
|
||||
CANConfStream.open(id.deviceId,payloadType::configFrame,'w');
|
||||
aJsonStream outStream = aJsonStream(&CANConfStream);
|
||||
aJson.print(remoteConfObj, &outStream);
|
||||
@@ -510,7 +510,7 @@ uint8_t canDriver::getIdByMac(macAddress mac)
|
||||
|
||||
if (i < 5) macStr[strptr++]=':';
|
||||
}
|
||||
debugSerial<<F("Searching devId for ")<<macStr<<endl;
|
||||
debugSerial<<F("CAN: Searching devId for ")<<macStr<<endl;
|
||||
aJsonObject * remoteConfObj = aJson.getObjectItem(confObj, macStr);
|
||||
|
||||
if (!remoteConfObj) return 0;
|
||||
@@ -522,7 +522,7 @@ aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
|
||||
if (!addrObj) return 0;
|
||||
if (addrObj && (addrObj->type == aJson_Int))
|
||||
{
|
||||
debugSerial<<F("find dev#")<< addrObj->valueint << endl;
|
||||
debugSerial<<F("CAN: find dev#")<< addrObj->valueint << endl;
|
||||
return addrObj->valueint;
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ return 0;
|
||||
|
||||
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;
|
||||
bool res;
|
||||
if (size>8) size = 8;
|
||||
|
||||
@@ -542,8 +542,8 @@ 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 ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
||||
else debugSerial.println("CAN Write error");
|
||||
if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
||||
else debugSerial.println("CAN: Write error");
|
||||
return res;
|
||||
#endif
|
||||
|
||||
@@ -552,8 +552,8 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
||||
CAN.beginExtendedPacket(msg_id,size);
|
||||
CAN.write(buf->data,size);
|
||||
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
|
||||
if (res=CAN.endPacket()) debugSerial<< ("CAN Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;
|
||||
else debugSerial.println("CAN Write error");
|
||||
if (res=CAN.endPacket()) debugSerial<< ("CAN: Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;
|
||||
else debugSerial.println("CAN: Write error");
|
||||
return res;
|
||||
#endif
|
||||
|
||||
@@ -565,8 +565,8 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t 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");
|
||||
if (res) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
|
||||
else debugSerial.println("CAN: Write error");
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
@@ -592,6 +592,16 @@ bool canDriver::sendCommand(aJsonObject * can,itemCmd cmd, bool status)
|
||||
{
|
||||
aJsonObject * dev = aJson.getArrayItem(can,0);
|
||||
aJsonObject * it = aJson.getArrayItem(can,1);
|
||||
aJsonObject * sfx = aJson.getArrayItem(can,2);
|
||||
if (sfx)
|
||||
switch (sfx->type)
|
||||
{
|
||||
case aJson_Int: cmd.setSuffix(sfx->valueint);
|
||||
break;
|
||||
case aJson_String:
|
||||
int suffix=txt2subItem(sfx->valuestring);
|
||||
if (suffix) cmd.setSuffix(suffix);
|
||||
}
|
||||
debugSerial<<dev->valueint << ":" << it->valueint<<endl;
|
||||
if (dev && it && dev->type == aJson_Int && it->type == aJson_Int)
|
||||
return sendCommand(dev->valueint, it->valueint, cmd, status);
|
||||
@@ -621,8 +631,8 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
|
||||
res=write (id.id,&packet,8);
|
||||
|
||||
if (res) debugSerial<<F(" ok")<<endl;
|
||||
else debugSerial<<F(" fail")<<endl;
|
||||
if (res) debugSerial<<F("CAN: sent ok")<<endl;
|
||||
else debugSerial<<F("CAN: fail")<<endl;
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -632,7 +642,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
////////////////////////////// Steream //////////////////////////
|
||||
|
||||
|
||||
int canStream::send(uint8_t len)
|
||||
int canStream::send(uint8_t len, uint16_t _seqNo)
|
||||
{
|
||||
canid_t id;
|
||||
datagram_t packet;
|
||||
@@ -642,7 +652,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
id.status=1;
|
||||
id.payloadType=pType;
|
||||
id.deviceId=devId;
|
||||
id.itemId=0; // chunk?
|
||||
id.itemId=_seqNo;
|
||||
|
||||
res=driver->write (id.id, &writeBuffer, len);
|
||||
writePos=0;
|
||||
@@ -662,37 +672,48 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
{
|
||||
case canState::StreamOpenedRead:
|
||||
readPos = 0;
|
||||
res= driver->requestFrame(devId,pType); //Requesting frame;
|
||||
res= driver->requestFrame(devId,pType,seqNo); //Requesting frame;
|
||||
if (res)
|
||||
state = canState::FrameRequested;
|
||||
else
|
||||
{
|
||||
state = canState::Error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (seqNo ==0xFFFF) seqNo =0;
|
||||
//continue
|
||||
|
||||
case canState::FrameRequested:
|
||||
{
|
||||
uint32_t timer = millis();
|
||||
{
|
||||
int c;
|
||||
|
||||
|
||||
uint32_t timer = millis();
|
||||
do {
|
||||
debugSerial.print(".");
|
||||
//debugSerial.print(".");
|
||||
yield();
|
||||
|
||||
if (c=driver->readFrame()>0 && (driver->RXid.deviceId == devId) && (driver ->RXid.payloadType == pType))
|
||||
if ((c=driver->readFrame()>0) && (driver->RXid.deviceId == devId) && (driver ->RXid.payloadType == pType) && driver->RXid.status)
|
||||
{
|
||||
state = canState::FrameReceived;
|
||||
debugSerial<<F("Payload received ")<< c << "|" <<driver->RXlen<< " "<<driver->RXpacket.payload<<endl;;
|
||||
debugSerial<<F("CAN: Payload received ")<< c << "|" <<driver->RXlen<< " "<<driver->RXpacket.payload<<"#"<<driver->RXid.itemId<<endl;
|
||||
seqNo=driver->RXid.itemId;
|
||||
failedCount=0;
|
||||
return driver->RXlen;
|
||||
}
|
||||
|
||||
} while((!isTimeOver(timer,millis(),1000UL)) );
|
||||
|
||||
debugSerial<<F("CAN: RX data awaiting timeout #")<<failedCount<<endl;
|
||||
if (failedCount>=3)
|
||||
{
|
||||
state = canState::Error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
debugSerial<<F("RX data awaiting timeout")<<endl;
|
||||
return -1;
|
||||
failedCount++;
|
||||
state = canState::StreamOpenedRead;
|
||||
}
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case canState::FrameReceived:
|
||||
@@ -707,7 +728,22 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
(driver->RXid.payloadType == pType) &&
|
||||
(driver->RXid.status == 0)
|
||||
)
|
||||
state = canState::StreamOpenedWrite;
|
||||
{
|
||||
debugSerial<<F("CAN: frame confirmed #")<<driver->RXid.itemId<<endl;
|
||||
if (seqNo == driver->RXid.itemId)
|
||||
{
|
||||
state = canState::StreamOpenedWrite;
|
||||
seqNo++;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = canState::Error;
|
||||
errorSerial<<F("CAN: wrong seqNum")<<endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return driver->RXlen;
|
||||
@@ -772,7 +808,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
if (isTimeOver(timer,millis(),1000UL))
|
||||
{
|
||||
state = canState::Error;
|
||||
errorSerial<<F("CAN write timeout")<<endl;
|
||||
errorSerial<<F("CAN: write timeout")<<endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -782,7 +818,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
writeBuffer.data[writePos++]=c;
|
||||
if (writePos>=8)
|
||||
{
|
||||
bool res = send(8);
|
||||
bool res = send(8,seqNo);
|
||||
if (res) state = canState::waitingConfirm;
|
||||
else state = canState::Error;
|
||||
return res;
|
||||
@@ -791,7 +827,7 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool st
|
||||
|
||||
void canStream::flush()
|
||||
{
|
||||
send(writePos);
|
||||
send(writePos,seqNo);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ bool sendCommand(aJsonObject * can,itemCmd cmd, bool status = false);
|
||||
bool upTime(uint32_t ut);
|
||||
bool salt(uint32_t salt);
|
||||
bool lookupMAC();
|
||||
bool requestFrame(uint8_t devId, payloadType _payloadType );
|
||||
bool requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo );
|
||||
int readFrame();
|
||||
bool sendRemoteID(macAddress mac);
|
||||
bool begin();
|
||||
@@ -161,13 +161,15 @@ extern aJsonObject * topics;
|
||||
class canStream : public Stream
|
||||
{
|
||||
public:
|
||||
canStream(canDriver * _driver) : readPos(0),writePos(0),devId(0), pType(payloadType::unknown),state(canState::stateUnknown){driver=_driver; }
|
||||
canStream(canDriver * _driver) : readPos(0),writePos(0),devId(0), pType(payloadType::unknown),state(canState::stateUnknown),seqNo(0),failedCount(0){driver=_driver; }
|
||||
int open(uint8_t controllerID, payloadType _pType, char _mode)
|
||||
{
|
||||
if (mode) close();
|
||||
devId=controllerID;
|
||||
pType = _pType;
|
||||
mode = _mode;
|
||||
seqNo=0xFFFF;
|
||||
failedCount=0;
|
||||
if (mode == 'w') state=canState::StreamOpenedWrite;
|
||||
else state=canState::StreamOpenedRead;
|
||||
return 1;
|
||||
@@ -194,7 +196,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
int send(uint8_t len);
|
||||
int send(uint8_t len, uint16_t _seqNo);
|
||||
int checkState();
|
||||
canDriver * driver;
|
||||
unsigned int readPos;
|
||||
@@ -203,6 +205,8 @@ private:
|
||||
datagram_t writeBuffer;
|
||||
|
||||
uint8_t devId;
|
||||
uint16_t seqNo;
|
||||
int8_t failedCount;
|
||||
char mode;
|
||||
payloadType pType;
|
||||
canState state;
|
||||
|
||||
@@ -237,7 +237,7 @@ NRFFlashStorage EEPROM;
|
||||
{
|
||||
samBufferPos = 0;
|
||||
EEPROM.write(startPos+pos-sizeof(samBuffer),(byte*)samBuffer,sizeof(samBuffer));
|
||||
|
||||
|
||||
}
|
||||
|
||||
samBuffer[samBufferPos++]=ch;
|
||||
|
||||
@@ -44,6 +44,14 @@ extern canDriver LHCAN;
|
||||
#include "Adafruit_MCP23X17.h"
|
||||
Adafruit_MCP23X17 mcp;
|
||||
#endif
|
||||
|
||||
#ifdef ULTRASONIC
|
||||
#define US_TRIG PA_14 //pin49
|
||||
#define US_ECHO PA_15 //pin50
|
||||
#include "Ultrasonic.h"
|
||||
Ultrasonic ultrasonic(US_TRIG, US_ECHO);
|
||||
#endif
|
||||
|
||||
#if not defined (NOIP)
|
||||
extern PubSubClient mqttClient;
|
||||
#endif
|
||||
@@ -107,6 +115,7 @@ void Input::Parse(aJsonObject * configObj)
|
||||
store = NULL;
|
||||
inType = 0;
|
||||
pin = 0;
|
||||
pin2 =0;
|
||||
|
||||
if (!inputObj || !root) return;
|
||||
if (!configObj) configObj = inputObj;
|
||||
@@ -118,10 +127,25 @@ void Input::Parse(aJsonObject * configObj)
|
||||
if (itemBuffer) inType = static_cast<uint8_t>(itemBuffer->valueint);
|
||||
|
||||
itemBuffer = aJson.getObjectItem(configObj, "#");
|
||||
if (itemBuffer) pin = static_cast<uint8_t>(itemBuffer->valueint);
|
||||
else pin = static_cast<uint8_t>(atoi(configObj->name));
|
||||
}
|
||||
if (itemBuffer)
|
||||
switch (itemBuffer->type)
|
||||
{
|
||||
case aJson_Int:
|
||||
pin = static_cast<uint8_t>(itemBuffer->valueint);
|
||||
|
||||
break;
|
||||
case aJson_Array:
|
||||
if ((itemBuffer->child) && (itemBuffer->child->type == aJson_Int))
|
||||
{
|
||||
pin = static_cast<uint8_t>(itemBuffer->child->valueint);
|
||||
if ((itemBuffer->child->child) && (itemBuffer->child->child->type == aJson_Int))
|
||||
pin = static_cast<uint8_t>(itemBuffer->child->child->valueint);
|
||||
}
|
||||
|
||||
} //switch
|
||||
else pin = static_cast<uint8_t>(atoi(configObj->name));
|
||||
|
||||
}
|
||||
// Persistant storage
|
||||
itemBuffer = aJson.getObjectItem(inputObj, "@S");
|
||||
if (!itemBuffer) {
|
||||
@@ -135,8 +159,10 @@ void Input::Parse(aJsonObject * configObj)
|
||||
|
||||
void cleanStore(aJsonObject * input)
|
||||
{
|
||||
if (input->type == aJson_Object) {
|
||||
if (input && (input->type == aJson_Object)) {
|
||||
// Check for nested inputs
|
||||
Input in(input);
|
||||
in.store->aslong = 0;
|
||||
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
||||
if (inputArray && (inputArray->type == aJson_Array))
|
||||
{
|
||||
@@ -153,9 +179,8 @@ if (input->type == aJson_Object) {
|
||||
}
|
||||
else
|
||||
{
|
||||
Input in(input);
|
||||
in.store->aslong = 0;
|
||||
//in.Poll(CHECK_INPUT);
|
||||
// Input in(input);
|
||||
// in.store->aslong = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,6 +292,14 @@ switch (cause) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CHECK_ULTRASONIC:
|
||||
switch (inType)
|
||||
{
|
||||
case IN_ULTRASONIC:
|
||||
analogPoll(cause);
|
||||
contactPoll(cause);
|
||||
}
|
||||
break;
|
||||
case CHECK_SENSOR: //Slow polling
|
||||
switch (inType)
|
||||
{
|
||||
@@ -528,7 +561,8 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
|
||||
#endif
|
||||
|
||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
||||
bool Input::changeState(uint8_t newState, short cause)
|
||||
bool Input::
|
||||
changeState(uint8_t newState, short cause)
|
||||
{
|
||||
if (!inputObj || !store) return false;
|
||||
|
||||
@@ -666,8 +700,11 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
||||
static volatile uint8_t contactPollBusy = 0;
|
||||
|
||||
void Input::contactPoll(short cause) {
|
||||
boolean currentInputState;
|
||||
bool currentInputState;
|
||||
|
||||
if (!store /*|| contactPollBusy*/) return;
|
||||
if ((inType == IN_ULTRASONIC) && (cause!=CHECK_ULTRASONIC)) return;
|
||||
|
||||
contactPollBusy++;
|
||||
|
||||
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
|
||||
@@ -684,9 +721,9 @@ if (inType & IN_I2C)
|
||||
currentInputState = (inCache.I2CReadBit(IN_I2C,0,pin) == inputOnLevel);
|
||||
else
|
||||
#endif
|
||||
if (isAnalogPin(pin) && (mapObj=aJson.getObjectItem(inputObj, "map")) && mapObj->type == aJson_Array)
|
||||
if ((isAnalogPin(pin) || (inType == IN_ULTRASONIC)) && (mapObj=aJson.getObjectItem(inputObj, "map")) && mapObj->type == aJson_Array)
|
||||
{
|
||||
int value = inCache.analogReadCached(pin);
|
||||
int value = inCache.analogReadCached(pin,pin2,inType);
|
||||
if (value >= aJson.getArrayItem(mapObj, 0)->valueint && value <= aJson.getArrayItem(mapObj, 1)->valueint)
|
||||
currentInputState = true;
|
||||
else currentInputState = false;
|
||||
@@ -801,7 +838,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
|
||||
// onContactChanged(currentInputState); //Legacy input - to remove later
|
||||
|
||||
bool res = true;
|
||||
if (currentInputState) //Button pressed state transitions
|
||||
if (currentInputState) //Button pressed state transitions
|
||||
|
||||
switch (store->state)
|
||||
{
|
||||
@@ -896,7 +933,7 @@ void Input::analogPoll(short cause) {
|
||||
|
||||
pinMode(pin, inputPinMode);
|
||||
*/
|
||||
inputVal = inCache.analogReadCached(pin);
|
||||
inputVal = inCache.analogReadCached(pin,pin2,inType);
|
||||
// Mapping
|
||||
if (inputMap && inputMap->type == aJson_Array)
|
||||
{
|
||||
@@ -1110,8 +1147,18 @@ readCache::readCache()
|
||||
cached_data = 0;
|
||||
}
|
||||
|
||||
uint16_t readCache::analogReadCached (uint8_t _pin)
|
||||
uint16_t readCache::analogReadCached (uint8_t _pin, uint8_t trigPin, uint8_t _type )
|
||||
{
|
||||
#ifdef ULTRASONIC
|
||||
if (_type == IN_ULTRASONIC)
|
||||
{
|
||||
if ((_pin==addr) && (IN_ULTRASONIC == type)) return cached_data;
|
||||
type = IN_ULTRASONIC;
|
||||
cached_data=ultrasonic.read();
|
||||
//debugSerial<<F("LEN: ")<<cached_data<<endl;
|
||||
return cached_data;
|
||||
}
|
||||
#endif
|
||||
if ((_pin==addr) && (IN_ANALOG==type)) return cached_data;
|
||||
addr = _pin;
|
||||
type = IN_ANALOG;
|
||||
|
||||
@@ -33,6 +33,7 @@ e-mail anklimov@gmail.com
|
||||
#define IN_DHT22 4
|
||||
#define IN_CCS811 5
|
||||
#define IN_HDC1080 6
|
||||
#define IN_ULTRASONIC 7
|
||||
|
||||
#define IN_COUNTER 8
|
||||
#define IN_UPTIME 16
|
||||
@@ -62,6 +63,7 @@ e-mail anklimov@gmail.com
|
||||
#define CHECK_SENSOR 1
|
||||
#define CHECK_INPUT 2
|
||||
#define CHECK_INTERRUPT 3
|
||||
#define CHECK_ULTRASONIC 4
|
||||
|
||||
|
||||
#define T_LONG 1000
|
||||
@@ -134,6 +136,7 @@ public:
|
||||
aJsonObject *inputObj;
|
||||
uint8_t inType;
|
||||
uint8_t pin;
|
||||
uint8_t pin2;
|
||||
inStore *store;
|
||||
|
||||
Input(aJsonObject *obj, aJsonObject * configObj = NULL);
|
||||
@@ -188,11 +191,12 @@ protected:
|
||||
class readCache {
|
||||
public:
|
||||
readCache();
|
||||
uint16_t analogReadCached (uint8_t pin);
|
||||
uint16_t analogReadCached (uint8_t pin, uint8_t trigPin=0, uint8_t _type = IN_ANALOG);
|
||||
uint8_t digitalReadCached(uint8_t pin);
|
||||
#ifdef MCP23017
|
||||
uint8_t I2CReadBit(uint8_t type, uint8_t addr, uint8_t pin);
|
||||
#endif
|
||||
|
||||
void invalidateInputCache();
|
||||
protected:
|
||||
uint8_t addr;
|
||||
|
||||
@@ -703,7 +703,7 @@ st.setSuffix(suffixCode);
|
||||
|
||||
int Par[3];
|
||||
while (payload && k < 3)
|
||||
Par[k++] = getInt((char **) &payload);
|
||||
Par[k++] = getIntFromStr((char **) &payload);
|
||||
i=i+k; //i=total # of parameters
|
||||
switch(suffixCode)
|
||||
{case S_HUE:
|
||||
@@ -748,7 +748,7 @@ st.setSuffix(suffixCode);
|
||||
short i = 0;
|
||||
int Par[4];
|
||||
while (payload && i < 4)
|
||||
Par[i++] = getInt((char **) &payload);
|
||||
Par[i++] = getIntFromStr((char **) &payload);
|
||||
|
||||
switch (i) //Number of params
|
||||
{
|
||||
@@ -770,7 +770,7 @@ st.setSuffix(suffixCode);
|
||||
}
|
||||
default: //some known command
|
||||
{
|
||||
int32_t intParam = getInt((char **) &payload);
|
||||
int32_t intParam = getIntFromStr((char **) &payload);
|
||||
if (intParam) st.Int(intParam);
|
||||
return Ctrl(st,NULL, true, authorized);
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ extern aJsonObject *items;
|
||||
extern short thermoSetCurTemp(char *name, float t);
|
||||
|
||||
int txt2cmd (char * payload);
|
||||
int txt2subItem(char *payload);
|
||||
|
||||
class Item
|
||||
{
|
||||
|
||||
@@ -101,15 +101,78 @@ todo - extend to values
|
||||
*/
|
||||
itemCmd::itemCmd(char * _cmd)
|
||||
{
|
||||
//debugSerial<<"ITEMCMD:" <<_cmd<<endl;
|
||||
cmd.aslong=0;
|
||||
param.aslong=0;
|
||||
cmd.itemArgType=ST_VOID;
|
||||
int i=0;
|
||||
while (_cmd[i]) {_cmd[i]=toupper(_cmd[i]);i++;};
|
||||
|
||||
int cmdN = txt2cmd(_cmd);
|
||||
if (cmdN == CMD_UNKNOWN) return;
|
||||
cmd.cmdCode=cmdN;
|
||||
short i=0;
|
||||
int Par[4];
|
||||
|
||||
while (_cmd[i]) {_cmd[i]=toupper(_cmd[i]);i++;};
|
||||
|
||||
int cmdN = txt2cmd(_cmd);
|
||||
if (cmdN>=0) cmd.cmdCode = cmdN;
|
||||
|
||||
bool hsvflag=false;
|
||||
|
||||
switch (cmd.cmdCode) {
|
||||
case CMD_HSV:
|
||||
hsvflag=true;
|
||||
case CMD_RGB:
|
||||
|
||||
cmd.cmdCode=CMD_VOID;
|
||||
//Parsing integers from payload
|
||||
i = 0;
|
||||
|
||||
while (_cmd && i < 4)
|
||||
Par[i++] = getIntFromStr((char **) &_cmd);
|
||||
|
||||
if (hsvflag)
|
||||
{
|
||||
setSuffix(S_HSV);
|
||||
cmd.itemArgType=ST_HSV255;
|
||||
switch (i) //Number of params
|
||||
{
|
||||
case 4:
|
||||
setColorTemp(Par[3]);
|
||||
case 3:
|
||||
param.v=Par[2];
|
||||
case 2:
|
||||
setH(Par[0]);
|
||||
setS(Par[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setSuffix(S_RGB);
|
||||
switch (i) //Number of params
|
||||
{
|
||||
case 3: RGB(Par[0],Par[1],Par[2]);
|
||||
break;
|
||||
case 4: RGBW(Par[0],Par[1],Par[2],Par[3]);
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// case CMD_UNKNOWN: //Not known command
|
||||
// case CMD_JSON: //JSON input (not implemented yet
|
||||
// cmd.cmdCode=CMD_VOID;
|
||||
// break;
|
||||
|
||||
default: //some known command
|
||||
//case CMD_VOID:
|
||||
//case CMD_UP:
|
||||
//case CMD_DN:
|
||||
{
|
||||
itemCmd num =getNumber((char **) &_cmd);
|
||||
cmd.itemArgType=num.getArgType();
|
||||
param.aslong=num.param.aslong;
|
||||
if (cmd.cmdCode) setSuffix(S_CMD);
|
||||
}
|
||||
} //switch
|
||||
//debugOut();
|
||||
}
|
||||
|
||||
itemCmd itemCmd::setChanType(short chanType)
|
||||
|
||||
@@ -148,6 +148,7 @@ volatile unsigned long timerCount=0;
|
||||
volatile int16_t timerNumber=-1;
|
||||
volatile int8_t timerHandlerBusy=0;
|
||||
volatile uint32_t cryptoSalt=0;
|
||||
volatile uint32_t ultrasonicInputCheck=0;
|
||||
//uint32_t timerCtr=0;
|
||||
|
||||
aJsonObject *pollingItem = NULL;
|
||||
@@ -778,14 +779,30 @@ lan_status lanLoop() {
|
||||
lanStatus=READ_RE_CONFIG;
|
||||
break;
|
||||
|
||||
case AWAITING_CONFIG:
|
||||
if (isTimeOver(timerLanCheckTime,millis(),TIMEOUT_REINIT_NOT_CONFIGURED))
|
||||
lanStatus=DO_REINIT;
|
||||
break;
|
||||
|
||||
case READ_RE_CONFIG: // Restore config from FLASH, re-init LAN
|
||||
if (loadConfigFromEEPROM()) lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
|
||||
else
|
||||
switch (loadConfigFromEEPROM())
|
||||
{
|
||||
case 1: lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
|
||||
break;
|
||||
|
||||
case -1: //Temporary busy
|
||||
if (isTimeOver(timerLanCheckTime,millis(),TIMEOUT_RELOAD))
|
||||
{
|
||||
errorSerial<<F("30s EEPROM is not reloaded. Reboot");
|
||||
softRebootFunc();
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
lanStatus = AWAITING_CONFIG;
|
||||
timerLanCheckTime = millis();
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case DO_GET:
|
||||
@@ -1558,7 +1575,7 @@ lanStatus=DO_READ_RE_CONFIG;
|
||||
|
||||
int loadConfigFromEEPROM()
|
||||
{
|
||||
if (configLocked) return 0;
|
||||
if (configLocked) return -1;
|
||||
configLocked++;
|
||||
|
||||
infoSerial<<F("Loading Config from EEPROM")<<endl;
|
||||
@@ -2957,13 +2974,21 @@ void inputLoop(short cause) {
|
||||
inputLoopBusy++;
|
||||
|
||||
configLocked++;
|
||||
bool needCheckUltrasonic = false;
|
||||
//if (millis() > timerInputCheck)
|
||||
if (isTimeOver(timerInputCheck,millis(),INTERVAL_CHECK_INPUT))
|
||||
{
|
||||
if ((cause != CHECK_INTERRUPT) && isTimeOver(ultrasonicInputCheck,millis(),INTERVAL_CHECK_ULTRASONIC)) needCheckUltrasonic=true;
|
||||
|
||||
aJsonObject *input = inputs->child;
|
||||
|
||||
while (input) {
|
||||
if (input->type == aJson_Object) {
|
||||
|
||||
Input in(input);
|
||||
in.Poll(cause);
|
||||
if (needCheckUltrasonic) in.Poll(CHECK_ULTRASONIC);
|
||||
|
||||
// Check for nested inputs
|
||||
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
|
||||
if (inputArray && (inputArray->type == aJson_Array))
|
||||
@@ -2974,6 +2999,7 @@ configLocked++;
|
||||
{
|
||||
Input in(inputObj,input);
|
||||
in.Poll(cause);
|
||||
if (needCheckUltrasonic) in.Poll(CHECK_ULTRASONIC);
|
||||
|
||||
//yield();
|
||||
inputObj = inputObj->next;
|
||||
@@ -2982,14 +3008,16 @@ configLocked++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input in(input);
|
||||
in.Poll(cause);
|
||||
//Input in(input);
|
||||
//in.Poll(cause);
|
||||
//if (needCheckUltrasonic) in.Poll(CHECK_ULTRASONIC);
|
||||
}
|
||||
}
|
||||
//yield();
|
||||
input = input->next;
|
||||
}
|
||||
if (cause != CHECK_INTERRUPT) timerInputCheck = millis();// + INTERVAL_CHECK_INPUT;
|
||||
if (cause != CHECK_INTERRUPT) timerInputCheck = millis();
|
||||
if (needCheckUltrasonic) {ultrasonicInputCheck = millis(); needCheckUltrasonic=false;}
|
||||
inCache.invalidateInputCache();
|
||||
}
|
||||
configLocked--;
|
||||
|
||||
@@ -232,7 +232,8 @@ enum lan_status {
|
||||
DO_NOTHING = -15,
|
||||
DO_GET = -16,
|
||||
GET = -17,
|
||||
GET_IN_PROGRESS = 18
|
||||
GET_IN_PROGRESS = 18,
|
||||
AWAITING_CONFIG = 19
|
||||
};
|
||||
|
||||
extern lan_status lanStatus;
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
#define TIMEOUT_REINIT 5000UL
|
||||
#define TIMEOUT_RELOAD 30000UL
|
||||
#define TIMEOUT_RETAIN 8000UL
|
||||
#define TIMEOUT_REINIT_NOT_CONFIGURED 120000UL
|
||||
#define INTERVAL_1W 5000UL
|
||||
#define PERIOD_THERMOSTAT_FAILED (600 * 1000UL)
|
||||
|
||||
@@ -120,6 +121,8 @@
|
||||
#define INTERVAL_CHECK_INPUT 11
|
||||
#endif
|
||||
|
||||
#define INTERVAL_CHECK_ULTRASONIC 100
|
||||
|
||||
#ifndef TIMER_CHECK_INPUT
|
||||
#define TIMER_CHECK_INPUT 15
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@ virtual unsigned int seek(unsigned int _pos = 0) = 0;
|
||||
virtual int open(String _filename, char mode) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual uint16_t getContentType() {return contentType;};
|
||||
virtual void putEOF() {if (textMode) write (EOFchar);};
|
||||
virtual void putEOF() {if (textMode) {write (EOFchar);textMode=false;}};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -110,7 +110,7 @@ return !err;
|
||||
|
||||
// chan is pointer to pointer to string
|
||||
// Function return first retrived integer and move pointer to position next after ','
|
||||
long getInt(char **chan) {
|
||||
long getIntFromStr(char **chan) {
|
||||
if (chan && *chan && **chan)
|
||||
{
|
||||
//Skip non-numeric values
|
||||
|
||||
@@ -53,7 +53,7 @@ void PrintBytes(uint8_t* addr, uint8_t count, bool newline);
|
||||
void SetBytes(uint8_t* addr, uint8_t count, char * out);
|
||||
bool SetAddr(char * in, uint8_t* addr);
|
||||
uint8_t HEX2DEC(char i, bool* err);
|
||||
long getInt(char ** chan);
|
||||
long getIntFromStr(char **chan);
|
||||
itemCmd getNumber(char ** chan);
|
||||
unsigned long freeRam ();
|
||||
void parseBytes(const char* str, char separator, byte* bytes, int maxBytes, int base);
|
||||
|
||||
Reference in New Issue
Block a user