Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Alarms #1555

Closed
gfwilliams opened this issue Mar 10, 2022 · 22 comments
Closed

Fix Alarms #1555

gfwilliams opened this issue Mar 10, 2022 · 22 comments

Comments

@gfwilliams
Copy link
Member

gfwilliams commented Mar 10, 2022

The current Alarm system is stupid. We now have:

  • alarm (the default)
  • qalarm
  • hardalarm
  • Plus some other as yet uncontributed forks

They are all almost identical, but all of them have issues, none of them work together, and none sync with Gadgetbridge.

Plenty of apps also implement their own timers, which stop when the app is exited:

  • chronowid (chrono widget)
  • countdowntimer

There are outstanding issues like:

And I've lost track of the hours I've spent trying to debug and maintain the 3 different alarm apps, which I could have spent making real improvements to a single app.

Also it'd be nice to have an API where other apps can query the alarm state, like #1513

So the plan is to:

  • Have a 'core alarm' library that provides an API and well tested, reliable and efficient code trigger alarms, but that doesn't contain any apps/widgets so folks can make their own that depend on it
  • Try and merge features from other apps into the default alarm app, and remove the others.
  • Add Gadgetbridge alarm syncing support
@andrewgoz
Copy link
Contributor

TimerClock is my current clock and it implements its own alarm system unrelated to anything else. It doesn't appear to work with SleepPhaseAlarm, which I assume is designed to work with the default alarm app. A common API would be useful here!

I've been making some changes to TimerClock (no PRs, yet). If I have time I might look into making it compatible with the default alarm app (or whatever SleepPhaseAlarm is trying to do), unless something happens here first!

I think it would be a good idea if alarms required the ID of the app that creates them, so apps could query the global alarm list for 'their' alarms.

@nxdefiant
Copy link
Contributor

Yes, SleepPhaseAlarm checks only the config alarm.json of the default alarm for enabled buzzers.

@gfwilliams
Copy link
Member Author

Yes, SleepPhaseAlarm checks only the config alarm.json of the default alarm for enabled buzzers.

Ok, great - please keep doing that as I'll use alarm.json for this thing.

@andrewgoz great - yes, having an app ID would be great (I think #1513 did that too). And yes, making TimerClock use the built in alarm/timer system when done would be great

@gfwilliams
Copy link
Member Author

There's now a branch for the new alarms at https://github.com/espruino/BangleApps/tree/new_alarm

Maybe you could take a look and see if that does what you need? specifically @peerdavid and @andrewgoz

I think it should be enough to do timers for clocks/etc

'Hard alarm' from Q Alarm should be ok to implement on top of this too - it'd just mean that to switch the 'hard' bit on/off you'd need to run the separate app at the moment

@peerdavid
Copy link
Contributor

Oh wow thank you so much -- I had a first look and the API seems perfect to me. I really love that we are able to set an ID. This weekend I will have some time - so I will integrate and test it into some of my clocks then I can give better feedback :)

Thanks again,
David

@gfwilliams
Copy link
Member Author

Great! It'd be good if you spot anything that's missing.

Also any thoughts about things that can be done to make it less likely someone wants to fork the alarm app in future :) I tried to add the js field to allow custom code to be executed, but there may be other things too.

@storm64
Copy link
Contributor

storm64 commented Apr 1, 2022

I just had a brief look but the new_alarm branch looks awesome.

Here are my thoughts and ideas how to change/improve it even more to reduce the chances of a fork.
I'm referring to the properties of an alarm in alarm.json:

  1. The dow is missing in the README.md.
  2. Add a optional name to be able to remember the purpose and maybe additionally change sorting.
  3. Add a optional vib or pattern to change the vibration pattern, as string or array with on,off,on,... in ms.
  4. Add a optional config to store additional information. Some apps might want to save some data according to the specific alarm.
  5. Move the msg, name and vib into config

@gfwilliams
Copy link
Member Author

Thanks!

  1. Just added :)
  2. I'm not sure I get where/how this would be used? We already have msg
  3. This sounds great - actually I've already seen this code duplicated multiple times so I might make that a library
  4. Actually I guess apps can write anywhere, but I just added an optional data object to the docs which I guess people mnay use
  5. Personally I think app-specific data probably shouldn't be mixed with the built-in stuff. I reckon maybe leave this one for now. Unless there's a good reason, adding extra nesting isn't always good as it'll be slower to execute and use more memory

@storm64
Copy link
Contributor

storm64 commented Apr 1, 2022

  1. The name would be displayed on the alarms/timers list instead of "Alarm"/"Timer" and as title of the alarm prompt.
    Some examples:
    • Work 7:00 -> Alarm at 0700 on weekdays
    • Weekend 9:00 -> Alarm at 0900 on the weekend
    • Washer 2:20 -> Timer with 2h 20min
    • Window 0:05 -> Timer with 5min

4.+5. Sounds reasonable, works for me.

@gfwilliams
Copy link
Member Author

Just added vibration.

Wrt name - Seems like an idea but why couldn't we just display 'msg' there instead of 'name'?

I think maybe leave it for the moment - I don't want to get carried away adding stuff or we'll never actually get this bug-free and finished and merged in. It seems like if it's needed we could easily add name at a later date.

It's not like the app can never change or be added to, and I don't intend to avoid forks by making the Alarm app do everything. Really, I just don't want to make any design decisions that mean people think they have to fork rather than contributing back to the main app.

@dashavoo
Copy link
Contributor

dashavoo commented Apr 1, 2022

I had intended to comment a few days ago but what you've done covers almost everything I wanted to say anyway, I think.

My opinions:

  • vibration shouldn't be one of the keys in alarm.json, but a library would be awesome.
  • There should be an app for the app id as well as id so that an app can find its own entries easily and also distinguish between them
  • Which enables storing message, name, vibration, any other config in a specific file per app.
  • A setting to indicate whether the widget should display for the alarm or not.

(and related to that final bullet point, if I am not mistaken exiting the alarm using the physical button rather than the on screen button can leave the widget showing even if it was timer/non-repeating and will never alarm again.)

@peerdavid
Copy link
Contributor

peerdavid commented Apr 2, 2022

@gfwilliams I just tested the new alarm library in my fork: I updated the lcars, not analog and black&white clock and the simple timer app. I implemented the timers of the clocks such that its optional i.e. if alarm is not installed, then this functionality is simply not provided but the clock can still be used. For the simple timer I used it as a dependency in metadata as the app is useless otherwise.

Overall I really like the API, it feels great that I don't have to re-implement the timer etc. Also everything that I need is provided and easy to use. I (probably) found two little bugs:

  • When I want to check whether the timer is still running it was not sufficient for me to check timeToNext===undefined as it could also be that timeToNext.on is false in case the timer is only disabled. So I guess the documentation should be adapted.

  • When I run a single timer it works fine. But I have some problems if I start a timer (e.g. for 1h), then a second timer which I start and delete afterward -- seems to me that then also the first timer no more works. At least the widget symbol disappears etc. Not sure if this "undefined" in the list of timers (json file) is a problem?

Thank you so much for doing this especially as I really failed to implement such library -- it really really helps a lot and reduces duplicated code for all my apps.

David

@pzo
Copy link

pzo commented Apr 3, 2022

Could the alarm also handle being set on specific dates/times ? Or being recurrent ?
We already have a calendar display app, with alarms on specific days there shouldn't much left to implement to have an organiser.

@dashavoo
Copy link
Contributor

dashavoo commented Apr 3, 2022

Could the alarm also handle being set on specific dates/times ? Or being recurrent ? We already have a calendar display app, with alarms on specific days there shouldn't much left to implement to have an organiser.

I was wondering about this over the weekend. Specific dates would be useful, or days of months rather than days of week. Should the library be separated out of the default alarms app and be a more general scheduling library? Essentially a Bangle cron.

What if the library, boot code and widget were one thing, with the alarm app separate? Putting a field in the file along the lines of "isAlarm" could control whether the alarm icon shows (you probably don't want to show it for every scheduled thing, only alarms and timers).

@gfwilliams
Copy link
Member Author

I want to check whether the timer is still running it was not sufficient for me to check timeToNext===undefined

Not entirely sure I understand - so if timer.on=false, timeToNext===undefined ? Or is timeToNext still set even when the timer is off?

I have some problems if I start a timer (e.g. for 1h), then a second timer which I start and delete afterward

Please could you paste up some example code? Is it possible the same ID was used? In which case the new timer would overwrite the old one?

Could the alarm also handle being set on specific dates/times ? Or being recurrent ?

Good point - I'd say being recurrent is probably a step too far (since then you're considering day/week/month/etc), but we could have an optional date field which we check? It would be nice to be able to have calendar events handled with the same code, and when the calendar app gets called from the alarm it could recalculate the date of the next one.

Should the library be separated out of the default alarms app and be a more general scheduling library?

Yes, I was wondering about that. It would definitely be nice to be able to replace the default alarm 'app' easily. Maybe just an app called sched or similar?

Putting a field in the file along the lines of "isAlarm" could control whether the alarm icon shows

Yes, good idea.

@gfwilliams
Copy link
Member Author

Ok, I've now refactored it into a new library called sched, added an optional date and hidden options.

But in my opinion that's probably about ready.

Any thoughts about things like Q Alarm? I had a quick look and I could port them over (it'd basically just be a clone of the 'alarm' app with an added 'hard' mode) but honestly I wonder if it's worth all the effort.

Perhaps things like the Chrono widget we could actually just strip it right back, delete the app and turn it into a simple widget that displayed the time until the nearest alarm went off.

@peerdavid
Copy link
Contributor

peerdavid commented Apr 4, 2022

Hi @gfwilliams thanks for your answer. Here are the steps to reproduce the problem -- I execute all 3 comments to simulate what happens if I add timer 1, add timer 2 and delete timer 2:

require('sched').setAlarm("timer1", {timer : 1*60*1000,});
alarm.reload();

require('sched').setAlarm("timer2", {timer : 1*60*1000,});
alarm.reload();

alarm.setAlarm("timer2", undefined);
alarm.reload();

I would expect that "timer1" fires after 1 minute, but this never happens. Also I have seen that the icon (widgets) was no more shown after executing the last command. Here is an output of my json file as well as a screenshot of the bangle (no alarm icon):

sched

sched2

Let me know if I can do something else to help :)

David

@gfwilliams
Copy link
Member Author

Let me know if I can do something else to help :)

Excellent, thanks! That's all I need I think - I'll check it out now

@gfwilliams
Copy link
Member Author

Ok, I'm pretty sure it's sorted if not try now. What does everyone think - ok to merge?

the actual error seems to be caused by the 'undefined' at the end:

>require("Storage").readJSON("sched.json")
Uncaught SyntaxError: Expecting a valid value, got undefined
 at line 1 col 78 in sched.json
..."t":40122000,"ot":39522000},undefined]

That itself was a bug, but looks like Espruino's JSON.stringify didn't convert undefined->null as it is supposed to (just fixed that too), and that could have caused errors like this all over

@dashavoo
Copy link
Contributor

dashavoo commented Apr 5, 2022

I still think there should be an appid field in addition to the id field.

I would also be inclined to slim it down to the essentials and let apps handle any additional data separately as I mentioned above - if apps start putting a lot into data {} it could get big. Isn't it better to have the bare minimum in sched?

In terms of doing the scheduling, I think everything is covered. I think this will open up a lot of possibilities.

@peerdavid
Copy link
Contributor

@gfwilliams I just tested it on my watch and it works fine now. Thank you so much!

@gfwilliams
Copy link
Member Author

I still think there should be an appid field in addition to the id field.

Just added docs for this, but it doesn't need extra code.

I really don't think adding a separate file per app is going to be a great idea. If someone's actually going to do something crazy then yes, they can do and store whatever they want in their app.

But if someone just wants to store a number or two it's not going to matter. The vibration is something that's built in and I can totally see you might want to have different alarms with different vibration patterns so I think it makes a lot of sense to keep.

Just merged this with master - seems good enough for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants