timer conflict test now directly uses the proposed sTimer info, not the NV staged values.

This commit is contained in:
rljonesau 2019-02-15 06:36:13 +11:00
parent fefb84a87a
commit aade6fdc34
5 changed files with 111 additions and 47 deletions

View file

@ -161,8 +161,8 @@ CSetTimerScreen::keyHandler(uint8_t event)
_colSel = 4; _colSel = 4;
} }
else { // in config fields, save new settings else { // in config fields, save new settings
NVstore.setTimerInfo(_timerID, _timerInfo); // test if the setting conflict with an already defined timer
_conflictID = CTimerManager::conflictTest(_timerID); _conflictID = CTimerManager::conflictTest(_timerInfo);
if(_conflictID) { if(_conflictID) {
_timerInfo.enabled = 0; // cancel enabled status _timerInfo.enabled = 0; // cancel enabled status
_ConflictTime = millis() + 1500; _ConflictTime = millis() + 1500;
@ -174,7 +174,7 @@ CSetTimerScreen::keyHandler(uint8_t event)
} }
_rowSel = 0; _rowSel = 0;
_colSel = 0; _colSel = 0;
NVstore.setTimerInfo(_timerID, _timerInfo); // may have got disabled NVstore.setTimerInfo(_timerID, _timerInfo); // save, but timer may have got disabled
NVstore.save(); NVstore.save();
} }
} }

View file

@ -36,7 +36,6 @@
void void
CTimerManager::createMap(int timerMask, uint16_t timerMap[24*60], uint16_t timerIDs[24*60]) CTimerManager::createMap(int timerMask, uint16_t timerMap[24*60], uint16_t timerIDs[24*60])
{ {
int maxPoints = 24*60;
memset(timerMap, 0, 24*60*sizeof(uint16_t)); memset(timerMap, 0, 24*60*sizeof(uint16_t));
memset(timerIDs, 0, 24*60*sizeof(uint16_t)); memset(timerIDs, 0, 24*60*sizeof(uint16_t));
@ -48,46 +47,99 @@ CTimerManager::createMap(int timerMask, uint16_t timerMap[24*60], uint16_t timer
// get timer settings // get timer settings
NVstore.getTimerInfo(timerID, timer); NVstore.getTimerInfo(timerID, timer);
// and add info to map if enabled // and add info to map if enabled
if(timer.enabled) { createMap(timer, timerMap, timerIDs);
// create linear minute of day values for start & stop // if(timer.enabled) {
// note that if stop < start, that is treated as a timer that rolls over midnight // // create linear minute of day values for start & stop
int timestart = timer.start.hour * 60 + timer.start.min; // linear minute of day // // note that if stop < start, that is treated as a timer that rolls over midnight
int timestop = timer.stop.hour * 60 + timer.stop.min; // int timestart = timer.start.hour * 60 + timer.start.min; // linear minute of day
for(int dayMinute = 0; dayMinute < maxPoints; dayMinute++) { // int timestop = timer.stop.hour * 60 + timer.stop.min;
for(int day = 0x01; day != 0x80; day <<= 1) { // for(int dayMinute = 0; dayMinute < maxPoints; dayMinute++) {
if(timer.enabled & day || timer.enabled & 0x80) { // specific or everyday // for(int day = 0x01; day != 0x80; day <<= 1) {
uint16_t activeday = day; // may also hold non repeat flag later // if(timer.enabled & day || timer.enabled & 0x80) { // specific or everyday
if(!timer.repeat) { // uint16_t activeday = day; // may also hold non repeat flag later
// flag timers that should get cancelled // if(!timer.repeat) {
activeday |= (activeday << 8); // combine one shot status in MS byte // // flag timers that should get cancelled
} // activeday |= (activeday << 8); // combine one shot status in MS byte
if(timestop > timestart) { // }
// treat normal start < stop times (within same day) // if(timestop > timestart) {
if((dayMinute >= timestart) && (dayMinute < timestop)) { // // treat normal start < stop times (within same day)
timerMap[dayMinute] |= activeday; // if((dayMinute >= timestart) && (dayMinute < timestop)) {
timerIDs[dayMinute] |= timerBit; // timerMap[dayMinute] |= activeday;
} // timerIDs[dayMinute] |= timerBit;
} // }
else { // }
// time straddles a day, start > stop, special treatment required // else {
if(dayMinute >= timestart) { // // time straddles a day, start > stop, special treatment required
// true from start until midnight // if(dayMinute >= timestart) {
timerMap[dayMinute] |= activeday; // // true from start until midnight
timerIDs[dayMinute] |= timerBit; // timerMap[dayMinute] |= activeday;
} // timerIDs[dayMinute] |= timerBit;
if(dayMinute < timestop) { // }
// after midnight, before stop time, i.e. next day // if(dayMinute < timestop) {
// adjust for next day, taking care to wrap week // // after midnight, before stop time, i.e. next day
if(day & 0x40) // last day of week? // // adjust for next day, taking care to wrap week
activeday >>= 6; // roll back to start of week // if(day & 0x40) // last day of week?
else // activeday >>= 6; // roll back to start of week
activeday <<= 1; // next day // else
timerMap[dayMinute] |= activeday; // activeday <<= 1; // next day
timerIDs[dayMinute] |= timerBit; // timerMap[dayMinute] |= activeday;
} // timerIDs[dayMinute] |= timerBit;
} // }
// }
// }
// }
// }
// }
}
}
}
// create a timer map, based only upon the supplied timer info
// the other form of createMap uses the NV stored timer info
void
CTimerManager::createMap(sTimer& timer, uint16_t timerMap[24*60], uint16_t timerIDs[24*60])
{
int maxPoints = 24*60;
int timerBit = 0x0001 << timer.timerID;
if(timer.enabled) {
// create linear minute of day values for start & stop
// note that if stop < start, that is treated as a timer that rolls over midnight
int timestart = timer.start.hour * 60 + timer.start.min; // linear minute of day
int timestop = timer.stop.hour * 60 + timer.stop.min;
for(int dayMinute = 0; dayMinute < maxPoints; dayMinute++) {
for(int day = 0x01; day != 0x80; day <<= 1) {
if(timer.enabled & day || timer.enabled & 0x80) { // specific or everyday
uint16_t activeday = day; // may also hold non repeat flag later
if(!timer.repeat) {
// flag timers that should get cancelled
activeday |= (activeday << 8); // combine one shot status in MS byte
}
if(timestop > timestart) {
// treat normal start < stop times (within same day)
if((dayMinute >= timestart) && (dayMinute < timestop)) {
timerMap[dayMinute] |= activeday;
timerIDs[dayMinute] |= timerBit;
} }
} }
else {
// time straddles a day, start > stop, special treatment required
if(dayMinute >= timestart) {
// true from start until midnight
timerMap[dayMinute] |= activeday;
timerIDs[dayMinute] |= timerBit;
}
if(dayMinute < timestop) {
// after midnight, before stop time, i.e. next day
// adjust for next day, taking care to wrap week
if(day & 0x40) // last day of week?
activeday >>= 6; // roll back to start of week
else
activeday <<= 1; // next day
timerMap[dayMinute] |= activeday;
timerIDs[dayMinute] |= timerBit;
}
}
} }
} }
} }
@ -117,12 +169,17 @@ uint16_t selectedTimer[24*60];
uint16_t timerIDs[24*60]; uint16_t timerIDs[24*60];
int int
CTimerManager::conflictTest(int timerID) CTimerManager::conflictTest(sTimer& timerInfo)
{ {
int selectedMask = 0x0001 << timerID; // int timerID = timerInfo.timerID;
int selectedMask = 0x0001 << timerInfo.timerID; // bit mask for timer we are testing
int othersMask = 0x3fff & ~selectedMask;
memset(selectedTimer, 0, sizeof(selectedTimer));
createMap(timerInfo, selectedTimer, timerIDs); // create a map from the supplied timer info (under test)
createMap(othersMask, otherTimers, timerIDs); // create a map for all other timers, and get their unique IDs
createMap(selectedMask, selectedTimer, timerIDs); // create a map for the nominated timer (under test)
createMap(0x3fff & ~selectedMask, otherTimers, timerIDs); // create a map for all other timers, and get their unique IDs
for(int i=0; i< 24*60; i++) { for(int i=0; i< 24*60; i++) {
if(otherTimers[i] & selectedTimer[i]) { // both have the same day bit set - CONFLICT! if(otherTimers[i] & selectedTimer[i]) { // both have the same day bit set - CONFLICT!
uint16_t timerBit = timerIDs[i]; uint16_t timerBit = timerIDs[i];

View file

@ -33,11 +33,14 @@
#include <stdint.h> #include <stdint.h>
struct sTimer;
class CTimerManager { class CTimerManager {
public: public:
static void createMap(int timermask, uint16_t map[24*60], uint16_t timerIDs[24*60]); static void createMap(int timermask, uint16_t map[24*60], uint16_t timerIDs[24*60]);
static void createMap(sTimer& timer, uint16_t timerMap[24*60], uint16_t timerIDs[24*60]);
static void condenseMap(uint16_t timerMap[24*60], int factor); static void condenseMap(uint16_t timerMap[24*60], int factor);
static int conflictTest(int timerID); static int conflictTest(sTimer& timer);
}; };
#endif //__TIMERMANAGER_H__ #endif //__TIMERMANAGER_H__

View file

@ -294,6 +294,7 @@ void
CESP32HeaterStorage::loadTimer(int idx) CESP32HeaterStorage::loadTimer(int idx)
{ {
sTimer& timer = _calValues.timer[idx]; sTimer& timer = _calValues.timer[idx];
timer.timerID = idx;
char SectionName[16]; char SectionName[16];
sprintf(SectionName, "timer%d", idx+1); sprintf(SectionName, "timer%d", idx+1);
preferences.begin(SectionName, false); preferences.begin(SectionName, false);

View file

@ -78,10 +78,12 @@ struct sTimer {
uint8_t enabled; // timer enabled - each bit is a day of week flag uint8_t enabled; // timer enabled - each bit is a day of week flag
uint8_t repeat; // repeating timer uint8_t repeat; // repeating timer
uint8_t temperature; uint8_t temperature;
uint8_t timerID; // numeric ID
sTimer() { sTimer() {
enabled = 0; enabled = 0;
repeat = false; repeat = false;
temperature = 22; temperature = 22;
timerID = 0;
}; };
sTimer& operator=(const sTimer& rhs) { sTimer& operator=(const sTimer& rhs) {
start = rhs.start; start = rhs.start;
@ -89,6 +91,7 @@ struct sTimer {
enabled = rhs.enabled; enabled = rhs.enabled;
repeat = rhs.repeat; repeat = rhs.repeat;
temperature = rhs.temperature; temperature = rhs.temperature;
timerID = rhs.timerID;
}; };
void init() { void init() {
start.hour = 0; start.hour = 0;