-
-
Save kasperkamperman/6590c7966d1963e6f8ae9968a43bed06 to your computer and use it in GitHub Desktop.
temporary version local
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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