DrMemCS / drmem

Full source tree for the DrMem control system
MIT License
3 stars 4 forks source link

Reimagine the `time-of-day` driver #98

Closed rneswold closed 5 months ago

rneswold commented 5 months ago

Motivation

I don't like the time-of-day driver:

To illustrate the second point: I want a light to be on after 5:30 pm. With the tod driver, the logic block has to monitor the minute and hour devices. Those devices' values currently need to be read from different channels. When the time goes from 5:59 to 6:00, it could be that the minute's channel changes from 59 to 00 first, which means the logic block will perform calculations for 5:00pm and turn off the light and then immediately get the hour update yielding 6:00 and turn them on again. The users would see this as the lights briefly changing at the wrong time.

The time-of-day should be removed as a driver and, instead, be made an async task that posts the time-of-day to a broadcast channel. Logic blocks can use the channel, if they need time-of-day.

Tasks

Logic blocks:

rneswold commented 5 months ago

These are a few ideas as to how we refer to time in logic block expressions.

Treat as Devices

We could leave the grammar alone and, instead, have specially named devices to refer to the time values. For instance, seconds in UTC time could be a utc:second device name. The user would add all the required time devices to the inputs map and the expression handler would just work.

Although this would require the least amount of work, it's my least favorite because I don't like having special values. They consume a small part of the device name space. They are also a useful name that someone may want to use for a hardware clock.

Add Grammar Syntax

  1. We could add some syntax to the grammar. Expressions can only have simple identifers from the inputs map, so there are no device names in the expressions. This allows us to use the device notation for time values: utc:second or local:hour, for example.
  2. We could use a function notation: second(UTC) or hour(LOCAL).
  3. We could use method notation: utc.second() or local.hour().
  4. Maybe a "substitution" notation: $UTC_SECOND$ or $LOCAL_HOUR$.
  5. We already use curly braces to substitute inputs. Maybe combine this with the first option: {utc:second} or {local:hour}, for example.

Any of these would require scanning expressions to see if the receive handle needs to be saved and awaited upon.

Of these, I think I prefer option 5. The curly braces are a similar use for devices, so we're not using a different notation for built-in devices. It uses the device naming scheme which can't conflict because external devices have to be specified in the inputs map and their lookup name can't have colons.

Common Effort

There would be some work in knowing how to access the time devices. All the time values, UTC and local, arrive in one message so all the fields change at once. If an expression uses more than one time field, it should only update the expression once (since all the fields have already changed) and it should see the new values of all the field in its calculation.