|
/************************************************************* |
|
Hue @ Lolin D32 Pro (ESP32) |
|
Basic demo of switch based on touch TFT display to demonstrate |
|
communication between ESP and Hue gateway |
|
Version: 1.00 |
|
by Petr Lukas |
|
|
|
Functionality: |
|
Touch a button on TFT to switch on and off the lights. |
|
*************************************************************/ |
|
#include <WiFi.h> |
|
#include <HTTPClient.h> |
|
|
|
#include <Adafruit_GFX.h> |
|
#include <Adafruit_ImageReader.h> |
|
#include <Adafruit_ILI9341.h> |
|
|
|
#include <SPI.h> |
|
#include <SD.h> |
|
|
|
// Touchscreen library |
|
#include <XPT2046_Touchscreen.h> |
|
|
|
// Fonts |
|
#include <Fonts/FreeMono9pt7b.h> |
|
#include <Fonts/FreeSansBold9pt7b.h> |
|
#include <Fonts/FreeSansBold12pt7b.h> |
|
|
|
// Default pin numbers for D32 Pro |
|
#define TFT_CS 14 |
|
#define TFT_DC 27 |
|
#define TFT_RST 33 |
|
#define TS_CS 12 |
|
|
|
// SD card pin |
|
#define SD_CS 4 |
|
|
|
// IP of Hue gateway |
|
String ip = "YOUR_HUE_BRIDGE_IP"; |
|
|
|
// Hue gateway user name |
|
String user_name = "YOUR_HUE_AUTHORIZED_USER"; |
|
|
|
// Wifi network SSID |
|
const char* ssid = "YOUR_SSID"; |
|
|
|
// Wifi network password |
|
const char* password = "YOUR_PASSWORD"; |
|
|
|
// Power consumtion per bulb |
|
float consumption = 8.5; // Let's assume consumption of bulb in full light is 8.5 W |
|
|
|
|
|
unsigned long previousMillis = 0; |
|
bool state1 = false; |
|
bool state2 = false; |
|
bool state3 = false; |
|
float total_consumption = 0; |
|
int runtime = 0; |
|
|
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); |
|
Adafruit_ImageReader reader; |
|
XPT2046_Touchscreen ts(TS_CS); |
|
|
|
void setup() { |
|
// put your setup code here, to run once: |
|
Serial.begin(115200); |
|
tft.begin(); |
|
tft.setFont(&FreeMono9pt7b); |
|
tft.fillScreen(ILI9341_BLACK); |
|
tft.setCursor(0, 15); |
|
|
|
tft.println("Init SD card..."); |
|
if (!SD.begin(SD_CS)) { |
|
tft.setTextColor(ILI9341_RED); |
|
Serial.println("SD card failed"); |
|
tft.println("Failed!"); |
|
delay(999999); |
|
return; |
|
} |
|
|
|
WiFi.begin(ssid, password); |
|
|
|
tft.println("Connecting to WiFi"); |
|
Serial.print("Connecting to WiFi"); |
|
while (WiFi.status() != WL_CONNECTED) { |
|
delay(1000); |
|
Serial.print("."); |
|
} |
|
Serial.println("Connected to the WiFi network"); |
|
tft.println("Success"); |
|
delay(500); |
|
|
|
tft.println("Init touchscreen..."); |
|
ts.begin(); |
|
|
|
tft.println("Setup complete"); |
|
tft.println("Starting loop..."); |
|
delay(500); |
|
|
|
tft.fillScreen(ILI9341_BLACK); |
|
drawButtons(); |
|
} |
|
void switchLight(byte light_id, bool current_state, int x, int y){ |
|
HTTPClient http; |
|
String req_string; |
|
req_string = "http://"; |
|
req_string += ip; |
|
req_string += "/api/"; |
|
req_string += user_name; |
|
req_string += "/lights/"; |
|
req_string += light_id; |
|
req_string += "/state"; |
|
Serial.println(req_string); |
|
http.begin(req_string); |
|
http.addHeader("Content-Type", "text/plain"); |
|
|
|
String put_string; |
|
put_string = "{\"on\":"; |
|
put_string += (current_state)? "true" : "false"; |
|
put_string += "}"; |
|
|
|
int httpResponseCode = http.PUT(put_string); |
|
|
|
// Change button only in case the operation is successfull |
|
if(httpResponseCode == 200){ |
|
toggleButton(x,y,current_state); |
|
} |
|
|
|
if(httpResponseCode > 0){ |
|
String response = http.getString(); |
|
Serial.println(httpResponseCode); |
|
Serial.println(response); |
|
} else { |
|
Serial.print("Error on sending PUT Request: "); |
|
Serial.println(httpResponseCode); |
|
} |
|
http.end(); |
|
} |
|
|
|
void drawButtons(){ |
|
int y = 115; |
|
int y_space = 60; |
|
|
|
reader.drawBMP("/wemos.bmp", tft, 10, 20); |
|
reader.drawBMP("/hue.bmp", tft, 180, 20); |
|
reader.drawBMP("/off.bmp", tft, 130, y); |
|
reader.drawBMP("/off.bmp", tft, 130, y + y_space); |
|
reader.drawBMP("/off.bmp", tft, 130, y + y_space*2); |
|
|
|
tft.setFont(&FreeSansBold12pt7b); |
|
|
|
y = y + 22; |
|
|
|
tft.setCursor(3, y); |
|
tft.println("Hall:"); |
|
|
|
tft.setCursor(3, y + y_space); |
|
tft.println("Bedroom:"); |
|
|
|
tft.setCursor(3, y + y_space*2); |
|
tft.println("Bathroom:"); |
|
|
|
tft.setFont(&FreeSansBold9pt7b); |
|
tft.setCursor(50, 310); |
|
tft.println("0.00 Wh | 0 min"); |
|
} |
|
|
|
void toggleButton(int x, int y, bool state){ |
|
if(state){ |
|
reader.drawBMP("/on.bmp", tft, x, y); |
|
} else { |
|
reader.drawBMP("/off.bmp", tft, x, y); |
|
} |
|
} |
|
|
|
void loop() { |
|
unsigned long currentMillis = millis(); |
|
if (currentMillis - previousMillis >= 1000){ |
|
if(state1)total_consumption += consumption/3600; |
|
if(state2)total_consumption += consumption/3600; |
|
if(state3)total_consumption += consumption/3600; |
|
|
|
runtime++; |
|
|
|
tft.setFont(&FreeSansBold9pt7b); |
|
tft.setCursor(50, 310); |
|
tft.fillRect(0,285,240,320,ILI9341_BLACK); |
|
tft.print(total_consumption,2); |
|
tft.print(" Wh | "); |
|
tft.print(runtime/60); |
|
tft.print(" min"); |
|
previousMillis = currentMillis; |
|
} |
|
|
|
if (ts.touched()) { |
|
TS_Point p = ts.getPoint(); |
|
// You need to test coordinates (in this case landscape oriented) |
|
/* |
|
tft.setCursor(0,50); |
|
tft.fillRect(0,30,100,50,ILI9341_BLACK); |
|
tft.println(p.x); |
|
tft.println(p.y); |
|
*/ |
|
if((p.x < 2500 && p.x > 2000) && (p.y < 1800 && p.y > 300)){ |
|
state1 = !state1; |
|
switchLight(1, state1, 130, 115); |
|
} |
|
if((p.x < 2000 && p.x > 1500) && (p.y < 1800 && p.y > 300)){ |
|
state2 = !state2; |
|
switchLight(2, state2, 130, 175); |
|
} |
|
if((p.x < 1500 && p.x > 1000) && (p.y < 1800 && p.y > 300)){ |
|
state3 = !state3; |
|
switchLight(3, state3, 130, 235); |
|
} |
|
delay(500); |
|
} |
|
} |