Extracting start and stop times from the email
In my last post I said one of the improvements I wanted to make to my solar panels automation was to “Parse the Octopus free electricity email to extract the start and end time and set the timers in Node-RED without any manual intervention.”. I’ve now done this and this short post explains how I did it.
Reading the email
The start and stop times are in the subject of the email from Octopus. When this email arrives in my gmail account, I simply extract the full subject text into an attribute of the sensor I set for this event.
Setting and using the start and stop times
With the full subject text now available to Home Assistant, I can extract the start and stop times and use this to switch devices on and off accordingly. Unfortunately the start and stop times use the 12 hour clock (with am and pm) so it’s slightly harder than it might be. In the end, I decided to use a NodeRED function node and Javascript to do the work. Note the heavy use of incomprehensible regex!
Basically, on receipt of the email from Octopus, the code below calculates the number of milliseconds from “now” to the start and stop times.
//
// This calculates the number of milliseconds from "now" to the start and end times as
// provided in the Octopus Energy Power Ups email which looks like:
// "Power-ups: Opt in to Power up for free at 1:02 PM - 10:30 PM, Wednesday 31/01/24"
// [This version assumes the free power will always be "tomorrow" so ignores the date.]
//
var s = msg.data.event.new_state.attributes.subject; // The subject text of the power up email
// Extract the two times in the subject which are the start and end times respectively
let times = s.match(/((1[0-2]|0?[1-9]):([0-5][0-9]) ?([AaPp][Mm]))/g);
// Get the current time and date and extract some attributes we need to calculate the delays
const now = new Date()
let msecs_1970_to_now = now.getTime()
let year = now.getFullYear()
let month = now.getMonth()
let day = now.getDate() + 1 // Tomorrow!
let [hr_s, min_s, ap_s] = times[0].toLowerCase().match(/\d+|[a-z]+/g) || []; // Extract each element of the time (hh, mm, AM/PM)
hr_s = `${(hr_s % 12) + (ap_s == 'am' ? 0 : 12)}` // Convert first (AM/PM) hour to 24 hour clock
let [hr_e, min_e, ap_e] = times[1].toLowerCase().match(/\d+|[a-z]+/g) || []; // Extract each element of the time (hh, mm, AM/PM)
hr_e = `${(hr_e % 12) + (ap_e == 'am' ? 0 : 12)}` // Convert second (AM/PM) hour to 24 hour clock
// Use the current time attributes determined above to get the javascript time for the start & end times tomorrow and as msecs
const start_time = new Date(year, month, day, hr_s, min_s);
const end_time = new Date(year, month, day, hr_e, min_e);
let msecs_1970_to_start_time = start_time.getTime();
let msecs_1970_to_end_time = end_time.getTime();
// Calculate the time delay from now to the start & end times in msecs and put in msg fields
msg.start = msecs_1970_to_start_time - msecs_1970_to_now + 60000; // Start a minute late to be on the safe side
msg.end = msecs_1970_to_end_time - msecs_1970_to_now - 60000; // End a minute early to be on the safe side
msg.topic = "START";
msg.delay = msg.start; // The wait NodeRED node requires this field in millisecs
node.send (msg); // send a message to be used to trigger the start
msg.topic = "END";
msg.delay = msg.end;
return msg; // send a message to be used to trigger the end
This code sends two messages with the following self-explanatory properties:
msg.topic is either “START” or “END”
msg.delay is the number of milliseconds until the start or end time of the free period
Note I calculate a delay rather than an absolute time as I use a NodeRED delay node to then trigger the actions I want (I couldn’t find a suitable node that would trigger at an absolute time using an input message).
No automated charging for free
This now allows me to maximise my use of free electricity. However, I still can’t automatically set my solar panels to be charged from the grid during these free power periods. I’m currently working on this and hopefully will post an update on this shortly. Ironically my solar panels use absolute times for setting when they can be charged from the grid!