Projects

Random Timing

A scheduler with built-in Randomisation

Ashley Woods

Issue 77, December 2023

A scheduling tool that automates turning lights and devices on and off around your home in a more human-like way. - by Ashley Woods.

When it comes to automatically turning lights on and off around the home, we can be spoilt for choice. Tools such as Home Assistant, the Tuya platform, LIFX and the like all offer schedules where we can control smart devices like lights and sockets right down to the minute.

Such home automation may be a simple convenience to have the lights on when we arrive home in the evening, or it may be designed to make the house appear occupied to deter potential intruders.

While these scheduling tools can control events down to the minute, sometimes we want a more random sequence with lights turning on and off at slightly different times of the day or possibly not even operating on some days.

Existing scheduling tools may not offer this degree of randomisation and this desire for randomisation became the inspiration for Temere. The name comes from Latin, where one of its translations is “random, or by chance”, which seemed like a suitable name for such a system.

Background

Temere is designed to be a scheduler with built in randomisation. A schedule can be prepared to turn a smart light on between say 6PM and 7PM and leave it on for about an hour, and do this slightly differently on subsequent days, or possibly skip a day here and there, and turn on earlier at weekends and run for longer.

All of the schedule attributes of operating days, turn on time and duration can be seeded with variable amounts of randomisation to end up with a more human-like pattern of lights being turned on and off.

Smart devices all offer some form of API. At the most basic level this can turn a device on or off. More advanced smart lights offer an API which can dim the light, set colour or other attributes. Temere uses Python scripts which call the respective API to control the smart device.

With its built-in randomisation, Temere determines exactly when to run such scripts. In this way, Temere is designed to integrate with the likes of Home Assistant and the Tuya Cloud.

Control of the specific smart light or smart socket may be via the Internet to the cloud provider (such as Tuya) or via a direct local connection to the device (also such as Tuya), or via Home Assistant.

Elements of Temere

Temere is made up of a number of software components including the following:

  1. MySQL database with a number of tables (These are summarised below).
  2. PHP web front end which provides the user interface to Temere.
  3. Several python scripts to process the data and control the devices (These are also summarised below).
  4. Home Assistant is not necessary, but if it is available, then use the Temere to HA integration as it is easy to set up.

Our instance of Temere runs on a hosted virtual server running CentOS. Most of the smart devices are Grid Connect devices sourced from the big hardware store. These are white label Tuya devices which are registered with Tuya and controlled via the Tuya Cloud.

All Python scripts run in a virtual environment on the server. This was done to remove any potential conflict with other Python scripts which also run on the same server.

The MySQL database contains the following tables:

  1. Devices table defines each smart device. These can be lights, sockets or similar smart devices from any manufacturer where an API is available to control the device.
  2. Controls table contains all the configuration needed to control a specific device. Each device may have multiple controls.
  3. Schedule table contains the schedules for each device. This includes the switch on and switch off time as well as the amount of randomisation applied to the schedule. Each device may have multiple schedules.
  4. Sequence table contains the exact turn on and turn off timings for every device for every day in the month.

The following Python scripts provide internal processing or control devices:

  1. Planner script reads records from the schedule table, builds in the randomisation and outputs records to the sequence table.
  2. Conductor script runs under the control of cron, reads records from the sequence table to determine what events are due and calls the appropriate control script to control the device.
  3. Various Device Control scripts, which are specific to the type of control needed. We use one script for publishing MQTT messages for Home Assistant and another for calling the Tuya API to control devices via the Tuya cloud. These all use replaceable command line parameters to pass the device specific information.

The following diagram shows the relationship between the various components of Temere.

Our implementation uses a mix of local and cloud hosted components. The Temere server and the Mosquitto MQTT broker used by Home Assistant are both cloud hosted (on different Linux servers). Home assistant is running on a local Raspberry Pi. Home assistant is configured to use the external MQTT broker rather than the instance that can be installed on Home Assistant. This means our user interface to Temere connects over the Internet which allows control from anywhere. The alternate implementation with all components hosted locally will also work. The only constraint is that Temere must be able to connect to the broker if you wish to control Home Assistant. This is complicated if the broker is inside a firewall and Temere is outside the firewall. So, the simplest option is to host all components locally; as separate Raspberry Pi devices, virtual machines or in a Docker container.

How it Works

The real essence of Temere is the randomisation element introduced within the system. This randomisation is configured in the Schedule, which is the main user interface page. This home page for the scheduler is shown here.

Two different Schedules are available: one for weekdays and one for weekends.

Randomisation

Randomisation is introduced in the following three places.

Trigger Weighting

Trigger Weighting controls how many days within the week or within the weekend, the device will be controlled. This is set as a percentage from zero to 100. The higher the setting, the more likely a device will be controlled on a particular day.

The actual day of the week or day of the weekend cannot be specified, however, setting a Trigger Weighting of 60 on a weekday schedule means the device will be controlled about three days out of five.

As with any randomness, this will vary, but over the full month it is likely to average out. Setting a Trigger Weighting of 100 means the device will be controlled every day of the week or weekend.

In the example, the Hall Light is scheduled at 50% which means it will come on two or three days in the week.

<1h>Switch On Flex

Switch On Flex is configured in minutes. It defines the random delay added to the configured Switch On Time.

In the example, the Hall Light Switch On Time is set for 18:00 and the Switch On Flex is set to 30 minutes. Therefore, the actual switch on time will be somewhere between 6PM and 6:30PM. This random delay will vary each day.

Duration Flex

Duration Flex is also configured in minutes. It defines the random amount of time added to the Duration (which is also configured in minutes).

In the example, the Hall Light is configured with a duration of 240 minutes, with a Duration Flex of 60 minutes, so once this light switches on, it will remain on for somewhere between four and five hours.

Multiple Schedules can be prepared for the same device, but an overlapping schedule cannot be set to active until the conflict is resolved.

Planner Script

Once the Schedule is set up, the Planner script is run. This can be run manually but is automatically run each month when the month is detected as changed.

The Planner does the following:

  1. It reads each record in the Schedule table and generates the corresponding records in the Sequence table.
  2. The Sequence is prepared for the current month. It will contain all the turn on and turn off events for every device for the complete month. The randomisation discussed above is introduced in this process. This results in a Sequence with the actual turn on and turn off times defined to the minute.
  3. Once the Sequence is generated, the exact timing for every device is known. Events are always created in pairs, with a turn off event matching every turn on event. These two events are associated in the database by a Cycle ID so the matching event pairs can easily be tracked.
The following image shows a partial dump of the Sequence table based on Schedule ID 101 from the above Hall Light example.

This shows the result of the various pieces of controlled randomness. Note the following in this Sequence.

  1. Events for all days prior to the current date are purged from the table as soon as they are created so they are not shown here.
  2. The Trigger Weighting of 50 has created eight cycles, which is close enough to 50% of the weekdays between 10 September and 30 September.
  3. The turn on time varies between 18:06 and 18:30, as dictated by the turn on flex value of 30.
  4. The turn off time varies from 22:29 to 23:10, as dictated by the duration plus the duration flex.
  5. Every time the Planner runs to rebuild the sequence, a new batch number gets created and assigned to the new sequence records.
  6. A unique Cycle ID is also generated to tie together the corresponding switch on and switch off event pairs.

  7. Old sequence records normally get purged during the rebuild process, however any cycle which is in progress will be retained. This avoids the possibility of leaving a light turned on because the turn on event has triggered, but the corresponding turn off event gets deleted during a sequence rebuild.
  8. As the Conductor processes due events, it will update the relevant sequence record to show the actual time of the event. As the Conductor is launched by cron, we may choose to run the Conductor with any granularity. If cron runs the Conductor (say) every five minutes, then some additional delay (up to four minutes) will be introduced between the sequence on or off time and the actual on or off time. This can be avoided by running the Conductor via cron every one minute.
The Devices table and the Controls table define the controlled devices and how each device is controlled.

These aspects of the overall configuration have been separated because each device may have several means of control. For example, the Hall Light in the above Schedule is a Grid Connect device which is configured in the Tuya Cloud as well as in Home Assistant. It can be controlled by both systems.

By defining two separate Controls for the same device, we can easily select an alternate control for a device. The Control defines what control script gets called by the Conductor and what parameters get passed to this control script.

For example, the Hall Light can be controlled by Home Assistant by publishing a MQTT message containing the topic and the payload, whereas the same light can be controlled via the Tuya API by sending a device ID and the desired state. The configuration to define which control method to use is set in the Devices table.

Several iterations of this design were tested, and while this approach is a little more complicated it offers the best flexibility.

Creating a New Device Schedule

Setting up a new device in Temere requires several steps. These are shown in the following diagram.

The configuration for Devices and Controls is very closely coupled, with the following dependencies in both directions.

  1. A Device cannot be fully defined until at least one control is defined for the device.
  2. A Control cannot be fully defined until the Device it supports is defined.

The correct workflow is to create a new device with just the device name and related metadata, build the control and select the device it supports, then return to the device and select the desired control. This process ensures only the appropriate working controls are associated with a device.

Once the device and the controls have been created and the device control script created, the device test function can be used to confirm the operation. The test functions are accessed from the Manage Devices page. This can be seen in the following screenshot.

As can be seen, only active devices can be tested. The ON and OFF functions call the configured python control script to directly control the device. This is the same script called by the Conductor when it runs.

All activity from PHP and Python is logged. This can be a useful troubleshooting tool.

The following shows a snippet of the Conductor log, where one event has been selected to process.

Temere in Operation

The following types of devices have been used with Temere.

  1. Selected controllable entities in Home Assistant. This includes smart lights and smart sockets. These are controlled by defining a new MQTT Automation in Home Assistant. This new automation will subscribe to a chosen topic. Temere will then run the appropriate Python control script to publish a message on the topic and the light or socket will turn on or off. This is a very simple process and has emerged as the preferred approach for controlling devices due to the simplicity.
  2. Tuya devices which are registered with Tuya Cloud. Tuya offers a white label service for several different brands of home automation devices. We use several Arlec Grid Connect Smart Sockets and several Arlec Grid Connect LED ceiling lights; all of which are registered with the Tuya Cloud. The Tuya API can be used to control these devices via a python script.

The simplest way to set this up in Home Assistant is to create a pair of new MQTT Automations for each light or socket; one to turn it on and one to turn it off. We use the topic “miaw/lights/hall_light” to control the hall light and the payload of “0” to turn it off or “1” to turn it on.

The following shows the YAML for this specific automation as shown in the YAML editor in Home Assistant.

This requires a Python script with the topic and the payload specified as command line parameters which are extracted from the Control definition held in Temere.

At present, each device in Home Assistant uses a pair of automations; one for turn on and one for turn off. This could be simplified by using just one automation to control all entities and passing the entity and the desired state in the

MQTT payload. This will require a template or a script in Home Assistant and is a topic for future development. As it is trivial to set up new automations in Home Assistant, this effort is parked for the moment.

Tuya control works in a similar way but is a little more complex. We leverage work done by others, especially the very powerful “tinytuya” library which really simplifies connecting to the Tuya cloud. This provides a wrapper around the complexity of making a HTTP request to the Tuya Cloud using the underlying Tuya API.

Regardless of whether the end device is controlled through Home Assistant or Tuya Cloud, or any other API controllable smart device the setup is the same. The name of the script and the required parameters to pass to the script are all defined in the Temere database. This allows the scripts to be quite generic and reusable for multiple similar devices.

Scheduling for these lights can then be removed from the vendor tools and be controlled only by Temere. The state of the light will still be shown by Home Assistant or by the LIFX or Tuya or whatever platform, but the timing of switch on and switch off will be controlled by Temere. Temere does not monitor the state of a device as this is done very well by other tools. Temere adopts a “fire and forget” approach. Automations triggered by events in platforms such as Home Assistant will still execute, but Temere will pseudo-randomly control lights. In this way Temere is intended to complement existing home automation tools.

Future Work

A number of extensions are already envisaged for Temere. These include the following.

Either updating or building a new Schedule user interface to permit creation of single events in the Sequence. At present the Sequence always has a pair of events; one for switch on and a corresponding switch off event. Some events, such as triggering a backup do not require a pair of events. The architecture and flexibility of the Sequence Table and the cron driven Conductor mean this extension would be straightforward to implement. While this could be done using just cron, Temere centralises all this configuration.

The current interface to Home Assistant requires a separate automation for each event. These are trivial to duplicate and edit, however, a single automation which subscribes to a generic MQTT topic and parses the MQTT payload to extract the Home Assistant entity and desired function would provide easier scalability. Once the automation was set up in Home Assistant a new device could be added to Temere, with the appropriate entity ID copied from Home Assistant and the control should work. This requires some work in Home Assistant as well as in the HA control script, but no change in Temere itself.

At present the Schedule simply turns things on and off. Some lights also offer colour options and brightness options. These are not currently controlled by Temere so any light turned on by Temere will generally turn on at the same colour and brightness as it was when last turned off. These extra features of selected lights could be managed by Temere so that such lights could be turned on with a known brightness and colour.

Getting Temere

Temere is available from GitHub at the following link:

https://github.com/ajw2060/Temere

About the author

Ashley Woods lives on the family property in South East Queensland, where he runs a small herd of beef cattle. In a previous career, he lived in Sydney and worked as an Infrastructure Architect for a multinational IT company. He is an occasional contributor to DIYODE Magazine, where his projects integrate Agriculture and IoT to streamline farm operations.