mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03:00
single, double, tripple click, longpress, repeat logic for contact inputs are added
This commit is contained in:
@@ -113,7 +113,7 @@ void Input::Parse()
|
||||
void Input::setup()
|
||||
{
|
||||
if (!isValid() || (!root)) return;
|
||||
|
||||
/*
|
||||
#ifndef CSSHDC_DISABLE
|
||||
if (inType == IN_CCS811)
|
||||
{
|
||||
@@ -127,6 +127,51 @@ if (!isValid() || (!root)) return;
|
||||
}
|
||||
// TODO rest types setup
|
||||
#endif
|
||||
*/
|
||||
store->aslong=0;
|
||||
uint8_t inputPinMode = INPUT; //if IN_ACTIVE_HIGH
|
||||
switch (inType)
|
||||
{
|
||||
case IN_PUSH_ON:
|
||||
case IN_PUSH_TOGGLE :
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
||||
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
||||
pinMode(pin, inputPinMode);
|
||||
|
||||
store->state=IS_IDLE;
|
||||
break;
|
||||
|
||||
case IN_ANALOG:
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
case IN_ANALOG | IN_ACTIVE_HIGH:
|
||||
pinMode(pin, inputPinMode);
|
||||
break;
|
||||
|
||||
case IN_DHT22:
|
||||
case IN_COUNTER:
|
||||
case IN_UPTIME:
|
||||
break;
|
||||
|
||||
#ifndef CSSHDC_DISABLE
|
||||
case IN_CCS811:
|
||||
{
|
||||
in_ccs811 ccs811(this);
|
||||
ccs811.Setup();
|
||||
}
|
||||
break;
|
||||
|
||||
case IN_HDC1080:
|
||||
{
|
||||
in_hdc1080 hdc1080(this);
|
||||
hdc1080.Setup();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
} //switch
|
||||
|
||||
}
|
||||
|
||||
@@ -140,17 +185,18 @@ if (!isValid()) return -1;
|
||||
|
||||
switch (cause) {
|
||||
case CHECK_INPUT: //Fast polling
|
||||
case CHECK_INTERRUPT: //Realtime polling
|
||||
switch (inType)
|
||||
{
|
||||
case IN_PUSH_ON:
|
||||
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
||||
case IN_PUSH_TOGGLE :
|
||||
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
||||
contactPoll();
|
||||
contactPoll(cause);
|
||||
break;
|
||||
case IN_ANALOG:
|
||||
case IN_ANALOG | IN_ACTIVE_HIGH:
|
||||
analogPoll();
|
||||
analogPoll(cause);
|
||||
break;
|
||||
|
||||
// No fast polling
|
||||
@@ -406,43 +452,331 @@ void Input::dht22Poll() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void Input::contactPoll() {
|
||||
boolean currentInputState;
|
||||
bool Input::executeCommand(aJsonObject* cmd, char* defCmd)
|
||||
{
|
||||
if (!cmd) return false;
|
||||
|
||||
switch (cmd->type)
|
||||
{
|
||||
case aJson_String: //legacy - no action
|
||||
break;
|
||||
case aJson_Array: //array - recursive iterate
|
||||
{
|
||||
aJsonObject * command = cmd->child;
|
||||
while (command)
|
||||
{
|
||||
executeCommand(command,defCmd);
|
||||
command = command->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case aJson_Object:
|
||||
{
|
||||
aJsonObject *item = aJson.getObjectItem(cmd, "item");
|
||||
aJsonObject *icmd = aJson.getObjectItem(cmd, "icmd");
|
||||
aJsonObject *ecmd = aJson.getObjectItem(cmd, "ecmd");
|
||||
aJsonObject *emit = aJson.getObjectItem(cmd, "emit");
|
||||
|
||||
char * itemCommand;
|
||||
if(icmd) itemCommand = icmd->valuestring;
|
||||
else itemCommand = defCmd;
|
||||
|
||||
char * emitCommand;
|
||||
if(ecmd) emitCommand = ecmd->valuestring;
|
||||
else emitCommand = defCmd;
|
||||
|
||||
debugSerial << F("IN:") << (pin) << F(" : ") <<endl;
|
||||
if (item) debugSerial << item->valuestring<< F(" -> ")<<itemCommand<<endl;
|
||||
if (emit) debugSerial << emit->valuestring<< F(" -> ")<<emitCommand<<endl;
|
||||
|
||||
|
||||
|
||||
|
||||
if (emit && emitCommand) {
|
||||
/*
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
WiringPinMode inputPinMode;
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)||defined(ARDUINO_ARCH_AVR)||defined(ARDUINO_ARCH_ESP8266)||defined(ARDUINO_ARCH_ESP32)
|
||||
|
||||
TODO implement
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if (getIdxField())
|
||||
{ (newValue) ? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}",
|
||||
: publishDataToDomoticz(0,emit,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",getIdxField()); getIdxField())
|
||||
: publishDataToDomoticz(0, emit,
|
||||
"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",
|
||||
getIdxField());
|
||||
} else
|
||||
#endif
|
||||
*/
|
||||
uint32_t inputPinMode;
|
||||
uint8_t inputOnLevel;
|
||||
if (inType & IN_ACTIVE_HIGH) {
|
||||
inputOnLevel = HIGH;
|
||||
inputPinMode = INPUT;
|
||||
} else {
|
||||
inputOnLevel = LOW;
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
{
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
||||
if (mqttClient.connected() && !ethernetIdleCount)
|
||||
{
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||
mqttClient.publish(addrstr, emitCommand , true);
|
||||
}
|
||||
}
|
||||
} // emit
|
||||
if (item && itemCommand) {
|
||||
//debugSerial <<F("Controlled item:")<< item->valuestring <<endl;
|
||||
Item it(item->valuestring);
|
||||
if (it.isValid()) it.Ctrl(itemCommand, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
} //switch type
|
||||
}
|
||||
|
||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
||||
bool Input::changeState(uint8_t newState, short cause)
|
||||
{
|
||||
if (!inputObj || !store) return false;
|
||||
|
||||
if (newState == IS_REQSTATE)
|
||||
if (store->delayedState && cause != CHECK_INTERRUPT)
|
||||
{
|
||||
// Requested delayed change State and safe moment
|
||||
newState=store->reqState; //Retrieve requested state
|
||||
debugSerial<<F("Pended state retrieved:")<<newState;
|
||||
|
||||
}
|
||||
pinMode(pin, inputPinMode);
|
||||
else return true; // No pended State
|
||||
else if (store->delayedState)
|
||||
return false; //State changing is postponed already (( giving up
|
||||
|
||||
aJsonObject *cmd = NULL;
|
||||
|
||||
switch (newState)
|
||||
{
|
||||
case IS_IDLE:
|
||||
switch (store->state)
|
||||
{
|
||||
case IS_RELEASED: //click
|
||||
cmd = aJson.getObjectItem(inputObj, "click");
|
||||
break;
|
||||
case IS_RELEASED2: //doubleclick
|
||||
cmd = aJson.getObjectItem(inputObj, "dclick");
|
||||
break;
|
||||
case IS_PRESSED3: //tripple click
|
||||
cmd = aJson.getObjectItem(inputObj, "tclick");
|
||||
break;
|
||||
case IS_WAITPRESS: //do nothing
|
||||
break;
|
||||
default: //rcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
;
|
||||
}
|
||||
break;
|
||||
case IS_PRESSED: //scmd
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd");
|
||||
break;
|
||||
case IS_PRESSED2: //scmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd2");
|
||||
break;
|
||||
case IS_PRESSED3: //scmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd3");
|
||||
break;
|
||||
|
||||
case IS_RELEASED: //rcmd
|
||||
case IS_WAITPRESS:
|
||||
case IS_RELEASED2:
|
||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
|
||||
break;
|
||||
case IS_LONG: //lcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd");
|
||||
break;
|
||||
case IS_REPEAT: //rpcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd");
|
||||
break;
|
||||
case IS_LONG2: //lcmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd2");
|
||||
break;
|
||||
case IS_REPEAT2: //rpcmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd2");
|
||||
break;
|
||||
case IS_LONG3: //lcmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd3");
|
||||
break;
|
||||
case IS_REPEAT3: //rpcmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd3");
|
||||
break;
|
||||
|
||||
}
|
||||
if (!cmd)
|
||||
{
|
||||
store->state=newState;
|
||||
return true; //nothing to do
|
||||
}
|
||||
if (cause != CHECK_INTERRUPT)
|
||||
{
|
||||
executeCommand(cmd);
|
||||
//Executed
|
||||
store->state=newState;
|
||||
store->delayedState=false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Postpone actual execution
|
||||
store->reqState=store->state;
|
||||
store->delayedState=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Input::contactPoll(short cause) {
|
||||
boolean currentInputState;
|
||||
if (!store) return;
|
||||
|
||||
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
|
||||
|
||||
|
||||
uint8_t inputOnLevel;
|
||||
if (inType & IN_ACTIVE_HIGH) inputOnLevel = HIGH;
|
||||
else inputOnLevel = LOW;
|
||||
|
||||
|
||||
currentInputState = (digitalRead(pin) == inputOnLevel);
|
||||
if (currentInputState != store->currentValue) // value changed
|
||||
|
||||
switch (store->state) //Timer based transitions
|
||||
{
|
||||
case IS_PRESSED:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) changeState(IS_LONG, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_PRESSED2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) changeState(IS_LONG2, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT2, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT2, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_PRESSED3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) changeState(IS_LONG3, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT3, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT3, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_RELEASED:
|
||||
case IS_RELEASED2:
|
||||
case IS_WAITPRESS:
|
||||
|
||||
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause);
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentInputState != store->lastValue) // value changed
|
||||
{
|
||||
if (store->bounce) store->bounce = store->bounce - 1;
|
||||
else //confirmed change
|
||||
{
|
||||
if (inType & IN_PUSH_TOGGLE) {
|
||||
store->timestamp16 = millis() & 0xFFFF; //Saving timestamp of changing
|
||||
|
||||
if (inType & IN_PUSH_TOGGLE) { //To refactore
|
||||
if (currentInputState) { //react on leading edge only (change from 0 to 1)
|
||||
store->logicState = !store->logicState;
|
||||
store->currentValue = currentInputState;
|
||||
store->lastValue = currentInputState;
|
||||
onContactChanged(store->logicState);
|
||||
}
|
||||
} else {
|
||||
store->logicState = currentInputState;
|
||||
store->currentValue = currentInputState;
|
||||
onContactChanged(currentInputState);
|
||||
} else
|
||||
|
||||
{
|
||||
onContactChanged(currentInputState); //Legacy input - to remove later
|
||||
|
||||
bool res = true;
|
||||
if (currentInputState) //Button pressed state transitions
|
||||
|
||||
switch (store->state)
|
||||
{
|
||||
case IS_IDLE:
|
||||
res = changeState(IS_PRESSED, cause);
|
||||
break;
|
||||
|
||||
case IS_RELEASED:
|
||||
case IS_WAITPRESS:
|
||||
res = changeState(IS_PRESSED2, cause);
|
||||
break;
|
||||
|
||||
case IS_RELEASED2:
|
||||
|
||||
res = changeState(IS_PRESSED3, cause);
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch (store->state) //Button released state transitions
|
||||
{
|
||||
case IS_PRESSED:
|
||||
res = changeState(IS_RELEASED, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
case IS_REPEAT:
|
||||
res = changeState(IS_WAITPRESS, cause);
|
||||
break;
|
||||
|
||||
case IS_PRESSED2:
|
||||
res = changeState(IS_RELEASED2, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG2:
|
||||
case IS_REPEAT2:
|
||||
case IS_LONG3:
|
||||
case IS_REPEAT3:
|
||||
case IS_PRESSED3:
|
||||
res = changeState(IS_IDLE, cause);
|
||||
break;
|
||||
}
|
||||
if (res) { //State changed or postponed
|
||||
store->logicState = currentInputState;
|
||||
store->lastValue = currentInputState;
|
||||
}
|
||||
}
|
||||
// store->currentValue = currentInputState;
|
||||
}
|
||||
@@ -451,23 +785,26 @@ void Input::contactPoll() {
|
||||
}
|
||||
|
||||
|
||||
void Input::analogPoll() {
|
||||
|
||||
void Input::analogPoll(short cause) {
|
||||
int16_t inputVal;
|
||||
int32_t mappedInputVal; // 10x inputVal
|
||||
aJsonObject *inputMap = aJson.getObjectItem(inputObj, "map");
|
||||
int16_t Noize = ANALOG_NOIZE;
|
||||
short simple = 0;
|
||||
uint32_t inputPinMode;
|
||||
// uint32_t inputPinMode;
|
||||
int max=1024*10;
|
||||
int min=0;
|
||||
|
||||
|
||||
/*
|
||||
if (inType & IN_ACTIVE_HIGH) {
|
||||
inputPinMode = INPUT;
|
||||
} else {
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
}
|
||||
|
||||
pinMode(pin, inputPinMode);
|
||||
*/
|
||||
inputVal = analogRead(pin);
|
||||
// Mapping
|
||||
if (inputMap && inputMap->type == aJson_Array)
|
||||
@@ -522,11 +859,13 @@ void Input::analogPoll() {
|
||||
|
||||
|
||||
void Input::onContactChanged(int newValue) {
|
||||
debugSerial << F("IN:") << (pin) << F("=") << newValue << endl;
|
||||
|
||||
aJsonObject *item = aJson.getObjectItem(inputObj, "item");
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
if (!item && !emit) return;
|
||||
aJsonObject *scmd = aJson.getObjectItem(inputObj, "scmd");
|
||||
aJsonObject *rcmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
debugSerial << F("LEGACY IN:") << (pin) << F("=") << newValue << endl;
|
||||
if (emit) {
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if (getIdxField())
|
||||
|
||||
@@ -35,6 +35,22 @@ e-mail anklimov@gmail.com
|
||||
#define IN_COUNTER 8
|
||||
#define IN_UPTIME 16
|
||||
|
||||
#define IS_IDLE 0
|
||||
#define IS_PRESSED 1
|
||||
#define IS_RELEASED 2
|
||||
#define IS_LONG 3
|
||||
#define IS_REPEAT 4
|
||||
#define IS_WAITPRESS 5
|
||||
#define IS_PRESSED2 6
|
||||
#define IS_RELEASED2 7
|
||||
#define IS_LONG2 8u
|
||||
#define IS_REPEAT2 9u
|
||||
#define IS_PRESSED3 10u
|
||||
#define IS_LONG3 11u
|
||||
#define IS_REPEAT3 12u
|
||||
#define IS_REQSTATE 0xFF
|
||||
|
||||
|
||||
|
||||
#define SAME_STATE_ATTEMPTS 3
|
||||
#define ANALOG_STATE_ATTEMPTS 6
|
||||
@@ -42,6 +58,15 @@ e-mail anklimov@gmail.com
|
||||
|
||||
#define CHECK_INPUT 1
|
||||
#define CHECK_SENSOR 2
|
||||
#define CHECK_INTERRUPT 3
|
||||
#define CHECK_DELAYED 4
|
||||
|
||||
#define T_LONG 1000
|
||||
#define T_IDLE 600
|
||||
#define T_RPT 300
|
||||
#define T_RPT_PULSE 200
|
||||
|
||||
|
||||
|
||||
// in syntaxis
|
||||
// "pin": { "T":"N", "emit":"out_emit", item:"out_item", "scmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd":"repeat_command" }
|
||||
@@ -79,11 +104,24 @@ extern aJsonObject *inputs;
|
||||
typedef union {
|
||||
long int aslong;
|
||||
uint32_t timestamp;
|
||||
// Analog input structure
|
||||
struct {
|
||||
int8_t logicState;
|
||||
int8_t bounce;
|
||||
uint8_t reserved;
|
||||
uint8_t reserved2;
|
||||
int16_t currentValue;
|
||||
};
|
||||
// Digital input structure
|
||||
struct {
|
||||
uint8_t reserved3:1;
|
||||
uint8_t lastValue:1;
|
||||
uint8_t logicState:1;
|
||||
uint8_t delayedState:1;
|
||||
uint8_t bounce:4;
|
||||
uint8_t state:4;
|
||||
uint8_t reqState:4;
|
||||
uint16_t timestamp16;
|
||||
|
||||
};
|
||||
|
||||
} inStore;
|
||||
|
||||
@@ -121,8 +159,8 @@ public:
|
||||
protected:
|
||||
void Parse();
|
||||
|
||||
void contactPoll();
|
||||
void analogPoll();
|
||||
void contactPoll(short cause);
|
||||
void analogPoll(short cause);
|
||||
|
||||
void dht22Poll();
|
||||
|
||||
@@ -140,4 +178,6 @@ protected:
|
||||
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
||||
|
||||
char* getIdxField();
|
||||
bool changeState(uint8_t newState, short cause);
|
||||
bool executeCommand(aJsonObject* cmd, char* defCmd = NULL);
|
||||
};
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
int mqtt::publish(int value)
|
||||
{};
|
||||
|
||||
int mqtt::publish(float value)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
int mqtt::publish(char * value)
|
||||
{
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
aJsonObject *emit = aJson.getObjectItem(in, "emit");
|
||||
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||
if mqttClient.connected() mqttClient.publish(addrstr, value, true);
|
||||
};
|
||||
*/
|
||||
@@ -51,7 +51,7 @@
|
||||
#define EEPROM_offset EEPROM_offset_NotAlligned + (4 -(EEPROM_offset_NotAlligned & 3))
|
||||
|
||||
#ifndef INTERVAL_CHECK_INPUT
|
||||
#define INTERVAL_CHECK_INPUT 50
|
||||
#define INTERVAL_CHECK_INPUT 15
|
||||
#endif
|
||||
|
||||
#ifndef INTERVAL_CHECK_SENSOR
|
||||
|
||||
@@ -504,5 +504,13 @@ RebootFunc();
|
||||
#endif
|
||||
|
||||
|
||||
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo)
|
||||
{
|
||||
uint32_t endTime=(timestamp + time) % modulo;
|
||||
return ((currTime>endTime) && (currTime <timestamp)) ||
|
||||
((timestamp<endTime) && ((currTime>endTime) || (currTime <timestamp)));
|
||||
}
|
||||
|
||||
|
||||
#pragma message(VAR_NAME_VALUE(debugSerial))
|
||||
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
||||
|
||||
@@ -59,3 +59,4 @@ char* setTopic(char* buf, int8_t buflen, topicType tt, const char* suffix = NULL
|
||||
void printUlongValueToStr(char *valstr, unsigned long value);
|
||||
void scan_i2c_bus();
|
||||
void softRebootFunc();
|
||||
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo = 0xFFFFFFFF);
|
||||
|
||||
Reference in New Issue
Block a user