Skip to content

Instantly share code, notes, and snippets.

@richardlevy
Created May 4, 2023 10:20
Show Gist options
  • Select an option

  • Save richardlevy/192e271ea990b1ad0f12974d510f0911 to your computer and use it in GitHub Desktop.

Select an option

Save richardlevy/192e271ea990b1ad0f12974d510f0911 to your computer and use it in GitHub Desktop.
Solis Cloud Scraper Alexa Skill
/*
lambda/index.js
This is a very basic Alexa skill to get the latest stats from a Solis Cloud Scraper installation.
To configure you need to:
* Add the URL of your Solis Scraper installation in the GetRemoteDataHandler function directly below
* Add your Solis Scraper username and password to the getRemoteData function at the bottom
I used one of the example project templates and modified it. You will have to separately choose an invocation name.
You do no need to distribute this to use it, just move it to testing and it will be available to any Alexa device you are signed in to (assuming you sign in to your Amazon Developer account with the same account)
*/
/* eslint-disable no-use-before-define */
/* eslint-disable global-require */
const Alexa = require('ask-sdk-core');
const GetRemoteDataHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest'
|| (handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'GetRemoteDataIntent');
},
async handle(handlerInput) {
let outputSpeech = "Sorry, I couldn't get the information";
// Add the URI of your Solis Scraper here
await getRemoteData('<INSERT SOLIS SCRAPE URI HERE>/data')
.then((response) => {
const data = JSON.parse(response);
const now = Date.now();
const endTime = data.scrapeEndTimeMs;
const age = Math.floor( (now - endTime) / 1000 );
var ageSpeech = ""
if (age < 60) {
ageSpeech = `${age} seconds`
} else {
const mins = Math.floor(age / 60);
if (mins === 1) {
ageSpeech = `${mins} minute`
} else {
ageSpeech = `${mins} minutes`
}
}
outputSpeech = `${ageSpeech} ago, the solar was generating ${data.currentGen}. `;
outputSpeech = `${outputSpeech} The house was using ${data.currentHouseDraw} `;
outputSpeech = `${outputSpeech} and the battery charge was ${data.batteryCharge}. `;
outputSpeech = `${outputSpeech} Todays total yield is ${data.totalYield}, `;
outputSpeech = `${outputSpeech} ${data.todayFromGrid} has been imported and ${data.todayToGrid} has been exported.`;
})
.catch((err) => {
console.log(`ERROR: ${err.message}`);
// set an optional error message here
// outputSpeech = err.message;
});
return handlerInput.responseBuilder
.speak(outputSpeech)
.getResponse();
},
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'You can introduce yourself by telling me your name';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
},
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
},
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);
return handlerInput.responseBuilder.getResponse();
},
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error handled: ${error.message}`);
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Please say again.')
.reprompt('Sorry, I can\'t understand the command. Please say again.')
.getResponse();
},
};
const getRemoteData = (url) => new Promise((resolve, reject) => {
const client = url.startsWith('https') ? require('https') : require('http');
// Format is <username>:<password>
// e.g
// {'auth': 'myUsername:myPassword'}
var authOptions = {'auth': 'username:password'};
const request = client.get(url, authOptions, (response) => {
if (response.statusCode < 200 || response.statusCode > 299) {
reject(new Error(`Failed with status code: ${response.statusCode}`));
}
const body = [];
response.on('data', (chunk) => body.push(chunk));
response.on('end', () => resolve(body.join('')));
});
request.on('error', (err) => reject(err));
});
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
GetRemoteDataHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.lambda();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment