Advertisement
Guest User

Untitled

a guest
Apr 2nd, 2019
763
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.31 KB | None | 0 0
  1. /*
  2. esp8266Huemotion
  3. https://github.com/LeskoIam/esp8266Huemotion
  4.  
  5. Used instead of very expensive Hue motion sensor.
  6. It's basicly a D1 mini, which breaks out pins from esp8266 WiFi module and adds some
  7. periphery to enable USB serial communication.
  8.  
  9. Operation:
  10. It uses PIR sensor attached to pin D1 (arduino library maps this pin to pin 5) to
  11. detect motion and turn on specified Hue light bulb if all conditions are met. These
  12. conditions are:
  13. - It's night time. This is determined based on if specified light bulb is on or off.
  14. State of the light bulb is checked and updated every set number of minutes
  15. ("lights_check_delay").
  16. - If motion is detected. Specified light bulb is turned on for set amount of time
  17. ("motion_detected_delay"). Motion is still detected and updated when light is turned on,
  18. this means light is turned off only after no motion is detected for set delay.
  19.  
  20. Deep sleep:
  21. If enabled, you can put module to sleep while "lights_check_delay" is active. It can conserve
  22. a lot of power and is specialy useful when module is powered with batteries. This is controlled
  23. with "use_deep_sleep" variable.
  24. Minor hardware modification is also necessary. Connect D0 pin to RST pin. This connection is
  25. used to wake up the module after sleep period is over.
  26.  
  27. The circuit:
  28. - Philips Hue lights
  29. - D1 mini or clone (esp8266).
  30. - PIR motion sensor (HC-SR501).
  31.  
  32. Settings:
  33. Look for code in #### block.
  34. Mandatory settings:
  35. - use_deep_sleep
  36. - ssid
  37. - password
  38. - bridge_ip, port
  39. - user
  40. - light
  41. Optional:
  42. - motion_detected_delay
  43. - lights_check_delay
  44. - hue_on
  45. - hue_off
  46.  
  47. */
  48. #include <ESP8266WiFi.h>
  49. #include <time.h>
  50.  
  51.  
  52. //// Global settings and variables
  53. // ################################################
  54. // Deep Sleep
  55. boolean use_deep_sleep = 0; // If deep sleep is enable don't forget to connect D0 to RST pin
  56. // Wifi Settings
  57. const char* ssid = "";
  58. const char* password = "";
  59.  
  60. // Hue settings
  61. const char* bridge_ip = ""; // Hue bridge IP
  62. const int port = 80;
  63. String user = "newdeveloper";
  64. String light = "21"; // Number of the light you want to control
  65.  
  66. // Motion timing
  67. unsigned long motion_detected_time = 0; // When was motion last detected
  68. unsigned long motion_detected_delay = 240*1000; // Keep light on for that many seconds after last motion was detected
  69.  
  70. // All lights off check timing
  71. unsigned long lights_check_time = 0; // When was light state last checked
  72. unsigned long lights_check_delay = 5*60*1000; // Check light state every that many minutes
  73.  
  74. // Commands
  75. String hue_on = "{\"on\":true, \"bri\":255}";
  76. String hue_on2 = "{\"on\":true, \"bri\":120}";
  77. String hue_off = "{\"on\":false}";
  78. // ################################################
  79.  
  80. int timezone = 0 * 3600; // change first value for your utc offset
  81. int dst = 3600 ; // change to 0 for no daylight savings.
  82.  
  83.  
  84. // Pin settings
  85. // PIR sensor is attached to D1 mini D1 pin which maps to pin 5 for arduino library
  86. int pirPin = 5;
  87.  
  88. int light_state = 0; // Internally track state of light
  89. int first_loop = 1; // Is this first loop
  90. int check_lights_first_loop = 1; // Same as above but for checking light state
  91. bool night_time; // master logic variable
  92.  
  93. void setup()
  94. {
  95. Serial.begin(115200);
  96. delay(10);
  97.  
  98. // Connect to WiFi network
  99. Serial.println();
  100. Serial.println();
  101. Serial.print("Connecting to ");
  102. Serial.println(ssid);
  103.  
  104. WiFi.mode(WIFI_STA);
  105. WiFi.begin(ssid, password);
  106. while (WiFi.status() != WL_CONNECTED)
  107. {
  108. delay(500);
  109. Serial.print(".");
  110. }
  111. Serial.println();
  112. Serial.println("WiFi connected");
  113. Serial.print("IP address: ");
  114. Serial.println(WiFi.localIP());
  115. Serial.println();
  116. Serial.print("MAC: ");
  117. Serial.println(WiFi.macAddress());
  118.  
  119. // Set PIR pin as input pin
  120. pinMode(pirPin, INPUT);
  121. if (use_deep_sleep)
  122. {
  123. // Connect D0 to RST to wake up
  124. pinMode(16, WAKEUP_PULLUP);
  125. }
  126.  
  127. Serial.println("Waiting 2 seconds for stable sensor readings...");
  128. delay(1000);
  129. Serial.println("Setup done. Main loop starting in a second...");
  130. delay(1000);
  131. Serial.println();
  132.  
  133. configTime(timezone, dst, "uk.pool.ntp.org");
  134. Serial.println ("\nWaiting for Internet Time");
  135. while(!time(nullptr)){
  136. Serial.print("*");
  137. delay(1000);
  138. }
  139. Serial.println("\nTime response....OK");
  140. }
  141.  
  142. void loop()
  143. {
  144. //// Check state of the light and set nigh_time accordingly
  145. if ((((lights_check_time + lights_check_delay) < millis()) || check_lights_first_loop == 1) && (light_state != 1))
  146. {
  147. Serial.print("Checking state of light ");
  148. Serial.println(light);
  149. check_lights_first_loop = 0;
  150. if (is_light_on() == 1) { night_time = 0; }
  151. else { night_time = 1; }
  152. lights_check_time = millis();
  153. if (use_deep_sleep)
  154. {
  155. if (!night_time)
  156. {
  157. // Go to deep sleep. Don't forget to convert milliseconds to microseconds
  158. Serial.printf("\nDEEP SLEEP for %i microseconds\n\n", lights_check_delay*1000);
  159. ESP.deepSleep(lights_check_delay * 1000);
  160. }
  161. }
  162. }
  163.  
  164.  
  165.  
  166. // Some debug prints
  167. Serial.println("-----");
  168. Serial.print("night_time: ");
  169. Serial.println(night_time);
  170. Serial.print("motion_detected_time: ");
  171. Serial.println(motion_detected_time);
  172. Serial.print("light_state: ");
  173. Serial.println(light_state);
  174.  
  175. time_t now = time(nullptr);
  176. struct tm* p_tm = localtime(&now);
  177. Serial.print(p_tm->tm_mday);
  178. Serial.print("/");
  179. Serial.print(p_tm->tm_mon + 1);
  180. Serial.print("/");
  181. Serial.print(p_tm->tm_year + 1900);
  182.  
  183. Serial.print(" ");
  184.  
  185. Serial.print(p_tm->tm_hour);
  186. Serial.print(":");
  187. if ((p_tm->tm_min) < 10) {Serial.print("0");}
  188. Serial.print(p_tm->tm_min);
  189. Serial.print(":");
  190. if ((p_tm->tm_sec) < 10) {Serial.print("0");}
  191. Serial.println(p_tm->tm_sec);
  192.  
  193. //// Main motion-light logic
  194. // Enter only if it is nigh time and ligh is not on because of us
  195. if ((night_time == 1) || (light_state == 1))
  196. {
  197. // Read PIR sensor
  198. int motion = digitalRead(pirPin);
  199. Serial.print("motion: ");
  200. Serial.println(motion);
  201.  
  202. // If motion is detected
  203. if (motion == HIGH)
  204. {
  205. // And light is off because of us.
  206. // This also prevents multiple turn ons (sensor output stays on for around 2 seconds)
  207. if (light_state == 0)
  208. {
  209. // Turn light on only if previous on time delay has passed or if this is first loop
  210. // first_loop check was added to handle situation when motion-light has
  211. // not yet been running for more than motion delay time
  212. if (((motion_detected_time + motion_detected_delay) < millis()) || first_loop == 1)
  213. {
  214. if ((p_tm->tm_hour <= 23) && (p_tm->tm_hour >= 17)) {Serial.println("Turning light on");
  215. light_control(hue_on); }
  216.  
  217. else if ((p_tm->tm_hour <= 5) || (p_tm->tm_hour == 0)) {Serial.println("Turning light on low");
  218. light_control(hue_on2);}
  219. light_state = 1;
  220. first_loop = 0;
  221. }
  222. }
  223. // Detect every motion and update detection time
  224. motion_detected_time = millis();
  225. }
  226. else
  227. {
  228. // Only turn off light if they were turned on by us
  229. if (light_state == 1)
  230. {
  231. // Turn light off only if on time delay has passed
  232. if ((motion_detected_time + motion_detected_delay) < millis())
  233. {
  234. Serial.print("No motion for ");
  235. Serial.print(motion_detected_delay/1000);
  236. Serial.println(" seconds. Turning light off");
  237. light_control(hue_off);
  238. light_state = 0;
  239. }
  240. }
  241. }
  242. }
  243. delay(333);
  244. }
  245.  
  246.  
  247. /* light_control.
  248. * Send PUT command to hue light (bridge). Function takes json formated command.
  249. * Returns:
  250. * 1 if operation successful
  251. * 0 if operation not successful
  252. * -1 if error occurred
  253. */
  254. bool light_control(String command)
  255. {
  256. int retval = 0; // return value
  257. WiFiClient client; // WiFiClient class to create TCP connections
  258.  
  259. if (!client.connect(bridge_ip, port))
  260. {
  261. Serial.println("ERR>> light_control - Connection failed");
  262. return -1;
  263. }
  264.  
  265. // This will send PUT request to the server
  266. client.println("PUT /api/" + user + "/lights/" + light + "/state HTTP/1.1");
  267. client.println("Host: " + String(bridge_ip) + ":" + String(port));
  268. client.println("User-Agent: ESP8266/1.0");
  269. client.println("Connection: keep-alive");
  270. client.println("Content-type: text/xml; charset=\"utf-8\"");
  271. client.print("Content-Length: ");
  272. client.println(command.length()); // PUT COMMAND HERE
  273. client.println();
  274. client.println(command); // PUT COMMAND HERE
  275.  
  276. // Wait 10 seconds for server to respond
  277. unsigned long timeout = millis();
  278. while (client.available() == 0)
  279. {
  280. if (millis() - timeout > 10000)
  281. {
  282. Serial.println("ERR>> light_control - Client timeout");
  283. client.stop();
  284. return -1;
  285. }
  286. }
  287.  
  288. // Read all the lines of the reply from server
  289. while(client.available())
  290. {
  291. String line = client.readStringUntil('\r');
  292. // Print line to serial if it's request status or json formated string
  293. if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
  294. // If success string is found in reply we have successfully sexecuted command
  295. if (line.indexOf("\"success\":") != -1){ retval = 1; }
  296. }
  297. Serial.println();
  298. client.stop();
  299. return retval;
  300. }
  301.  
  302. /* are_all_lights_on
  303. * Returns:
  304. * 1 if operation successful
  305. * 0 if operation not successful
  306. * -1 if error occurred
  307. */
  308. bool are_all_lights_on()
  309. {
  310. int retval = 0; // return value
  311. WiFiClient client; // WiFiClient class to create TCP connections
  312.  
  313. if (!client.connect(bridge_ip, port))
  314. {
  315. Serial.println("ERR>> are_all_lights_on - Connection failed");
  316. return -1;
  317. }
  318.  
  319. // This will send GET request to the server
  320. client.println("GET /api/" + user + "/lights HTTP/1.1");
  321. client.println("Host: " + String(bridge_ip) + ":" + String(port));
  322. client.println("Connection: close");
  323.  
  324. // Wait maximum of 10 seconds for server to respond
  325. unsigned long timeout = millis();
  326. while (client.available() == 0)
  327. {
  328. if (millis() - timeout > 10000)
  329. {
  330. Serial.println("ERR>> are_all_lights_on - Client timeout");
  331. client.stop();
  332. return -1;
  333. }
  334. }
  335.  
  336. // Read all the lines of the reply from server
  337. while(client.available())
  338. {
  339. String line = client.readStringUntil('\r');
  340. // Print line to serial if it's request status or json formated string
  341. if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
  342. // If any light is off - all lights are not on
  343. if (line.indexOf("\"on\":false") == -1){ retval = 1; }
  344. }
  345. Serial.println();
  346. client.stop();
  347. return retval;
  348. }
  349.  
  350. /* is_light_on.
  351. * Returns:
  352. * 1 if operation successful
  353. * 0 if operation not successful
  354. * -1 if error occurred
  355. */
  356. bool is_light_on()
  357. {
  358. int retval = 0;
  359. // Use WiFiClient class to create TCP connections
  360. WiFiClient client;
  361.  
  362. if (!client.connect(bridge_ip, port))
  363. {
  364. Serial.println("ERR>> is_light_on - Connection failed");
  365. return -1;
  366. }
  367.  
  368. // This will send GET request to the server
  369. client.println("GET /api/" + user + "/lights/" + light);
  370. client.println("Host: " + String(bridge_ip) + ":" + String(port));
  371. client.println("Connection: close");
  372.  
  373. // Wait maximum of 10 seconds for server to respond
  374. unsigned long timeout = millis();
  375. while (client.available() == 0)
  376. {
  377. if (millis() - timeout > 10000)
  378. {
  379. Serial.println("ERR>> is_light_on - Client timeout");
  380. client.stop();
  381. return -1;
  382. }
  383. }
  384.  
  385. // Read all the lines of the reply from server and print them to Serial
  386. while(client.available())
  387. {
  388. String line = client.readStringUntil('\r');
  389. // Print line to serial if it's request status or json formated string
  390. if (((line.indexOf("{") != -1) && (line.indexOf("}") != -1)) || (line.indexOf("HTTP") != -1)){ Serial.print(line); }
  391. // Check if light is on
  392. if (line.indexOf("\"on\":true") != -1){ retval = 1; }
  393. }
  394. Serial.println();
  395. client.stop();
  396. return retval;
  397. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement