Skip to content
This repository has been archived by the owner on Jul 10, 2024. It is now read-only.

Commit

Permalink
Set defaults (#9)
Browse files Browse the repository at this point in the history
* Fix auto-hold on switch off
  • Loading branch information
Matt Turner authored Mar 30, 2019
1 parent 32d216a commit e7165d5
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 7 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ Until Salus provide their own Alexa skill or a federated authentication method t

This app is a Node.js module, written using the excellent [alexa-app](https://www.npmjs.com/package/alexa-app) module framework by Matt Kruse [github](https://github.com/matt-kruse/alexa-app-server/blob/master/README.md)

This skill has 5 intents :-
This skill has 8 intents :-

* Alexa, ask boiler the temperature
* Alexa, ask boiler to set higher
* Alexa, ask boiler to set lower
* Alexa, ask boiler to set to x degrees
* Alexa, ask boiler to turn [on/off] [for x hours]
* Alexa, ask boiler to set the default [on/off] temperature to x degrees
* Alexa, ask boiler to set the default duration to [x hours]
* Alexa, ask boiler the current defaults

## Auto-switch off/Hold time

Expand All @@ -26,7 +29,6 @@ The last intent can take an optional duration which can be any valid time statem

* You will need to prevent Salus from overriding this by setting the off times to a late time (eg 10pm)
* It is optional and requires a hosted lambda, step function and dynamodb table
* Cancellation of the hold-time is not yet supported; the boiler will switch off

## Setting Up

Expand Down
22 changes: 20 additions & 2 deletions aws/ThermostatRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,32 @@ class ThermostatRepository {
}

async save(thermostat) {
let existingThermostat = await this.find(thermostat.userId);

let updateField = 'executionId';
let updateValue = thermostat.executionId;
if (existingThermostat.executionId !== thermostat.executionId) {
updateField = 'executionId';
updateValue = thermostat.executionId;
} else if (existingThermostat.defaultDuration !== thermostat.defaultDuration) {
updateField = 'defaultDuration';
updateValue = thermostat.defaultDuration;
} else if (existingThermostat.defaultOnTemp !== thermostat.defaultOnTemp) {
updateField = 'defaultOnTemp';
updateValue = thermostat.defaultOnTemp;
} else if (existingThermostat.defaultOffTemp !== thermostat.defaultOffTemp) {
updateField = 'defaultOffTemp';
updateValue = thermostat.defaultOffTemp;
}

const params = {
TableName,
Key: {
userId: thermostat.userId
},
UpdateExpression: 'set executionId=:eid',
UpdateExpression: `set ${updateField}=:updateField`,
ExpressionAttributeValues: {
':eid': thermostat.executionId
':updateField': updateValue
},
ReturnValues: 'UPDATED_NEW'
};
Expand Down
50 changes: 50 additions & 0 deletions aws/lambda.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,56 @@ app.intent('TurnIntent', {
return false;
});

app.intent('SetDefaultTempIntent', {
'slots': {
'onoff': 'ONOFF',
'temp': 'AMAZON.NUMBER'
},
'utterances': ['to set the default {onoff} temperature to {temp} degrees']
}, async (request, response) => {
let onOff = request.slot('onoff');
let temp = request.slot('temp');
let service = controlService(request);
try {
let messages = await service.setDefault(onOff, temp);
say(response, messages);
} catch (e) {
say(response, e);
}
return false;
});

app.intent('SetDefaultDurationIntent', {
'slots': {
'duration': 'AMAZON.DURATION'
},
'utterances': ['to set the default duration to {duration}']
}, async (request, response) => {
let duration = request.slot('duration');
let service = controlService(request);
try {
let messages = await service.setDefault('duration', duration);
say(response, messages);
} catch (e) {
say(response, e);
}
return false;
});

app.intent('DefaultsIntent', {
'slots': {},
'utterances': ['the current default values', 'the default values', 'the current defaults', 'the defaults']
}, async (request, response) => {
let service = controlService(request);
try {
let messages = await service.defaults();
say(response, messages);
} catch (e) {
say(response, e);
}
return false;
});

app.intent('AMAZON.HelpIntent', {
'slots': {},
'utterances': []
Expand Down
42 changes: 42 additions & 0 deletions aws/skill.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@
"how hot it is"
]
},
{
"name": "DefaultsIntent",
"slots": [],
"samples": [
"the current default values",
"the default values",
"the current defaults",
"the defaults"
]
},
{
"name": "TurnDownIntent",
"slots": [],
Expand Down Expand Up @@ -90,6 +100,38 @@
"set higher"
]
},
{
"name": "SetDefaultTempIntent",
"slots": [
{
"name": "temp",
"type": "AMAZON.NUMBER",
"samples": [
"{temp}",
"{temp} degrees"
]
},
{
"name": "onoff",
"type": "ONOFF"
}
],
"samples": [
"to set the default {onoff} temperature to {temp} degrees"
]
},
{
"name": "SetDefaultDurationIntent",
"slots": [
{
"name": "duration",
"type": "AMAZON.DURATION"
}
],
"samples": [
"to set the default duration to {duration}"
]
},
{
"name": "AMAZON.MoreIntent",
"slots": [],
Expand Down
47 changes: 44 additions & 3 deletions core/ControlService.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ class ControlService {
t = thermostat.defaultOffTemp;
}

return this.setTemperature(t, duration);
return this.setTemperature(t, duration, onOff === 'on');
}

async setTemperature(targetTemperature, forDuration) {
async setTemperature(targetTemperature, forDuration, allowAutoHold = true) {
console.log(`Setting temperature to ${targetTemperature}...`);
let client = await this.login();
try {
Expand All @@ -175,7 +175,7 @@ class ControlService {
messages.push(`The target temperature is now ${this.speakTemperature(updatedDevice.targetTemperature)} degrees.`);
this.logStatus(updatedDevice);

if (this._context.source === 'user') {
if (this._context.source === 'user' && allowAutoHold) {
let thermostat = await this.obtainThermostat();
let duration = forDuration || thermostat.defaultDuration;
let intent = await this._holdStrategy.holdIfRequiredFor(duration);
Expand Down Expand Up @@ -204,6 +204,47 @@ class ControlService {
return [`The heating will turn off in ${durationText}`];
}

async setDefault(name, value) {
console.log(`Setting default ${name} to ${value}...`);

let thermostat = await this.obtainThermostat();
let nameText = '';
let valueText = '';
switch(name) {
case 'on':
thermostat.defaultOnTemp = value;
nameText = 'on temperature';
valueText = `${value} degrees`;
break;
case 'off':
thermostat.defaultOffTemp = value;
nameText = 'off temperature';
valueText = `${value} degrees`;
break;
case 'duration':
thermostat.defaultDuration = value;
nameText = 'duration';
valueText = this.speakDuration(new Duration(value));
break;
}

await this._thermostatRepository.save(thermostat);

return [`The default ${nameText} has been set to ${valueText}`];
}

async defaults() {
console.log('Retrieving default values...');

let thermostat = await this.obtainThermostat();

return [
`The default on temperature is ${thermostat.defaultOnTemp}.`,
`The default off temperature is ${thermostat.defaultOffTemp}.`,
`The default duration is ${this.speakDuration(new Duration(thermostat.defaultDuration))}.`
];
}

logStatus(device) {
console.log(`${new Date().toISOString()} ${device.currentTemperature} => ${device.targetTemperature} (${device.status})`);
}
Expand Down

0 comments on commit e7165d5

Please sign in to comment.