WiFi RGB Lamp Web Server

Dependencies:   mbed ESP8266_WebServer

RGB WiFi Lamp

Firmware

This is the official firmware repository for the BinarySpace RGB WiFi Lamp project. This firmware is still in alpha stage, and subject to change.

Planned changes include:

  • Configure the WiFi Lamp to connect onto your SSID
  • Variety of operating modes like
    • Fixed colour operation
    • Rainbow gradient
    • Time-based colour changing
    • API-based colour changing

Connecting to the WiFi lamp

To connect to the WiFi lamp web server, scan for an open WiFi network using your cellphone, tablet or laptop that begins with the letters ESP_xxxxxx. This is the automatically created SSID of the ESP8266 WiFi module used in the lamp. Your WiFi client needs to be configured to use DHCP.

Once connected, simply point your browser at http://192.168.4.1 and you should see the rudementary web interface allowing you to switch the WiFi lamp on in the red colour or off.

A second option is to enter the following URL
http://192.168.4.1/setcolor?r=x&g=x&b=x
where x is a number between 0 and 255 for the intensity of (r)ed, (g)reen and (b)lue respectively. Any of the r,g,b parts not specified will automatically default to 0

Supported Platforms

  • ST Nucleo F103RB
  • ST Nucleo F302R8
  • ST Nucleo L152RE
  • ST Nucleo F401RE

Unsupported Platforms

  • ST Nucleo F030R8 (unsupported due to insufficient registers for PololuLed library)

How to update your firmware

One of the best things about the ST Nucleo series is that they enumerate as a USB Mass Storage device when plugged in. Updating the firmware is as simple as compiling it using mbed compiler(free registration required to use) for your selected platform, plugging in your Nucleo and copying the .bin file created by the compiler to the USB drive enumerated by the Nucleo. That's it!

Code is fully Open Source

Please feel free to fork this repository and to submit pull requests if you make any cool additions/changes.

If you are developing changes to the firmware and monitoring via serial console for debugging purposes, note than you can simply comment out the #define DEBUG_WIFI line at the top of the main.cpp file to make the output much less verbose. This effectively disables debugging of the WebServer library code and echoing of communications between the Nucleo and the ESP. It also makes the web server noticeably faster, as it doesn't have to output a lot of serial data before handling requests.

LED Strip colour inconsistency

If you are experiencing problems with the LED's not all changing colour, or perhaps flickering or incorrect colour, there could be 2 potential problems we have identified.

  • Power Supply problems - If the power supply is not providing enough power, or not clean enough power, you may experience flickering or random colour changes. Ensure that your power supply can provide enough power (1A @ 5V recommended). If this does not solve your problem, soldering a capacitor over the power supply lines(5V, GND) may help to clean out any noise from the power supply. (100uF minimum)
  • Depending on cable lengths and connectors, noise on the data line may also be a problem. Try soldering a 100Ω - 500Ω resistor in line on the Din pin of the LED strip

Firmware update for the ESP8266 Module

We suggest you upgrade the firmware on the ESP8266 module to the latest official AT firmware from Espressif. Click Here for a detailed upgrade quide.

Committer:
sschocke
Date:
Sun Jan 04 12:15:05 2015 +0000
Revision:
23:3563e1699fb9
Parent:
22:6d7a72fab8ff
Child:
24:849265425708
Added config screen functionality; Updated Color Picker to be more bandwidth and RAM friendly; Merged in latest WebServer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sschocke 0:d21e3e1c0a4b 1 #include "mbed.h"
sschocke 1:f07afcffeb5a 2 #include "PololuLedStrip.h"
sschocke 7:f15c81074400 3 #include "ESP8266_WebServer.h"
sschocke 22:6d7a72fab8ff 4 #include "resource.h"
sschocke 0:d21e3e1c0a4b 5 #include <string>
sschocke 13:1e8f27da036a 6 //#define DEBUG_WIFI
sschocke 0:d21e3e1c0a4b 7
sschocke 8:f819de1946a7 8 PololuLedStrip ledStrip(D11);
sschocke 1:f07afcffeb5a 9
sschocke 8:f819de1946a7 10 #define LED_COUNT 8
sschocke 1:f07afcffeb5a 11 rgb_color colors[LED_COUNT];
sschocke 1:f07afcffeb5a 12
sschocke 0:d21e3e1c0a4b 13 DigitalOut wifiCHPD(D4);
sschocke 0:d21e3e1c0a4b 14 DigitalOut wifiReset(D9);
sschocke 0:d21e3e1c0a4b 15
sschocke 0:d21e3e1c0a4b 16 int wifiOn = 0;
sschocke 23:3563e1699fb9 17 int opMode = 0;
sschocke 23:3563e1699fb9 18 std::string stationMAC;
sschocke 23:3563e1699fb9 19 std::string stationIP;
sschocke 23:3563e1699fb9 20 std::string ssid;
sschocke 23:3563e1699fb9 21 std::string apMAC;
sschocke 23:3563e1699fb9 22 std::string apIP;
sschocke 0:d21e3e1c0a4b 23
sschocke 0:d21e3e1c0a4b 24 Serial wifiSerial(D8,D2);
sschocke 0:d21e3e1c0a4b 25 Serial pc(USBTX,USBRX);
sschocke 7:f15c81074400 26 ESP8266_WebServer server(&wifiSerial);
sschocke 0:d21e3e1c0a4b 27
sschocke 22:6d7a72fab8ff 28 char temp[200];
sschocke 23:3563e1699fb9 29 const char* VERSION = "0.5-alpha";
sschocke 20:f5a6527bfda6 30
sschocke 20:f5a6527bfda6 31 #ifdef DEBUG_WIFI
sschocke 20:f5a6527bfda6 32 void pcrxint(void) {
sschocke 23:3563e1699fb9 33 //server.debugBuffers(&pc);
sschocke 23:3563e1699fb9 34 pc.putc('@');
sschocke 20:f5a6527bfda6 35 server.echoMode = true;
sschocke 20:f5a6527bfda6 36 }
sschocke 20:f5a6527bfda6 37 #endif
sschocke 20:f5a6527bfda6 38
sschocke 7:f15c81074400 39 void rxint(void) {
sschocke 7:f15c81074400 40 server.rxint();
sschocke 0:d21e3e1c0a4b 41 }
sschocke 0:d21e3e1c0a4b 42
tomvdb 4:4a502f72cbe3 43 void setColor( uint8_t r, uint8_t g, uint8_t b )
tomvdb 4:4a502f72cbe3 44 {
tomvdb 4:4a502f72cbe3 45 for ( int c = 0; c < LED_COUNT; c++ )
tomvdb 4:4a502f72cbe3 46 {
tomvdb 4:4a502f72cbe3 47 colors[c].red = r;
tomvdb 4:4a502f72cbe3 48 colors[c].green = g;
tomvdb 4:4a502f72cbe3 49 colors[c].blue = b;
tomvdb 4:4a502f72cbe3 50 }
tomvdb 4:4a502f72cbe3 51
tomvdb 4:4a502f72cbe3 52 ledStrip.write(colors, LED_COUNT);
tomvdb 4:4a502f72cbe3 53 }
tomvdb 4:4a502f72cbe3 54
sschocke 23:3563e1699fb9 55 void sendConfigJSONReply(int linkID, const char* result) {
sschocke 23:3563e1699fb9 56 sprintf(temp, jsonConfigReply, opMode, stationIP.c_str(), ssid.c_str(), result);
sschocke 23:3563e1699fb9 57 server.SendReply(linkID, temp, mimeJSON, 0);
sschocke 23:3563e1699fb9 58 }
sschocke 23:3563e1699fb9 59
sschocke 0:d21e3e1c0a4b 60 int main() {
sschocke 13:1e8f27da036a 61 pc.baud(115200);
sschocke 20:f5a6527bfda6 62 #ifdef DEBUG_WIFI
sschocke 20:f5a6527bfda6 63 pc.attach(&pcrxint);
sschocke 20:f5a6527bfda6 64 #endif
leet 10:f48a9f923271 65
sschocke 23:3563e1699fb9 66 pc.printf("WiFi Lamp - %s...\r\n", VERSION);
leet 10:f48a9f923271 67
sschocke 13:1e8f27da036a 68 setColor( 25, 0, 0);
tomvdb 4:4a502f72cbe3 69
sschocke 0:d21e3e1c0a4b 70 wifiCHPD = 0;
sschocke 0:d21e3e1c0a4b 71 wifiReset = 0;
sschocke 13:1e8f27da036a 72 wifiSerial.baud(115200);
sschocke 0:d21e3e1c0a4b 73 wifiSerial.attach(&rxint);
sschocke 7:f15c81074400 74 #ifdef DEBUG_WIFI
sschocke 7:f15c81074400 75 server.debugSerial = &pc;
sschocke 7:f15c81074400 76 #endif
sschocke 0:d21e3e1c0a4b 77 wait_ms(1000);
sschocke 0:d21e3e1c0a4b 78
sschocke 0:d21e3e1c0a4b 79 pc.printf("Powering WiFi...\r\n");
sschocke 0:d21e3e1c0a4b 80 wifiCHPD = 1;
sschocke 13:1e8f27da036a 81 wifiReset = 1;
sschocke 0:d21e3e1c0a4b 82 wait_ms(250);
sschocke 0:d21e3e1c0a4b 83 pc.printf("Hardware Reset WiFi...\r\n");
sschocke 0:d21e3e1c0a4b 84 wifiOn = 1;
sschocke 0:d21e3e1c0a4b 85
sschocke 23:3563e1699fb9 86 std::string fwVer = server.GetFirmwareVersion();
sschocke 23:3563e1699fb9 87 pc.printf("ESP Firmware Version: %s\r\n", fwVer.c_str());
sschocke 23:3563e1699fb9 88
sschocke 7:f15c81074400 89 pc.printf("Starting Web Server...\r\n");
sschocke 7:f15c81074400 90 server.Initialize();
sschocke 23:3563e1699fb9 91 pc.printf("Done\r\n");
sschocke 23:3563e1699fb9 92
sschocke 23:3563e1699fb9 93 opMode = server.GetOperatingMode();
sschocke 23:3563e1699fb9 94 pc.printf("Operating Mode: %s(%d)\r\n", opModes[opMode], opMode);
sschocke 23:3563e1699fb9 95 if( (opMode & OPMODE_STATION) ) {
sschocke 23:3563e1699fb9 96 pc.printf("Waiting 5 secs for join to WiFi Network...\r\n");
sschocke 23:3563e1699fb9 97 wait_ms(5000);
sschocke 23:3563e1699fb9 98 stationMAC = server.GetStationMAC();
sschocke 23:3563e1699fb9 99 stationIP = server.GetStationIP();
sschocke 23:3563e1699fb9 100 ssid = server.GetStationSSID();
sschocke 23:3563e1699fb9 101 pc.printf("Station MAC: %s, Station SSID: %s, Station IP: %s\r\n", stationMAC.c_str(), ssid.c_str(), stationIP.c_str());
sschocke 23:3563e1699fb9 102 }
sschocke 23:3563e1699fb9 103 if( (opMode & OPMODE_SOFTAP) ) {
sschocke 23:3563e1699fb9 104 apMAC = server.GetAPMAC();
sschocke 23:3563e1699fb9 105 apIP = server.GetAPIP();
sschocke 23:3563e1699fb9 106 pc.printf("SoftAP MAC: %s, SoftAP IP: %s\r\n", apMAC.c_str(), apIP.c_str());
sschocke 23:3563e1699fb9 107 }
sschocke 23:3563e1699fb9 108
sschocke 23:3563e1699fb9 109 //std::list<std::string> apList = server.ListAvailableSSID();
sschocke 23:3563e1699fb9 110
sschocke 23:3563e1699fb9 111 //for( std::list<std::string>::iterator it = apList.begin(); it!=apList.end(); ++it ) {
sschocke 23:3563e1699fb9 112 // pc.printf("Found SSID %s\r\n", (*it).c_str());
sschocke 23:3563e1699fb9 113 //}
sschocke 0:d21e3e1c0a4b 114
sschocke 13:1e8f27da036a 115 setColor( 0, 25, 0);
tomvdb 4:4a502f72cbe3 116 wait_ms(500);
tomvdb 4:4a502f72cbe3 117 setColor( 0, 0, 0);
tomvdb 4:4a502f72cbe3 118
sschocke 23:3563e1699fb9 119 std::string httpReply;
sschocke 0:d21e3e1c0a4b 120 while(true) {
sschocke 9:319aeb6e0123 121 ESP8266_WebRequest* request = server.GetRequest();
sschocke 9:319aeb6e0123 122 if( request != NULL ) {
sschocke 9:319aeb6e0123 123 pc.printf("HTTP %s %s\r\n", request->Method.c_str(), request->URI.c_str());
sschocke 9:319aeb6e0123 124 for( std::map<std::string,std::string>::iterator it = request->Parameters.begin(); it!=request->Parameters.end(); ++it ) {
sschocke 9:319aeb6e0123 125 pc.printf("HTTP Parameter %s = %s\r\n", it->first.c_str(), it->second.c_str());
sschocke 9:319aeb6e0123 126 }
sschocke 9:319aeb6e0123 127 if( request->URI == "/" ) {
sschocke 23:3563e1699fb9 128 httpReply = htmlHead;
sschocke 23:3563e1699fb9 129 httpReply += "<table><tr><td align='right'><a href='config'><img src='config.gif' /></a></td></tr>";
sschocke 23:3563e1699fb9 130 httpReply += "<tr><td align='center'>";
sschocke 23:3563e1699fb9 131 httpReply += "<img style='margin-right:2px' src='colormap.gif' usemap='#colormap' />";
sschocke 23:3563e1699fb9 132 httpReply += "<map id='colormap' name='colormap'>";
sschocke 23:3563e1699fb9 133 //int startx = 63;
sschocke 23:3563e1699fb9 134 //int countx = 7;
sschocke 23:3563e1699fb9 135 //for( int y=0; y<=180; y+=15) {
sschocke 23:3563e1699fb9 136 // int endx = startx + (countx*18);
sschocke 23:3563e1699fb9 137 // for( int x=startx; x<endx; x+= 18) {
sschocke 23:3563e1699fb9 138 // sprintf(temp, areaHTML, x,y, x+9,y+4, x+9,y+15, x,y+19, x-9,y+15, x-9,y+4);
sschocke 23:3563e1699fb9 139 // httpReply += temp;
sschocke 23:3563e1699fb9 140 // }
sschocke 23:3563e1699fb9 141 // if( y < 90 ) {
sschocke 23:3563e1699fb9 142 // startx -= 9;
sschocke 23:3563e1699fb9 143 // countx++;
sschocke 23:3563e1699fb9 144 // } else {
sschocke 23:3563e1699fb9 145 // startx += 9;
sschocke 23:3563e1699fb9 146 // countx--;
sschocke 23:3563e1699fb9 147 // }
sschocke 23:3563e1699fb9 148 //}
sschocke 23:3563e1699fb9 149 httpReply += "</map></td></tr><tr><td><span onClick=\"changeColor('#000000')\">Turn Off</span></td></tr></table>";
sschocke 23:3563e1699fb9 150 httpReply += htmlTail;
sschocke 23:3563e1699fb9 151 server.SendReply(request->LinkID, httpReply, mimeHTML);
sschocke 23:3563e1699fb9 152 } else if( request->URI == "/config" ) {
sschocke 23:3563e1699fb9 153 if( (opMode & OPMODE_STATION) ) {
sschocke 23:3563e1699fb9 154 stationIP = server.GetStationIP();
sschocke 23:3563e1699fb9 155 ssid = server.GetStationSSID();
sschocke 23:3563e1699fb9 156 }
sschocke 23:3563e1699fb9 157 httpReply = htmlHead;
sschocke 23:3563e1699fb9 158 httpReply += htmlConfigHTML;
sschocke 23:3563e1699fb9 159 httpReply += htmlTail;
sschocke 23:3563e1699fb9 160 httpReply = httpReply.replace(httpReply.find("%opmode1%"), 9, (opMode==1? " selected" : ""));
sschocke 23:3563e1699fb9 161 httpReply = httpReply.replace(httpReply.find("%opmode2%"), 9, (opMode==2? " selected" : ""));
sschocke 23:3563e1699fb9 162 httpReply = httpReply.replace(httpReply.find("%opmode3%"), 9, (opMode==3? " selected" : ""));
sschocke 23:3563e1699fb9 163 httpReply = httpReply.replace(httpReply.find("%stamac%"), 8, stationMAC);
sschocke 23:3563e1699fb9 164 httpReply = httpReply.replace(httpReply.find("%staip%"), 7, stationIP);
sschocke 23:3563e1699fb9 165 httpReply = httpReply.replace(httpReply.find("%apmac%"), 7, apMAC);
sschocke 23:3563e1699fb9 166 httpReply = httpReply.replace(httpReply.find("%apip%"), 6, apIP);
sschocke 23:3563e1699fb9 167 httpReply = httpReply.replace(httpReply.find("%ssid%"), 6, ssid);
sschocke 23:3563e1699fb9 168 server.SendReply(request->LinkID, httpReply, mimeHTML, 0);
sschocke 23:3563e1699fb9 169 } else if( request->URI == "/updateconfig" ) {
sschocke 23:3563e1699fb9 170 bool result = true;
sschocke 23:3563e1699fb9 171 int newOpMode = atoi(request->Parameters["opmode"].c_str());
sschocke 23:3563e1699fb9 172 std::string newSSID = request->Parameters["ssid"];
sschocke 23:3563e1699fb9 173 std::string newPassword = request->Parameters["pwd"];
sschocke 23:3563e1699fb9 174 if( newOpMode != opMode ) {
sschocke 23:3563e1699fb9 175 result = server.SetOperatingMode(newOpMode);
sschocke 23:3563e1699fb9 176 if( result == false ) {
sschocke 23:3563e1699fb9 177 sendConfigJSONReply(request->LinkID, "Error setting Operating Mode");
sschocke 23:3563e1699fb9 178 delete request;
sschocke 23:3563e1699fb9 179 continue;
sschocke 22:6d7a72fab8ff 180 }
sschocke 23:3563e1699fb9 181 opMode = newOpMode;
sschocke 23:3563e1699fb9 182 }
sschocke 23:3563e1699fb9 183 if( (opMode & OPMODE_STATION) ) {
sschocke 23:3563e1699fb9 184 if( (ssid.compare(newSSID) != 0) || (newPassword.empty() == false) ) {
sschocke 23:3563e1699fb9 185 result = server.SetStationSSID(newSSID, newPassword);
sschocke 23:3563e1699fb9 186 if( result == false ) {
sschocke 23:3563e1699fb9 187 sendConfigJSONReply(request->LinkID, "Error connecting to SSID");
sschocke 23:3563e1699fb9 188 delete request;
sschocke 23:3563e1699fb9 189 continue;
sschocke 23:3563e1699fb9 190 }
sschocke 23:3563e1699fb9 191 // Wait for SSID to connect
sschocke 23:3563e1699fb9 192 for( int retries=0; retries < 6; retries++) {
sschocke 23:3563e1699fb9 193 wait_ms(5000);
sschocke 23:3563e1699fb9 194 ssid = server.GetStationSSID();
sschocke 23:3563e1699fb9 195 if( ssid.compare(newSSID) == 0 ) {
sschocke 23:3563e1699fb9 196 break;
sschocke 23:3563e1699fb9 197 }
sschocke 23:3563e1699fb9 198 }
sschocke 23:3563e1699fb9 199 stationIP = server.GetStationIP();
sschocke 22:6d7a72fab8ff 200 }
sschocke 22:6d7a72fab8ff 201 }
sschocke 23:3563e1699fb9 202 sendConfigJSONReply(request->LinkID, "Success");
sschocke 20:f5a6527bfda6 203 } else if( request->URI == "/wifilamp.js" ) {
sschocke 20:f5a6527bfda6 204 server.SendReply(request->LinkID, javascript, strlen(javascript), mimeJavaScript);
sschocke 20:f5a6527bfda6 205 } else if( request->URI == "/wifilamp.css" ) {
sschocke 20:f5a6527bfda6 206 server.SendReply(request->LinkID, css, strlen(css), mimeCSS);
sschocke 22:6d7a72fab8ff 207 } else if( request->URI == "/colormap.gif" ) {
sschocke 23:3563e1699fb9 208 server.SendReply(request->LinkID, (char*)colormap, sizeof(colormap), mimeGIF);
sschocke 23:3563e1699fb9 209 } else if( request->URI == "/config.gif" ) {
sschocke 23:3563e1699fb9 210 server.SendReply(request->LinkID, (char*)configIcon, sizeof(configIcon), mimeGIF);
leet 16:f2f2da9ef9ab 211 } else if( request->URI == "/setcolour" || request->URI == "/setcolor" ) {
sschocke 7:f15c81074400 212 int r=0, g=0, b=0;
sschocke 9:319aeb6e0123 213
sschocke 9:319aeb6e0123 214 if(request->Parameters.count("r") > 0) r=atoi(request->Parameters["r"].c_str());
sschocke 9:319aeb6e0123 215 if(request->Parameters.count("g") > 0) g=atoi(request->Parameters["g"].c_str());
sschocke 9:319aeb6e0123 216 if(request->Parameters.count("b") > 0) b=atoi(request->Parameters["b"].c_str());
sschocke 7:f15c81074400 217
leet 16:f2f2da9ef9ab 218 pc.printf( "Set colour to (%i, %i, %i)\r\n", r,g,b);
sschocke 0:d21e3e1c0a4b 219
sschocke 7:f15c81074400 220 setColor( r,g,b );
sschocke 7:f15c81074400 221
sschocke 23:3563e1699fb9 222 server.SendReply(request->LinkID, "OK", mimeText, 0);
sschocke 7:f15c81074400 223 } else {
sschocke 11:3ab606a42227 224 server.Send404Error(request->LinkID);
sschocke 0:d21e3e1c0a4b 225 }
sschocke 7:f15c81074400 226 pc.printf("\r\nHTTP Reply Sent\r\n");
sschocke 9:319aeb6e0123 227 delete request;
sschocke 0:d21e3e1c0a4b 228 }
sschocke 0:d21e3e1c0a4b 229 }
sschocke 0:d21e3e1c0a4b 230 }