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 linkConstructing a Schedule
A vehicle schedule policy begins by choosing a default value for shouldCharge
, typically false
.
{
"defaultShouldCharge": false
}
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"
}
}
The policy then specifies 0 or more rules that override the value of shouldCharge
within certain timespans and situations:
{
"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]
}
]
}
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.
Each rule specifies a value for shouldCharge
and at least one filter. A filter restricts the times and situations to which the rule applies.
{
"shouldCharge": true,
"hourMinute": {
"from": "01:00",
"to": "09:00"
},
"weekdays": [5, 6]
}
Copy linkSupported Filters
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 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
{
"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]
},
// charge anytime on saturday
{
"shouldCharge": true,
"weekdays": [5]
},
// two windows on Sunday
{
"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 linkBehavior across day/rule boundaries
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)
Reading 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 linkSchema of the Schedule Status object
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
. If it cannot be achieved, that is the state MISALIGNED
.
{
"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. |
PENDING | The target's scheduled property is currently transitioning to the expected state. |
INACTIVE:OVERRIDDEN | Schedule is inactive because an External Start has been created. Read more at the vehicleAPI or chargerAPI External Start APIs. |
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.