Scheduling
A Schedule policy targets a specific device (vehicle/charger/HVAC) at a particular Location. It describes whether the target should be charging at any given time, or in the case of HVACs, what the holdType
, mode
, coolSetpoint
or heatSetpoint
should be. These target states are specified as shouldCharge
and targetState
, respectively.
Hardware kind | Scheduled properties |
---|---|
Vehicle | shouldCharge |
Charger | shouldCharge |
HVAC | holdType , mode , coolSetpoint , and heatSetpoint |
Copy linkAnatomy of a Schedule
Copy linkVehicles and chargers
A schedule policy for vehicles and chargers begins by choosing a default value for shouldCharge
, typically false
.
{
"defaultShouldCharge": false
}
The policy then specifies 0 or more rules that override the value of shouldCharge
. Each rule should contain a (filter)[#supported-filters] that specifies the situations when the rule should apply.
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "04:00"
},
"weekdays": [0, 1, 2, 3, 4]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "09:00"
},
"weekdays": [5, 6]
}
]
}
Copy linkHVACs
HVAC schedules first target either a holdType
of SCHEDULED
or PERMANENT
. A thermostat in a PERMANENT
hold type is configured to keep the current settings for mode
, heatSetpoint
, and coolSetpoint
(referred to as "mode settings" from this point forward) until the next command is sent to the device. A thermostat in a SCHEDULED
hold type follows a program set in the OEM's app. This program is not accessible through Enode, but the changes it makes to the mode settings are.
{
"defaultTargetState": {
"holdType": "SCHEDULED"
}
}
Like with vehicles/chargers, you specify 0 or more rules that override the target state. Each rule should contain a (filter)[#supported-filters] that specifies the situations when the rule should apply.
For example, an HVAC policy may wish to override the thermostat's program during certain periods of the day. This could be achieved by sending the following schedule to Enode.
{
"defaultTargetState": {
"holdType": "SCHEDULED"
},
"rules": [
{
"from": "01:00",
"to": "04:00",
"targetState": {
"holdType": "PERMANENT",
"mode": "HEAT",
"heatSetpoint": 20
}
}
]
}
This instructs the HVAC to follow the program on the device, except for hours 1 through 4. During this time, the thermostat will heat to at least 20 degrees.
Copy linkSupported Filters
Enode Schedules support a common set of rule filters across all asset types. A filter restricts the times and situations to which the rule applies.
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "09:00"
},
"weekdays": [5, 6]
}
Key | Description |
---|---|
hourMinute | Pair of clock times Time Zone Interpretation for Different Assets:
|
fromTimestamp | UTC timestamp (inclusive) from which this rule should apply. |
toTimestamp | UTC timestamp (exclusive) until which this rule should apply. |
weekdays | An array of weekdays to which this rule should apply. A weekday starts with 0 for Monday and ends with 6 for Sunday. |
Copy linkCreating Schedules
You should createAPI or updateAPI a Schedule in our API as soon as you know what the schedule will be.
Edge cases:
- If you create or update a Schedule a short time before a rule is set to apply, Enode will still do our best to get the target into the desired state for the period specified in the rule, though there may be a delay.
- Consider a Schedule that was created at 9:58:00 that contained a rule to start charging a vehicle at 10:00. The vehicle may actually start charging at 10:05.
- If you create or update a Schedule after the start period of a rule, Enode will still do our best to get the target into the desired state for the period specified in the rule, though there may be a delay.
- Consider a Schedule that was created at 10:30:00 that contained a rule to start charging a vehicle at 10:00. The vehicle may actually start charging at 10:35.
Copy linkExample Vehicle/Charger Policies
Copy linkAlways charge when possible
This is the typical default behavior of EVs and is equivalent to a null policy:
{
"defaultShouldCharge": true,
"rules": []
}
Copy linkPrevent any charging until a future time
{
"defaultShouldCharge": true,
"rules": [
{
"shouldCharge": false,
"toTimestamp": "2020-01-07T16:21:76Z"
}
]
}
Copy linkOnly charge between 01:00 and 06:00 each day
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
}
}
]
}
Copy linkOnly charge between 01:00 and 06:00 each work day, and any time on weekends
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
}
},
{
"shouldCharge": true,
"weekdays": [5, 6]
}
]
}
Copy linkSet a custom charging window for every day of the week
This example shows one charging window for every day of the week, except for Saturday (which can charge at any time) and Sunday (which has two charging windows).
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
},
"weekdays": [0]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "22:00",
"to": "04:00"
},
"weekdays": [1]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "02:00",
"to": "09:00"
},
"weekdays": [2]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
},
"weekdays": [3]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
},
"weekdays": [4]
},
{
"shouldCharge": true,
"weekdays": [5]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "06:00"
},
"weekdays": [6]
},
{
"shouldCharge": true,
"hourMinute": {
"from": "12:00",
"to": "15:00"
},
"weekdays": [6]
}
]
}
Copy linkExample HVAC Policies
Copy linkTarget 20° during the day, and 15° at night
{
"defaultTargetState": {
"mode": "AUTO",
"heatSetpoint": 18,
"coolSetpoint": 22,
"holdType": "PERMANENT"
},
"rules": [
{
"targetState": {
"mode": "AUTO",
"heatSetpoint": 14,
"coolSetpoint": 16,
"holdType": "PERMANENT"
},
"hourMinute": {
"from": "23:00",
"to": "06:00"
}
}
]
}
Copy linkTarget 20° during the day, 15° at night, and 7° until January 7, 2020
{
"defaultTargetState": {
"mode": "COOL",
"coolSetpoint": 20,
"holdType": "PERMANENT",
},
"rules": [{
"targetState": {
"mode": "HEAT",
"heatSetpoint": 15,
"holdType": "PERMANENT",
},
"hourMinute": {
"from": "23:00",
"to": "06:00"
},
{
"targetState": {
"mode": "AUTO",
"heatSetpoint": 6,
"coolSetpoint": 8,
"holdType": "PERMANENT",
},
"toTimestamp": "2020-01-07T00:00:00",
}
}]
}
Copy linkTarget 15° between 23:00 and 06:00 each work day and until 08:00 on weekends
{
"defaultTargetState": {
"mode": "AUTO",
"heatSetpoint": 18,
"coolSetpoint": 22,
"holdType": "PERMANENT"
},
"rules": [
{
"targetState": {
"mode": "AUTO",
"heatSetpoint": 14,
"coolSetpoint": 16,
"holdType": "PERMANENT"
},
"hourMinute": {
"from": "23:00",
"to": "06:00"
}
},
{
"targetState": {
"mode": "AUTO",
"heatSetpoint": 19,
"coolSetpoint": 21,
"holdType": "PERMANENT"
},
"hourMinute": {
"from": "06:00",
"to": "08:00"
},
"weekdays": [5, 6]
}
]
}
Copy linkSchedule behavior and edge cases
Copy linkExternal interference
Your users may interfere with a Schedule: for instance, if your Schedule stopped a vehicle from charging, your user may open their EV app and restart charging manually. Whenever this happens, Enode will try to get the target back into its expected state. If we are not able to, the Schedule Status's state will be MISALIGNED
.
Copy linkClock times can cross midnight
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "22:00", // If this is 22:00 on a Monday...
"to": "06:00" // ...then this is 06:00 on a Tuesday
}
}
]
}
Copy linkA rule is applied only during the intersection of all filters
With the following configuration:
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "22:00",
"to": "06:00"
},
"weekdays": [0]
}
]
}
This rule only applies from 22:00 - 05:59 on the clock. Additionally, it only applies on Mondays. Thus:
- Monday 00:00-05:59 -
shouldCharge: true
(inside 22:00-06:00, inside Monday) - Monday 21:00 -
shouldCharge: false
(outside 22:00-06:00) - Monday 22:00 -
shouldCharge: true
(inside 22:00-06:00 and inside Monday) - Tuesday 01:00 -
shouldCharge: false
(inside 22:00-06:00, but outside Monday)
Copy linkWhen rules overlap, the latter one has precedence
{
"defaultShouldCharge": false,
"rules": [
{
"shouldCharge": true,
"hourMinute": {
"from": "02:00",
"to": "10:00"
}
},
{
"shouldCharge": false,
"hourMinute": {
"from": "08:00",
"to": "09:00"
}
}
]
}
- 00:00 -
shouldCharge: false
- 02:00 -
shouldCharge: true
- 08:00 -
shouldCharge: false
(inside 02:00-10:00, but also inside 08:00-09:00, which was defined later in the array) - 09:00 -
shouldCharge: true
(inside 02:00-10:00 only)
Copy linkReading the current status of a Schedule
Every Schedule has a status object that describes the current status of its execution.
Copy linkReceiving the Schedule Status object
This object can be obtained at any time via the Get Schedule StatusAPI request.
It is also sent via webhook every time any of its values change, using the event user:schedule:execution-updated
Copy linkAnatomy of a Schedule Status
Remember that Schedules are all about scheduling a shouldCharge
value, which is just one part of whether a target is expected to be charged. For example, if a Vehicle is scheduled to be charging but is out driving on the road, it will not be charging. This is not a failure or problem from the scheduling point of view.
The scheduler combines the following properties to decide whether a target is expected to be charging:
needsCharge
- Does the target want to charge?isPluggedIn
- Is the target connected to allow charging?shouldCharge
- Do the schedule rules dictate that the target should be charging?
If all are true, the target is expected to be charging. If any are false, the target is not expected to be charging. Therefore, the execution engine always strives to keep the target's isCharging
value equal to the expected value. This state where this is achieved is called ALIGNED
.
The Schedule's state is MISALIGNED
whenever the expected state cannot be achieved. This can happen if the vendor APIs are down or have some other error. When a Schedule is MISALIGNED
, Enode will not attempt to re-align the schedule until the next expected state transition, as specified in upcomingTransitions
.
{
"scheduleId": "8d90101b-3f2f-462a-bbb4-1ed320d33bbe",
"changedAt": "2019-08-24T14:15:22Z",
"state": "ALIGNED",
"isCharging": false,
"isChargingExpected": false,
"isChargingExpectedParts": {
"needsCharge": true,
"isPluggedIn": true,
"shouldCharge": false
},
"upcomingTransitions": [
{
"at": "2020-04-08T02:00:00Z",
"shouldCharge": true
},
{
"at": "2020-04-08T06:00:00Z",
"shouldCharge": false
}
]
}
The state
field always has one of the following values:
Key | Description |
---|---|
ALIGNED | The target's scheduled property is in the expected state. |
MISALIGNED | The target's scheduled property is stuck in an unexpected state. Enode will not make any further attempts to get the target into the expected state. Look at the Schedule Status's upcomingTransitions list to understand the next opportunity for the schedule to become aligned. |
PENDING | The target's scheduled property is currently transitioning to the expected state. |
INACTIVE:OVERRIDDEN | Schedule is inactive because a Smart Override has been created. Learn about creating overrides in our API ReferenceAPI. |
INACTIVE:DISABLED | Schedule is inactive because its isEnabled property is false . |
INACTIVE:AWAY | Schedule is inactive because its target is away from the configured Location. Only applicable to schedules targeting vehicles because we don't want to apply an optimization schedule to a location where the user does not pay for electricity. Schedules targeting HVACs or Chargers won't enter this state. |
INACTIVE:INCAPABLE | Schedule is inactive because its target is incapable of receiving charging actions. |
The upcomingTransitions
field returns up to 2 upcoming transitions of the shouldCharge
field.