Alexa, ask my TV to do something thanks to my Raspberry Pi

How I implement Alexa connection with my raspberry
  • 1) How control television with Infrared (IR) emitter connect to the Raspberry with Lirc
  • 2) How create some Alexa intents in order to control Raspberry in the Alexa Skill Developper Kit
  • 3) How to link Alexa cloud with our raspberry NodeJS server

Materials needed

  • At least one Alexa connect to your intern wifi
  • x1 Raspberry or similar (here, I use and explain for Raspberry Pi 2 but can be adapt easily to other version)
  • x1 IR Transmitter module. (In my case, I use Whadda WPM316 for Arduino) . You can add an IR emitter if you need to record your remote. In my case, I was lucky, I found the mapping easily on internet.
  • x2 GPIO Cable (female/female)
  • Television (and his TV remote if you need to record each key)

Control my television with IR emitter and Lirc

Connection of the IR emitter to the Raspberry
sudo apt get install lirc
driver          = default
device = /dev/lirc0
dtoverlay=gpio-ir-tx,gpio_pin=18
dtoverlay=gpio-ir,gpio_pin=17
lircd.conf <name of your remove device>
# Restart lirc
sudo service lircd restart
# Send one press to power on or power off my tv:
irsend SEND_ONCE SAMSUNG_AA59-00600A_POWER KEY_POWER
# Send two press to press one of other key :
irsend SEND_ONCE SAMSUNG_AA59-00600A KEY_VOLUMEUP
Example of IR from a phone camera

Prepare my raspberry to Alexa with NodeJS Express server

GET on https://<myHostAddress>/:command
irsend SEND_ONCE <remote name in lircd.conf> <choosen commande like KEY_VOLUMEUP>
NodeJS / Express route to control Lirc
npm install pm2 -g# Go to your server folder
pm2 start app.js

Create your first Alexa Skill Intent

  • KEY_POWER => ON ; switch on ; switch off ; OFF; etc..
  • KEY_VOLUMEUP => louder the sound; turn up the volume; turn the volume up; etc…

Link to your Raspberry

const https = require('https')
const Alexa = require('ask-sdk-core');
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const commandkey = handlerInput.requestEnvelope.request.intent.slots.command.resolutions.resolutionsPerAuthority[0].values[0].value.name;
const speakOutput = `You just do the command ${commandkey}`;

https.get(`https://my_public_api/${commandkey}`, res => {
}).on('error', err => {
console.log(err.message);
})
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
const speakOutput = 'Mes excuses, je n\'ai pas compris la commande à transmettre à la télé';
console.log(`~~~~ Error handled: ${JSON.stringify(error)}`);
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(IntentReflectorHandler)
.addErrorHandlers(ErrorHandler)
.lambda();
  1. The exports.handler show all publics functions that will be launch for. It will execute each function in an ordered stack. (Reactive programming)
  2. Each function has a canHandle function inside. If a function is not handled (the function inside “canHandle” return false), the second function inside (handle) is not launched, and the following main function in the export.handler is executed etc…
  3. Because of errorHandler has a canHandle that return true and is at the bottom on the stack in the exports.handler, it will be launched if none of other function can handle it.
  4. If a main function canHandle, the handle function inside it is launch. Other main function will not be executed.
  5. The 2nd function inside each main function is handled, receiving an handlerInput. It embedded all information you need. I console.log it to found my retrieved command and fetch it to my API.
  6. Each main function should return an handlerInput.responseBuilder. You can stack function like .speak(“something”).reprompt(), if you want Alexa say “something” and wait a response from the interlocutor.
  7. I use https.get in my case, to fetch my API, because it is natively included in nodeJS without adding libs.
Tips to access to Cloudwatch log
French example from the Test tab

Final rendering (french version) :

Bibliography

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store