Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- esp8266Huemotion
- https://github.com/LeskoIam/esp8266Huemotion
- Used instead of very expensive Hue motion sensor.
- It's basicly a D1 mini, which breaks out pins from esp8266 WiFi module and adds some
- periphery to enable USB serial communication.
- Operation:
- It uses PIR sensor attached to pin D1 (arduino library maps this pin to pin 5) to
- detect motion and turn on specified Hue light bulb if all conditions are met. These
- conditions are:
- - It's night time. This is determined based on if specified light bulb is on or off.
- State of the light bulb is checked and updated every set number of minutes
- ("lights_check_delay").
- - If motion is detected. Specified light bulb is turned on for set amount of time
- ("motion_detected_delay"). Motion is still detected and updated when light is turned on,
- this means light is turned off only after no motion is detected for set delay.
- Deep sleep:
- If enabled, you can put module to sleep while "lights_check_delay" is active. It can conserve
- a lot of power and is specialy useful when module is powered with batteries. This is controlled
- with "use_deep_sleep" variable.
- Minor hardware modification is also necessary. Connect D0 pin to RST pin. This connection is
- used to wake up the module after sleep period is over.
- The circuit:
- - Philips Hue lights
- - D1 mini or clone (esp8266).
- - PIR motion sensor (HC-SR501).
- Settings:
- Look for code in #### block.
- Mandatory settings:
- - use_deep_sleep
- - ssid
- - password
- - bridge_ip, port
- - user
- - light
- Optional:
- - motion_detected_delay
- - lights_check_delay
- - hue_on
- - hue_off
- */
- #include <ESP8266WiFi.h>
- #include <time.h>
- //// Global settings and variables
- // ################################################
- // Deep Sleep
- boolean use_deep_sleep = 0; // If deep sleep is enable don't forget to connect D0 to RST pin
- // Wifi Settings
- const char* ssid = "";
- const char* password = "";
- // Hue settings
- const char* bridge_ip = ""; // Hue bridge IP
- const int port = 80;
- String user = "newdeveloper";
- String light = "21"; // Number of the light you want to control
- // Motion timing
- unsigned long motion_detected_time = 0; // When was motion last detected
- unsigned long motion_detected_delay = 240*1000; // Keep light on for that many seconds after last motion was detected
- // All lights off check timing
- unsigned long lights_check_time = 0; // When was light state last checked
- unsigned long lights_check_delay = 5*60*1000; // Check light state every that many minutes
- // Commands
- String hue_on = "{\"on\":true, \"bri\":255}";
- String hue_on2 = "{\"on\":true, \"bri\":120}";
- String hue_off = "{\"on\":false}";
- // ################################################
- int timezone = 0 * 3600; // change first value for your utc offset
- int dst = 3600 ; // change to 0 for no daylight savings.
- // Pin settings
- // PIR sensor is attached to D1 mini D1 pin which maps to pin 5 for arduino library
- int pirPin = 5;
- int light_state = 0; // Internally track state of light
- int first_loop = 1; // Is this first loop
- int check_lights_first_loop = 1; // Same as above but for checking light state
- bool night_time; // master logic variable
- void setup()
- {
- Serial.begin(115200);
- delay(10);
- // Connect to WiFi network
- Serial.println();
- Serial.println();
- Serial.print("Connecting to ");
- Serial.println(ssid);
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED)
- {
- delay(500);
- Serial.print(".");
- }
- Serial.println();
- Serial.println("WiFi connected");
- Serial.print("IP address: ");
- Serial.println(WiFi.localIP());
- Serial.println();
- Serial.print("MAC: ");
- Serial.println(WiFi.macAddress());
- // Set PIR pin as input pin
- pinMode(pirPin, INPUT);
- if (use_deep_sleep)
- {
- // Connect D0 to RST to wake up
- pinMode(16, WAKEUP_PULLUP);
- }
- Serial.println("Waiting 2 seconds for stable sensor readings...");
- delay(1000);
- Serial.println("Setup done. Main loop starting in a second...");
- delay(1000);
- Serial.println();
- configTime(timezone, dst, "uk.pool.ntp.org");
- Serial.println ("\nWaiting for Internet Time");
- while(!time(nullptr)){
- Serial.print("*");
- delay(1000);
- }
- Serial.println("\nTime response....OK");
- }
- void loop()
- {
- //// Check state of the light and set nigh_time accordingly
- if ((((lights_check_time + lights_check_delay) < millis()) || check_lights_first_loop == 1) && (light_state != 1))
- {
- Serial.print("Checking state of light ");
- Serial.println(light);
- check_lights_first_loop = 0;
- if (is_light_on() == 1) { night_time = 0; }
- else { night_time = 1; }
- lights_check_time = millis();
- if (use_deep_sleep)
- {
- if (!night_time)
- {
- // Go to deep sleep. Don't forget to convert milliseconds to microseconds
- Serial.printf("\nDEEP SLEEP for %i microseconds\n\n", lights_check_delay*1000);
- ESP.deepSleep(lights_check_delay * 1000);
- }
- }
- }
- // Some debug prints
- Serial.println("-----");
- Serial.print("night_time: ");
- Serial.println(night_time);
- Serial.print("motion_detected_time: ");
- Serial.println(motion_detected_time);
- Serial.print("light_state: ");
- Serial.println(light_state);
- time_t now = time(nullptr);
- struct tm* p_tm = localtime(&now);
- Serial.print(p_tm->tm_mday);
- Serial.print("/");
- Serial.print(p_tm->tm_mon + 1);
- Serial.print("/");
- Serial.print(p_tm->tm_year + 1900);
- Serial.print(" ");
- Serial.print(p_tm->tm_hour);
- Serial.print(":");
- if ((p_tm->tm_min) < 10) {Serial.print("0");}
- Serial.print(p_tm->tm_min);
- Serial.print(":");
- if ((p_tm->tm_sec) < 10) {Serial.print("0");}
- Serial.println(p_tm->tm_sec);
- //// Main motion-light logic
- // Enter only if it is nigh time and ligh is not on because of us
- if ((night_time == 1) || (light_state == 1))
- {
- // Read PIR sensor
- int motion = digitalRead(pirPin);
- Serial.print("motion: ");
- Serial.println(motion);
- // If motion is detected
- if (motion == HIGH)
- {
- // And light is off because of us.
- // This also prevents multiple turn ons (sensor output stays on for around 2 seconds)
- if (light_state == 0)
- {
- // Turn light on only if previous on time delay has passed or if this is first loop
- // first_loop check was added to handle situation when motion-light has
- // not yet been running for more than motion delay time
- if (((motion_detected_time + motion_detected_delay) < millis()) || first_loop == 1)
- {
- if ((p_tm->tm_hour <= 23) && (p_tm->tm_hour >= 17)) {Serial.println("Turning light on");
- light_control(hue_on); }
- else if ((p_tm->tm_hour <= 5) || (p_tm->tm_hour == 0)) {Serial.println("Turning light on low");
- light_control(hue_on2);}
- light_state = 1;
- first_loop = 0;
- }
- }
- // Detect every motion and update detection time
- motion_detected_time = millis();
- }
- else
- {
- // Only turn off light if they were turned on by us
- if (light_state == 1)
- {
- // Turn light off only if on time delay has passed
- if ((motion_detected_time + motion_detected_delay) < millis())
- {
- Serial.print("No motion for ");
- Serial.print(motion_detected_delay/1000);
- Serial.println(" seconds. Turning light off");
- light_control(hue_off);
- light_state = 0;
- }
- }
- }
- }
- delay(333);
- }
- /* light_control.
- * Send PUT command to hue light (bridge). Function takes json formated command.
- * Returns:
- * 1 if operation successful
- * 0 if operation not successful
- * -1 if error occurred
- */
- bool light_control(String command)
- {
- int retval = 0; // return value
- WiFiClient client; // WiFiClient class to create TCP connections
- if (!client.connect(bridge_ip, port))
- {
- Serial.println("ERR>> light_control - Connection failed");
- return -1;
- }
- // This will send PUT request to the server
- client.println("PUT /api/" + user + "/lights/" + light + "/state HTTP/1.1");
- client.println("Host: " + String(bridge_ip) + ":" + String(port));
- client.println("User-Agent: ESP8266/1.0");
- client.println("Connection: keep-alive");
- client.println("Content-type: text/xml; charset=\"utf-8\"");
- client.print("Content-Length: ");
- client.println(command.length()); // PUT COMMAND HERE
- client.println();
- client.println(command); // PUT COMMAND HERE
- // Wait 10 seconds for server to respond
- unsigned long timeout = millis();
- while (client.available() == 0)
- {
- if (millis() - timeout > 10000)
- {
- Serial.println("ERR>> light_control - Client timeout");
- client.stop();
- return -1;
- }
- }
- // Read all the lines of the reply from server
- while(client.available())
- {
- String line = client.readStringUntil('\r');
- // Print line to serial if it's request status or json formated string
- if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
- // If success string is found in reply we have successfully sexecuted command
- if (line.indexOf("\"success\":") != -1){ retval = 1; }
- }
- Serial.println();
- client.stop();
- return retval;
- }
- /* are_all_lights_on
- * Returns:
- * 1 if operation successful
- * 0 if operation not successful
- * -1 if error occurred
- */
- bool are_all_lights_on()
- {
- int retval = 0; // return value
- WiFiClient client; // WiFiClient class to create TCP connections
- if (!client.connect(bridge_ip, port))
- {
- Serial.println("ERR>> are_all_lights_on - Connection failed");
- return -1;
- }
- // This will send GET request to the server
- client.println("GET /api/" + user + "/lights HTTP/1.1");
- client.println("Host: " + String(bridge_ip) + ":" + String(port));
- client.println("Connection: close");
- // Wait maximum of 10 seconds for server to respond
- unsigned long timeout = millis();
- while (client.available() == 0)
- {
- if (millis() - timeout > 10000)
- {
- Serial.println("ERR>> are_all_lights_on - Client timeout");
- client.stop();
- return -1;
- }
- }
- // Read all the lines of the reply from server
- while(client.available())
- {
- String line = client.readStringUntil('\r');
- // Print line to serial if it's request status or json formated string
- if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
- // If any light is off - all lights are not on
- if (line.indexOf("\"on\":false") == -1){ retval = 1; }
- }
- Serial.println();
- client.stop();
- return retval;
- }
- /* is_light_on.
- * Returns:
- * 1 if operation successful
- * 0 if operation not successful
- * -1 if error occurred
- */
- bool is_light_on()
- {
- int retval = 0;
- // Use WiFiClient class to create TCP connections
- WiFiClient client;
- if (!client.connect(bridge_ip, port))
- {
- Serial.println("ERR>> is_light_on - Connection failed");
- return -1;
- }
- // This will send GET request to the server
- client.println("GET /api/" + user + "/lights/" + light);
- client.println("Host: " + String(bridge_ip) + ":" + String(port));
- client.println("Connection: close");
- // Wait maximum of 10 seconds for server to respond
- unsigned long timeout = millis();
- while (client.available() == 0)
- {
- if (millis() - timeout > 10000)
- {
- Serial.println("ERR>> is_light_on - Client timeout");
- client.stop();
- return -1;
- }
- }
- // Read all the lines of the reply from server and print them to Serial
- while(client.available())
- {
- String line = client.readStringUntil('\r');
- // Print line to serial if it's request status or json formated string
- if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
- // Check if light is on
- if (line.indexOf("\"on\":true") != -1){ retval = 1; }
- }
- Serial.println();
- client.stop();
- return retval;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement