openshwprojects / OpenBK7231T_App

Open source firmware (Tasmota/Esphome replacement) for BK7231T, BK7231N, BL2028N, T34, XR809, W800/W801, W600/W601 and BL602
https://openbekeniot.github.io/webapp/devicesList.html
1.39k stars 241 forks source link

Feature Request: Outlet scheduling #676

Open kapplejacks opened 1 year ago

kapplejacks commented 1 year ago

Is there a way to set schedules for different outlets? Id like to be able to turn them on and off at specific times and days.

Thank you!

valeklubomir commented 1 year ago

Usually this kind of functionality is supported on the side of Cloud/ Home Assistent. Localy no function is implemented. Eventually with script could it be done. Device is capable to obtain time and date from NTP server. Question is if script function can work and handle date/time.

From my experience little stand-alone functionality could be desired. Local scripting is probably best solution.

I had issues with home automation, with thermostat control. Electric water heater was controlled by logic in Cloud, but network connenction was broken, and control loop was interrupted, luckily heater has thermal surge, it did not overheat. But the water temperature was way over safe temperature limit (70 instead of 50 degree C). I had to change it and implement local logic and cloud logic work as backup/overide now.

openshwprojects commented 1 year ago

I think it should be relatively simple to create some kind of daily events and let user assign them to specific day of week, specific hour and a minute. A quick tick or second tick could iterate all events and check if timing conditions are met, and if so, fire the event string. The calendar driver would have to make sure that first NTP must be running and also might take in account case where next NTP packet shifts time several seconds in the future (to avoid skipped events), but all seems doable.... the only question is what if device reboots near the time of the event, maybe we should store last update time in flash memory and after reboot is done and ntp is up continue from there...

I might look into it tomorrow, but I had a busy week, we just finished BL602 guide: https://www.youtube.com/watch?v=L6d42IMGhHw&ab_channel=Elektrodacom

openshwprojects commented 1 year ago

@valeklubomir @kapplejacks ok I started working on that. For now, a simple version. That will of course require NTP driver. Here is how it will work: image

@valeklubomir , you know things well, can you take a look at my proposed system and suggest potential changes or improvements? https://github.com/openshwprojects/OpenBK7231T_App/commit/c88e13928a618bcf8e08bb9193fe2fb7476a87c2 It's not finished, but you should get an idea what I am planning to do. The NTP_RunEvents function is supposed to handle all cases, including a case where NTP resynch changes time to be several seconds in future. The NTP_RunEvents is called every second.

We could also add ability to run an event on given day of given month, but is it needed?

valekCN commented 1 year ago

How do I handle this with reset? I don't think startup command can process multiple addClockEvents, when backlog can be used in command.

valekCN commented 1 year ago

NTP Sync could be an issue. But minor one.

I imagine scheduler with more logic.

Here event must be executed at specified time and dayofweek. But what when I want to have for example relay active from 8:00 to 15:00 every day. Event will do the job at specified moment, when device is running. What if power outage occur, device is resetted,..... in the middle of active period, Default state after reset of relay is for example 0. So even when at 8:00 relay is switched ON, but device is restarted at 9:00 remaining scheduled time frame (till 15:00) relay will be OFF, but should be ON.

This type of event could stay

But for channel related, I would suggest logic block example:

addChannelScheduler [channel #] setChannelEvent [channel #] [time] [dayofweek] [enable/disable] [level] [temperature] [color]

relay will work only with [enable/disable] Single LED [enable/disable] [level] Multi LED (RGB/CW/WW/..) [enable/disable] [level] [temperature] [color]

Logic would need to sweep from 0:00 till 23:59 and determine preset values and update channel when neccessary. Question is how to do it efficient enough to not overload CPU. Also channels logic block should accept button or cloud as override command, and keep last state until next event.

valekCN commented 1 year ago

@openshwprojects valeklubomir and valekCN are all mine, but I needed second fork. But it is still not the solution what I need. Also branching is messing my work. It is hard to keep incomplete work separated from tested features with frequent pulls/fetches from upstream. Many years I worked alone and life was "easier" with keeping order. Just development was slow. I think I have to backup current state, discard all changes and try another way how to do it.....

openshwprojects commented 1 year ago

Ok, I will try to answer your questions now:

How do I handle this with reset? currently, if you power off/power on device at the minute when the event is scheduled, it will skip this event. I have idea how to fix that - just save last NTP time in "flashvars" structure, but this sounds bad, because.... saving every second to flash will wear out flash fast. So I am not sure right now... But this is edge case and it wil happen only if reset occurs at basically the same minute that event is scheduled. Maybe save the time only every 100 seconds or so? To ensure continuity in execution?

I don't think startup command can process multiple addClockEvents, when backlog can be used in command. autoexec.bat is the way for that, short startup command is only for short startup commands

NTP Sync could be an issue. But minor one. current code is designed to handle both "time went to future 100 seconds" and "time went backward" cases. The 100 seconds period could be increased even further at the cost of number of possible loops with checking the array.

What if power outage occur, device is resetted,..... in the middle of active period, I am aware about this issue, and so far I arrived at conclusion that we just assume that it is recommended to use "Save power state" feature so device remembers its state.

but device is restarted at 9:00 remaining scheduled time frame (till 15:00) relay will be OFF, but should be ON. Maybe indeed we could introduce a second mechanism for that.

relay will work only with [enable/disable] Single LED [enable/disable] [level] Multi LED (RGB/CW/WW/..) [enable/disable] [level] [temperature] [color]

There is no need for making LED-specific commands. This is sadly not documented, but when you look at the code, you will see: image maybe we could also add separate "fake" channels for RED, BLUE, ETC. Then we will get a single interface like:

_addPeriodValue [UniqueID] [ChannelIndex] STart_DayOfWeek Start_HH:MM:SS End_DayOfWeek EndHH:MM:SS Value

channelindex for example can be 1 for channel 1 (relay) or for example 130 for LED power on/off or 132 for temperature.... Very nice single point interface!

Logic would need to sweep from 0:00 till 23:59 and determine preset values and update channel when neccessary. you can include days of week here very cheaply (as an option)

Question is how to do it efficient enough to not overload CPU. convert HH:MM:SS to totalSeconds, then you have: startTotalSeconds and endTotalSeconds and then: if(currentDaySecons > startTotalSeconnsd && currentDaySeconds < endTotalSeconds) then period is active. Of course, you also have to handle case when start < end (start is at, for example, 23:30 and end at 00:30)

Also channels logic block should accept button or cloud as override command, and keep last state until next event. THAT one seems problematic, especially if we assume that we support reboot during period. Maybe... give each period an index from 0 to 32. So max 32 periods. Then, in FlashVars (those changed often) use a 32 ibit integer to store it. The integer will be called bPeriodDirty. At period start, given bit is set to 0. When user changes the same channel that is linked to period, the bit is set to 1. When period "sees" that this bit (his bit, periods bit) is set to 1, then it knows that the value is "dirty" (modified by user) and skips the setting. When period ends, it clears the "dirty" bit of his index

So my suggestion would go towards "addPeriodValue" as said above, as a second mechanism, next to "addClockEvent". I have a basic idea how to do what you said.

I also worked alone most of the time, this github account was created for OBK, and that was also with certain delay on my side. Still, please be aware that Github may not like two accs per user (according to their rules), but I don't know how strict the execution of that is.

valekCN commented 1 year ago

How does autoexec.bat work? I need quide.

github point of view: I have 2 different accounts, with different mail address. Only thing conencting it, is my person in the physical world.

valekCN commented 1 year ago

Over mignight interval will be splitted into two: 23:30 -> 0:30 converted to 23:30 -> 23:59 0:00 -> 0:30

Also consider day of week when calculating seconds since 1st day 0:00

valekCN commented 1 year ago

Also I would try to avoid saving some data to flashvars. until it is absolutely neccessary.

openshwprojects commented 1 year ago

Autoexec? This should explain: image if not, then tell me and I will update readme. We really need to work on docs!

I don't think we need to split interval. I think with well thought logic in checking it's not necessary.

Also consider day of week when calculating seconds since 1st day 0:00 Calculating seconds in relation not to the start of day, but in relation of the start of week? Good idea.

Also I would try to avoid saving some data to flashvars. until it is absolutely neccessary. We don't know when device will lose power and I don't think there is a mechanism like "run function at exit", so if we want to know if user overridden period then we need to save...

The override saving cost would be "one flashvars write per one override" which is not much, considering that mechanism for "remember last state" does one flashvars write per saved channel change

valekCN commented 1 year ago

autoexec.bat with lines works

addClockEvent 17:30:00 0xff 1 ToggleChannel 0;
addClockEvent 17:35:00 0xff 2 ToggleChannel 0;
openshwprojects commented 1 year ago

Of coursei t can be also run from console.

I am thinking about those periodicals. https://github.com/openshwprojects/OpenBK7231T_App/commit/928cbb5fc52541740979446447636c91bd9d56c0