phpoc_man
Published © GPL3+

Amazon Echo - LED Strip

This project allows you to use voice command to turn on/off, change color, effect of one, a range or all of an LED strip.

AdvancedFull instructions provided3,302
Amazon Echo -  LED Strip

Things used in this project

Story

Read more

Schematics

Hardware

Code

Lambda function (index.js)

JavaScript
/**
 * This sample demonstrates a simple skill built with the Amazon Alexa Skills Kit.
 * The Intent Schema, Custom Slots, and Sample Utterances for this skill, as well as
 * testing instructions are located at http://amzn.to/1LzFrj6
 *
 * For additional samples, visit the Alexa Skills Kit Getting Started guide at
 * http://amzn.to/1LGWsLG
 */

var mqtt = require('mqtt');

// Route the incoming request based on type (LaunchRequest, IntentRequest,
// etc.) The JSON body of the request is provided in the event parameter.
exports.handler = function (event, context) {
	try {
		console.log("event.session.application.applicationId=" + event.session.application.applicationId);

		/**
		 * Uncomment this if statement and populate with your skill's application ID to
		 * prevent someone else from configuring a skill that sends requests to this function.
		 */
		/*
		if (event.session.application.applicationId !== "amzn1.echo-sdk-ams.app.[unique-value-here]") {
			 context.fail("Invalid Application ID");
		}
		*/

		if (event.session.new) {
			onSessionStarted({requestId: event.request.requestId}, event.session);
		}

		if (event.request.type === "LaunchRequest") {
			onLaunch(event.request,
				event.session,
				function callback(sessionAttributes, speechletResponse) {
					context.succeed(buildResponse(sessionAttributes, speechletResponse));
				});
		} else if (event.request.type === "IntentRequest") {
			onIntent(event.request,
				event.session,
				function callback(sessionAttributes, speechletResponse) {
					context.succeed(buildResponse(sessionAttributes, speechletResponse));
				});
		} else if (event.request.type === "SessionEndedRequest") {
			onSessionEnded(event.request, event.session);
			context.succeed();
		}
	} catch (e) {
		context.fail("Exception: " + e);
	}
};

/**
 * Called when the session starts.
 */
function onSessionStarted(sessionStartedRequest, session) {
	console.log("onSessionStarted requestId=" + sessionStartedRequest.requestId +
		", sessionId=" + session.sessionId);
}

/**
 * Called when the user launches the skill without specifying what they want.
 */
function onLaunch(launchRequest, session, callback) {
	console.log("onLaunch requestId=" + launchRequest.requestId +
		", sessionId=" + session.sessionId);

	// Dispatch to your skill's launch.
	getWelcomeResponse(callback);
}

/**
 * Called when the user specifies an intent for this skill.
 */
function onIntent(intentRequest, session, callback) {
	console.log("onIntent requestId=" + intentRequest.requestId +
		", sessionId=" + session.sessionId);

	var intent = intentRequest.intent,
		intentName = intentRequest.intent.name;

	// Dispatch to your skill's intent handlers
	if ("LedStrip" === intentName) {
		setLightInSession(intent, session, callback);
	} else if ("AMAZON.HelpIntent" === intentName) {
		getWelcomeResponse(callback);
	} else if ("AMAZON.StopIntent" === intentName || "AMAZON.CancelIntent" === intentName) {
		handleSessionEndRequest(callback);
	} else {
		throw "Invalid intent";
	}
}

/**
 * Called when the user ends the session.
 * Is not called when the skill returns shouldEndSession=true.
 */
function onSessionEnded(sessionEndedRequest, session) {
	console.log("onSessionEnded requestId=" + sessionEndedRequest.requestId + ", sessionId=" + session.sessionId);
	// Add cleanup logic here
}

// --------------- Functions that control the skill's behavior -----------------------

function getWelcomeResponse(callback) {
	// If we wanted to initialize the session to have some attributes we could add those here.
	var sessionAttributes = {};
	var cardTitle = "Welcome";
	var speechOutput = "Welcome to P H P o C. How can I help you?";
	
	// If the user either does not reply to the welcome message or says something that is not
	// understood, they will be prompted again with this text.
	var repromptText = "How can I help you?";
	var shouldEndSession = false;
	
	callback(sessionAttributes,
		buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}

function handleSessionEndRequest(callback) {
	var cardTitle = "Session Ended";
	var speechOutput = "Thank you for trying the P h p o c  example. Have a nice day!";
	// Setting this to true ends the session and exits the skill.
	var shouldEndSession = true;
	
	callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession));
}

/**
 * Sets the led in the session and prepares the speech to reply to the user.
 */
function setLightInSession(intent, session, callback) {
	var cardTitle = intent.name;
	
	var colorStateRequest = intent.slots.ColorState;
	var ledFromRequest = intent.slots.FromLed;
	var ledToRequest = intent.slots.ToLed;
	var ledStateRequest = intent.slots.LedState;
	var effectRequest = intent.slots.Effect;

	var repromptText = "";
	var sessionAttributes = {};
	var shouldEndSession = true;
	var speechOutput = "";
	
	if(colorStateRequest || ledFromRequest || ledToRequest || ledStateRequest || effectRequest)
	{
		var colorState = colorStateRequest.value;
		var ledFrom = ledFromRequest.value;
		var ledTo = ledToRequest.value;
		var ledState = ledStateRequest.value;
		var effect = effectRequest.value;
		
		if (colorState === undefined) 
			colorState = "";
		
		if (ledFrom === undefined) 
			ledFrom = 0;
		
		if (ledTo === undefined) 
			ledTo = 0;
		
		if (ledState === undefined) 
			ledState = "";
		
		if (effect === undefined) 
			effect = "";
		
		var responseAlexa = "";
		
		if(colorState != "")
		{
			responseAlexa = "Ok, changing color of led strip ";
			
			if(ledFrom != 0 && ledTo !=0)
				responseAlexa += "from number " + ledFrom + " to number " + ledTo + " to " + colorState;
			else if(ledFrom != 0)
				responseAlexa += "number " + ledFrom + " to " + colorState;
			else
				responseAlexa += " to " +  colorState;
		}
		else if(ledState != "")
		{
			responseAlexa = "Ok, turning ";
			if(ledFrom != 0 && ledTo !=0)
				responseAlexa += ledState + " led strip from number " + ledFrom + " to number " + ledTo;
			else if(ledFrom != 0)
			{
				if(ledFrom == "all")
					responseAlexa += ledState + " all led strip";
				else
					responseAlexa += ledState + " led strip number " + ledFrom;
			}
		}
		else if(effect != "")
		{
			responseAlexa = "Ok, change effect of led ";
			
			if(ledFrom != 0 && ledTo !=0)
				responseAlexa += "from number " + ledFrom + " to number " + ledTo + " to " + effect;
			else if(ledFrom != 0)
				responseAlexa += "number " + ledFrom + " to " + effect;
			else
				responseAlexa = "Ok, change effect to " + effect;
		}
		else
		{
			responseAlexa = "Please try again";
		}
		
		if (ledFrom === "all") 
			ledFrom = 15;
		
		var paramsUpdate = ' {"color" : "' + colorState + '", "from" : ' + ledFrom + ', "to" : ' + ledTo + ', "state" : "' + ledState + '", "effect" : "' + effect + '"}';
		
		//Update 
		var mqttpromise = new Promise( function(resolve,reject){
			var client = mqtt.connect({port:1883,host:'iot.eclipse.org'})
			
			client.on('connect', function() { // When connected
				// publish a message to a topic
				client.publish('phpoc/alexa/ledstrip', paramsUpdate)
				client.end()
				resolve('Done Sending');
			});
			
		});
		mqttpromise.then(
			function(data) {
				console.log('Function called succesfully:', data);
				sessionAttributes = createcolorStateAttributes(colorState);
				speechOutput = responseAlexa;
				repromptText = responseAlexa;
				callback(sessionAttributes,buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
			},
			function(err) {
				console.log('An error occurred:', err);
			}
		);
		 
	} else {
		speechOutput = "Please try again";
		repromptText = "Please try again";
		callback(sessionAttributes,buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
	}
}

function createcolorStateAttributes(colorState) {
	return {
		colorState: colorState
	};
}

// --------------- Helpers that build all of the responses -----------------------

function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
	return {
		outputSpeech: {
			type: "PlainText",
			text: output
		},
		card: {
			type: "Simple",
			title: "SessionSpeechlet - " + title,
			content: "SessionSpeechlet - " + output
		},
		reprompt: {
			outputSpeech: {
				type: "PlainText",
				text: repromptText
			}
		},
		shouldEndSession: shouldEndSession
	};
}

function buildResponse(sessionAttributes, speechletResponse) {
	return {
		version: "1.0",
		sessionAttributes: sessionAttributes,
		response: speechletResponse
	};
}

PHPoC Source Code (task0.php)

PHP
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; // avoid php execution via http request

include_once "/lib/sd_spc.php";
include_once "/lib/sn_dns.php";
include_once "/lib/sn_json.php";
include_once "/lib/vn_mqtt.php";

define("RED",		1);
define("GREEN",		2);
define("BLUE",		4);
define("YELLOW",	RED | GREEN);
define("CYAN",		GREEN | BLUE);
define("MAGENTA",	RED | BLUE);
define("WHITE",		RED | GREEN | BLUE);

define("EFFECT_NORMAL",		1);
define("EFFECT_BLINK",		2);
define("EFFECT_COLOR",		3);
define("EFFECT_DOMINO",		4);

define("ON",		1);
define("OFF",		0);

function led_strip_get_tick()
{
	while(($pid = pid_open("/mmap/st0", O_NODIE)) == -EBUSY)
		usleep(500);

	if(!pid_ioctl($pid, "get state"))
		pid_ioctl($pid, "start");

	$tick = pid_ioctl($pid, "get count");
	pid_close($pid);

	return $tick;
}
function get_color_code($color_name)
{
	$color_name = strtoupper($color_name);
	
	if($color_name == "RED")
		return RED;
	if($color_name == "GREEN")
		return GREEN;
	if($color_name == "BLUE")
		return BLUE;
	if($color_name == "YELLOW")
		return YELLOW;
	if($color_name == "CYAN")
		return CYAN;
	if($color_name == "MAGENTA")
		return MAGENTA;
	if($color_name == "WHITE")
		return WHITE;

	return 0;
}

spc_reset();
spc_sync_baud(115200);

//$host_name = "test.mosquitto.org";
$host_name = "iot.eclipse.org";
//$host_name = "broker.hivemq.com";
//$host_name = "broker.mqttdashboard.com";
//$host_name = "[112.171.138.90]";
$port = 1883;

mqtt_setup(0, "PHPoC-MQTT Sub Example",  $host_name, $port); 

$will = "";
$username = "";
$password = "";

mqtt_connect(true, $will, $username, $password);

$out_topics = array(array("phpoc/alexa/ledstrip", 0));

if(mqtt_state() == MQTT_CONNECTED)
    mqtt_subscribe($out_topics);

$in_topic = "";
$in_content = "";
$is_retain = 0;

$led_from = 0;
$led_to = 0;
$led_effect = array("normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal", "normal");
$led_color = array(WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE);
$led_state = array(OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF);

$update = true;

while(1)
{
	if(mqtt_state() == MQTT_DISCONNECTED)
		while(mqtt_reconnect() == false);
	
	if(mqtt_loop($in_topic, $in_content, $is_retain))
	{
		//TODO , procees the received publish packet here
		if($is_retain == 1)
			echo "<<a stale message\r\n";
		
		echo "<<topic:$in_topic\r\n";
		echo "<<content: $in_content\r\n";
		
		$color	= json_text_value(json_search($in_content, "color"));
		$from	= (int)json_search($in_content, "from");
		$to		= (int)json_search($in_content, "to");
		$state	= json_text_value(json_search($in_content, "state"));
		$effect = json_text_value(json_search($in_content, "effect"));
		
		if($from > 15 || $to > 15)
			continue;
		
		if($from == 15)
		{
			$led_from = 1;
			$led_to = 14;
		}
		else if($from != 0)
		{
			$led_from = $from;
			$led_to = $to;
		}
		
		if($color != "")
		{
			$color_value = get_color_code($color);
			
			if($from != 0 && $to == 0)
				$led_color[$from - 1] = $color_value;
			else if($from != 0 && $to != 0)
			{
				for($i = $led_from; $i <= $led_to; $i++)
				{
					$led_color[$i - 1] = $color_value;
				}
			}
			else if($from == 0 && $to == 0)
			{
				for($i = 1; $i <= 14; $i++)
				{
					$led_color[$i - 1] = $color_value;
				}
			}
		}
		
		if($state != "" && $led_from != 0)
		{
			$state_value = ($state == "on") ? ON : OFF;
			
			if($led_to == 0)
			{
				$led_state[$led_from - 1] = $state_value;
				$led_effect[$led_from - 1] = "normal";
			}
			else
			{
				for($i = $led_from; $i <= $led_to; $i++)
				{
					$led_state[$i - 1] = $state_value;
					$led_effect[$i - 1] = "normal";
				}
			}
		}
		
		if($effect != "")
		{
			if($from != 0 && $to == 0)
			{
				$led_effect[$from - 1] = $effect;
				if($effect != "normal")
					$led_state[$from - 1] = ON;
			}
			else if($from != 0 && $to != 0)
			{
				for($i = $led_from; $i <= $led_to; $i++)
				{
					$led_effect[$i - 1] = $effect;
					if($effect != "normal")
						$led_state[$i - 1] = ON;
				}
			}
			else if($from == 0 && $to == 0)
			{
				for($i = 1; $i <= 14; $i++)
				{
					$led_effect[$i - 1] = $effect;
					if($effect != "normal")
						$led_state[$i - 1] = ON;
				}
			}
		}
		
		$update = true;
	}
	$curr_time = led_strip_get_tick();
	
	for($i = 0; $i < 14; $i++)
	{
		$effect = $led_effect[$i];
		switch($effect)
		{
			case "normal":
				//$update = true;
				break;
			case "blink":
				if(($curr_time - $update_time) > 1500)
				{
					//if($led_state[$i] == ON)
						$led_state[$i] = ($led_state[$i] + 1) % 2;
					
					$update = true;
				}
				break;
			case "color":
				if(($curr_time - $update_time) > 1500)
				{
					$led_color[$i] = ($led_color[$i] + 1) % 8;
					
					$update = true;
				}
				break;
			case "domino":
				
				break;
		}
	}
	
	if($update)
	{
		for($i = 1; $i <= 14; $i++)
		{
			if($led_state[$i - 1] == OFF)
			{
				spc_request($i, 4, "set 0 output low"); usleep(10);
				spc_request($i, 4, "set 1 output low"); usleep(10);
				spc_request($i, 4, "set 2 output low"); usleep(10);
			}
			else
			{
				$color = $led_color[$i - 1];
				
				$state = ($color & RED) ? "high" : "low";
				spc_request($i, 4, "set 0 output $state"); usleep(10);
				$state = ($color & GREEN) ? "high" : "low";
				spc_request($i, 4, "set 1 output $state"); usleep(10);
				$state = ($color & BLUE) ? "high" : "low";
				spc_request($i, 4, "set 2 output $state"); usleep(10);
			}
		}
		
		$update_time = led_strip_get_tick();
		$update = false;
	}
}
//mqtt_unsubscribe("sensors/temperature");
    
mqtt_disconnect();

?>

Credits

phpoc_man

phpoc_man

62 projects • 406 followers

Comments