Skip to content

Commit

Permalink
feat(thermostat): Add support for dual-setpoint thermostats
Browse files Browse the repository at this point in the history
  • Loading branch information
csuermann committed Mar 28, 2024
1 parent 9820452 commit eacf32c
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 27 deletions.
23 changes: 23 additions & 0 deletions device-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,29 @@ const types = {
},
decorator: defaultDecorator,
},
THERMOSTAT_2: {
defaultState: {
temperature: 0,
scale: 'CELSIUS',
lowerSetpoint: 0,
upperSetpoint: 0,
lowerSetpointScale: 'CELSIUS',
upperSetpointScale: 'CELSIUS',
thermostatMode: 'OFF',
powerState: 'OFF',
},
validators: {
temperature: temperatureValue,
scale: temperatureScale,
thermostatMode,
lowerSetpoint: wrapValidator(temperatureValue, 'lowerSetpoint'),
upperSetpoint: wrapValidator(temperatureValue, 'upperSetpoint'),
lowerSetpointScale: wrapValidator(temperatureScale, 'lowerSetpointScale'),
upperSetpointScale: wrapValidator(temperatureScale, 'upperSetpointScale'),
powerState,
},
decorator: defaultDecorator,
},
}

//---HELPERS---
Expand Down
43 changes: 38 additions & 5 deletions directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,26 @@ const directives = {
SelectInput: (request, _currentState) => ({
input: request.directive.payload.input,
}),
SetTargetTemperature: (request, _currentState) => ({
targetTemperature: request.directive.payload.targetSetpoint.value,
targetScale: request.directive.payload.targetSetpoint.scale,
powerState: 'ON',
}),
SetTargetTemperature: (request, currentState) => {
const newState = {
powerState: 'ON',
}

if (currentState.template === 'THERMOSTAT') {
newState['targetTemperature'] =
request.directive.payload.targetSetpoint.value
newState['targetScale'] = request.directive.payload.targetSetpoint.scale
} else if (currentState.template === 'THERMOSTAT_2') {
newState['lowerSetpoint'] = request.directive.payload.lowerSetpoint.value
newState['lowerSetpointScale'] =
request.directive.payload.lowerSetpoint.scale
newState['upperSetpoint'] = request.directive.payload.upperSetpoint.value
newState['upperSetpointScale'] =
request.directive.payload.upperSetpoint.scale
}

return newState
},
SetThermostatMode: (request, _currentState) => {
const newState = {
thermostatMode: request.directive.payload.thermostatMode.value,
Expand Down Expand Up @@ -418,6 +433,24 @@ function buildPropertiesFromState(state) {
)
}

if (state.hasOwnProperty('lowerSetpoint')) {
properties.push(
makeProperty('Alexa.ThermostatController', 'lowerSetpoint', {
value: state.lowerSetpoint,
scale: state.lowerSetpointScale,
})
)
}

if (state.hasOwnProperty('upperSetpoint')) {
properties.push(
makeProperty('Alexa.ThermostatController', 'upperSetpoint', {
value: state.upperSetpoint,
scale: state.upperSetpointScale,
})
)
}

if (state.hasOwnProperty('temperature')) {
properties.push(
makeProperty('Alexa.TemperatureSensor', 'temperature', {
Expand Down
Binary file added img/examples.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/csuermann/node-red-contrib-virtual-smart-home"
"url": "git+https://github.com/csuermann/node-red-contrib-virtual-smart-home.git"
},
"keywords": [
"Alexa",
Expand Down
38 changes: 21 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
# Virtual Smart Home (VSH)

A Node-RED node that represents a virtual device which can be controlled via
A Node-RED node that represents a virtual smart home device which can be controlled via
Amazon Alexa. Requires the '_virtual smart home_' skill to be enabled for your
Amazon account.

## Availability

The _virtual smart home_ skill is available in the Amazon skill stores in the following locales:

- [English (AU)](https://www.amazon.com.au/dp/B08JV9RT7H)
- [English (CA)](https://www.amazon.ca/dp/B08JV9RT7H)
- [English (GB)](https://www.amazon.co.uk/dp/B08JV9RT7H)
- [English (IN)](https://www.amazon.in/dp/B08JV9RT7H)
- [English (US)](https://www.amazon.com/dp/B08JV9RT7H)
- [French (FR)](https://www.amazon.fr/dp/B08JV9RT7H)
- [German (DE)](https://www.amazon.de/dp/B08JV9RT7H)
- [Italian (IT)](https://www.amazon.it/dp/B08JV9RT7H)
- [Portuguese (BR)](https://www.amazon.com.br/dp/B08JV9RT7H)
- [Spanish (ES)](https://www.amazon.es/dp/B08JV9RT7H)
![Examples](./img/examples.png)

## Highlights

Expand All @@ -27,16 +14,18 @@ The _virtual smart home_ skill is available in the Amazon skill stores in the fo
- Contact Sensor
- Dimmable Light Bulb
- Dimmer Switch
- Doorbell Event Source
- Entertainment Device
- Fan
- Garage Door Opener (en-US locale only)
- Lock
- Motion Sensor
- Plug
- Switch
- Scene
- Switch
- Temperature Sensor
- Thermostat
- Thermostat (Single-setpoint)
- Thermostat (Dual-setpoint)
- no separate account needed. Just link your existing Amazon account.
- new virtual devices can simply be dragged onto the Node-RED canvas and will
proactively be discovered by Alexa. No need to ask Alexa to discover devices.
Expand Down Expand Up @@ -77,6 +66,21 @@ like when the node gets invoked via Alexa. In this case `payload.source` is set

Please ensure that your setup does not send too many messages to Alexa. Otherwise you risk getting your account blocked.

## Availability

The _virtual smart home_ skill is available in the Amazon skill stores in the following locales:

- [English (AU)](https://www.amazon.com.au/dp/B08JV9RT7H)
- [English (CA)](https://www.amazon.ca/dp/B08JV9RT7H)
- [English (GB)](https://www.amazon.co.uk/dp/B08JV9RT7H)
- [English (IN)](https://www.amazon.in/dp/B08JV9RT7H)
- [English (US)](https://www.amazon.com/dp/B08JV9RT7H)
- [French (FR)](https://www.amazon.fr/dp/B08JV9RT7H)
- [German (DE)](https://www.amazon.de/dp/B08JV9RT7H)
- [Italian (IT)](https://www.amazon.it/dp/B08JV9RT7H)
- [Portuguese (BR)](https://www.amazon.com.br/dp/B08JV9RT7H)
- [Spanish (ES)](https://www.amazon.es/dp/B08JV9RT7H)

## Setup Instructions

### In the Alexa app
Expand Down
61 changes: 57 additions & 4 deletions virtual-device.html
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@
<option value="SCENE">Scene</option>
<option value="SWITCH">Switch</option>
<option value="TEMPERATURE_SENSOR">Temperature Sensor</option>
<option value="THERMOSTAT">Thermostat</option>
<option value="THERMOSTAT">Thermostat (Single-setpoint)</option>
<option value="THERMOSTAT_2">Thermostat (Dual-setpoint)</option>
</select>
</div>

Expand Down Expand Up @@ -699,13 +700,18 @@ <h4>Temperature Sensor</h4>
</dd>
</dl>

<h4>Thermostat</h4>
<h4>Thermostat (Single-setpoint)</h4>
<dl class="message-properties">
<dt>
payload.powerState
<span class="property-type">string</span>
</dt>
<dd>'ON' or 'OFF'</dd>
<dt>
payload.temperature
<span class="property-type">float</span>
</dt>
<dd>Measured temperature</dd>
<dt>
payload.scale
<span class="property-type">string</span>
Expand All @@ -714,6 +720,11 @@ <h4>Thermostat</h4>
Scale / unit of temperature. Allowed values: 'CELSIUS', 'FAHRENHEIT',
'KELVIN'
</dd>
<dt>
payload.targetTemperature
<span class="property-type">float</span>
</dt>
<dd>Target temperature</dd>
<dt>
payload.targetScale
<span class="property-type">string</span>
Expand All @@ -723,15 +734,57 @@ <h4>Thermostat</h4>
'FAHRENHEIT', 'KELVIN'
</dd>
<dt>
payload.targetTemperature
payload.thermostatMode
<span class="property-type">string</span>
</dt>
<dd>'AUTO', 'HEAT', 'COOL', 'ECO', 'OFF'</dd>
</dl>
<h4>Thermostat (Dual-setpoint)</h4>
<dl class="message-properties">
<dt>
payload.powerState
<span class="property-type">string</span>
</dt>
<dd>'ON' or 'OFF'</dd>
<dt>
payload.lowerSetpoint
<span class="property-type">float</span>
</dt>
<dd>Target temperature</dd>
<dd>Lower setpoint temperature</dd>
<dt>
payload.lowerSetpointScale
<span class="property-type">string</span>
</dt>
<dd>
Scale / unit of lowerSetpoint. Allowed values: 'CELSIUS', 'FAHRENHEIT',
'KELVIN'
</dd>
<dt>
payload.upperSetpoint
<span class="property-type">float</span>
</dt>
<dd>Upper setpoint temperature</dd>
<dt>
payload.upperSetpointScale
<span class="property-type">string</span>
</dt>
<dd>
Scale / unit of upperSetpoint. Allowed values: 'CELSIUS', 'FAHRENHEIT',
'KELVIN'
</dd>
<dt>
payload.temperature
<span class="property-type">float</span>
</dt>
<dd>Measured temperature</dd>
<dt>
payload.scale
<span class="property-type">string</span>
</dt>
<dd>
Scale / unit of temperature. Allowed values: 'CELSIUS', 'FAHRENHEIT',
'KELVIN'
</dd>
<dt>
payload.thermostatMode
<span class="property-type">string</span>
Expand Down

0 comments on commit eacf32c

Please sign in to comment.