Skip to content

Instantly share code, notes, and snippets.

@kasperkamperman
Created May 28, 2017 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kasperkamperman/6590c7966d1963e6f8ae9968a43bed06 to your computer and use it in GitHub Desktop.
Save kasperkamperman/6590c7966d1963e6f8ae9968a43bed06 to your computer and use it in GitHub Desktop.
temporary version local
/* Local
Example code on how to remote control the RGB led on the Particle Photon.
It listens to hue (0-359), saturation (0-255), brightness (0-255)
Copyleft 19-05-2017 - http://www.kasperKamperman.com
https://github.com/mrhornsby/spark-core-mdns
https://github.com/m-mcgowan/Webduino
https://community.particle.io/t/photon-running-simple-webserver-local-communication/20677/7
https://github.com/m-mcgowan/Webduino/blob/master/firmware/examples/Web_AjaxRGB_mobile/Web_AjaxRGB_mobile.ino
*/
// see WebServer/WebServer.h for documentation of the defines.
#define WEBDUINO_OUTPUT_BUFFER_SIZE 40
#define WEBDUINO_SERIAL_DEBUGGING 2 // debug serial
#define WEBDUINO_FAVICON_DATA "" // no favicon
#include "Particle.h"
#include "MDNS/MDNS.h"
#include "WebDuino.h"
const String hostname = "myphoton";
//const String remote_url = "http://www.lumiflow.nl/webapptest/";
const String remote_url = "https://www.kasperkamperman.com/localremote/";
const unsigned char header[] =
"HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nConnection: close\r\n\r\n";
const unsigned char header_content_html[] =
"Content-Type: text/html; charset=utf-8\r\n";
const unsigned char header_content_json[] =
"Content-Type: application/json; charset=utf-8\r\n";
const unsigned char index_html[] =
"<!DOCTYPE html> <html > <head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
"<title>Particle Photon RGB LOCAL Remote</title> <script src=\"https://storage.googleapis.com/code.getmdl.io/1.3.0/material.min.js\"></script>"
"<link rel=\"stylesheet\" href=\"https://storage.googleapis.com/code.getmdl.io/1.3.0/material.grey-amber.min.css\">"
"<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/icon?family=Material+Icons\"> <link rel=\"stylesheet\" href=\"css/style.css\">"
"<script src=\"https://www.kasperkamperman.com/import/rangetouch.js\"></script>"
"<script src=\"https://www.kasperkamperman.com/import/content.js\"></script>"
"<script src=\"https://www.kasperkamperman.com/import/index.js\"></script>"
"</head> <body></body> </html> ";
MDNS mdns;
WebServer webserver("", 80);
// brightness perception of the eye is not linair.
// so we use a LookUpTable to for the correct eye response.
// https://gist.github.com/kasperkamperman/3c3f72208366ed885f2f
const uint8_t luminanceLUT[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11,
11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24,
25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34,
35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 45, 46,
47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78,
79, 80, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 96, 97, 99,
100, 101, 103, 104, 106, 107, 108, 110, 111, 113, 114, 116, 118, 119, 121, 122,
124, 125, 127, 129, 130, 132, 134, 135, 137, 139, 141, 142, 144, 146, 148, 149,
151, 153, 155, 157, 159, 161, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
182, 185, 187, 189, 191, 193, 195, 197, 200, 202, 204, 206, 208, 211, 213, 215,
218, 220, 222, 225, 227, 230, 232, 234, 237, 239, 242, 244, 247, 249, 252, 255
};
int hue;
int saturation;
int brightness;
int red;
int green;
int blue;
// store red, green and blue in a character array
// we added time in this version
// because in local host we respond directly with this string.
char rgbTimeString[43];
// pre-declare functions
//int setHSB(String command);
void setHSB(char*);
void convertHSBtoRGB();
void webIndex(WebServer &server, WebServer::ConnectionType type, char *, bool) {
server.httpSuccess();
//server.write(header, sizeof(header));
//server.write(header_content_html, sizeof(header_content_html));
// content length...
// I use sizeof here, because the index_html is set at compile time
// so the length is solid.
server.write(index_html, sizeof(index_html));
//server.printP(page);
//server.print(remote_url + "?url=" + hostname);
//server.printP(tail);
}
void parseCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
bool receivedCmd = false;
if (type == WebServer::POST) {
bool repeat;
char name[16], value[32];
do
{
// readPOSTparam returns false when there are no more parameters
// to read from the input. We pass in buffers for it to store
// the name and value strings along with the length of those
// buffers.
repeat = server.readPOSTparam(name, 16, value, 32);
// this is a standard string comparison function. It returns 0
// when there's an exact match. We're looking for a parameter
// named args
if (strcmp(name, "cmd") == 0) {
receivedCmd = true;
setHSB(value);
}
} while (repeat);
}
if(receivedCmd) {
server.httpSuccess("application/json");
server.print(rgbTimeString);
//server.write(header, sizeof(header));
//server.write(header_content_html, sizeof(header_content_html));
// content length...
// we use strlen here to determine the current length.
// strlen counts to the null byte (written by sprintf)
// sizeof would give the complete buffer length
//server.write((const uint8_t*)rgbTimeString,strlen(rgbTimeString));
//server.print("{\"r\": 255, \"g\": 255, \"b\": 0, \"t\": 1954}");
}
else {
server.httpNoContent();
}
return;
}
void setup() {
//Particle.function("setHSB", setHSB);
//Particle.variable("getRGB", rgbString);
// give your device a local url like
// mylight.local
bool mdns_success = mdns.setHostname(hostname);
if(mdns_success) {
mdns.addService("tcp", "http", 80, hostname);
mdns.begin();
mdns.processQueries();
}
// webserver
webserver.setDefaultCommand(&webIndex);
// just point to the main page in case of a failure
// (not calling / or sethsb/)
webserver.setFailureCommand(&webIndex);
webserver.addCommand("index.html", &webIndex);
webserver.addCommand("sethsb/", &parseCmd);
webserver.begin();
}
void loop() {
mdns.processQueries();
// default buffer of 32 is enough. if you would like to send
// more data create a buffer yourself.
char buff[64];
int len = 64;
webserver.processConnection(buff, &len);
//webserver.processConnection();
if(RGB.controlled()) {
RGB.color(red, green, blue);
}
}
// Particle Cloud Function
//int setHSB(String command) {
void setHSB(char * inputCharArray) {
// split inputCharArray in tokens
char *p = strtok(inputCharArray,",");
// convert string to int
// make sure the value stays in 360 range
hue = constrain(atoi(p),0,359);
// scan for next comma
p = strtok(NULL,",");
saturation = constrain(atoi(p),0,255);
p = strtok(NULL,",");
brightness = constrain(atoi(p),0,255);
p = strtok(NULL,",");
int timeSendFromBrowser = atoi(p);
p = strtok(NULL,",");
// directly convert to rgb
convertHSBtoRGB();
//Convert RGB values to JSON format for easy processing at the browser side
sprintf(rgbTimeString,"{\"r\": %u, \"g\": %u, \"b\": %u, \"t\": %u}",red,green,blue,timeSendFromBrowser);
// if we don't have control yet over the RGB led
// take control
if(RGB.controlled() == false) {
RGB.control(true);
}
}
void convertHSBtoRGB() {
// convert hue, saturation and brightness ( HSB/HSV ) to RGB
int base;
if (saturation == 0) { // Acromatic color (gray). Hue doesn't mind.
red = brightness;
green = brightness;
blue = brightness;
} else {
base = ((255 - saturation) * brightness)>>8;
switch(hue/60) {
case 0:
red = brightness;
green = (((brightness-base)*hue)/60)+base;
blue = base;
break;
case 1:
red = (((brightness-base)*(60-(hue%60)))/60)+base;
green = brightness;
blue = base;
break;
case 2:
red = base;
green = brightness;
blue = (((brightness-base)*(hue%60))/60)+base;
break;
case 3:
red = base;
green = (((brightness-base)*(60-(hue%60)))/60)+base;
blue = brightness;
break;
case 4:
red = (((brightness-base)*(hue%60))/60)+base;
green = base;
blue = brightness;
break;
case 5:
red = brightness;
green = base;
blue = (((brightness-base)*(60-(hue%60)))/60)+base;
break;
}
}
red = luminanceLUT[red];
green = luminanceLUT[green];
blue = luminanceLUT[blue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment