Skip to content

Instantly share code, notes, and snippets.

@embedded-creations
Last active April 14, 2016 16:04
Show Gist options
  • Save embedded-creations/cd47646f5b9233953f0fac7e0e310a56 to your computer and use it in GitHub Desktop.
Save embedded-creations/cd47646f5b9233953f0fac7e0e310a56 to your computer and use it in GitHub Desktop.
Wakeup Light Project - Minimal Version
/*
* Wakeup Light - Minimal Version
*
* Copyright (c) 2016 Louis Beaudoin (Pixelmatix)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "InternetButton.h"
InternetButton b = InternetButton();
enum lightState {
LIGHT_STATE_OFF,
LIGHT_STATE_ON
};
lightState state = LIGHT_STATE_OFF;
time_t ledon_time;
time_t ledoff_time;
// Parse an ISO8601 timestamp string including (optional) timezone offset, return time_t in GMT, 0 if error
time_t convertIso8601ToTime(const char * iso8601String) {
char iso8601StringCopy[30];
struct tm timestamp_struct;
time_t timestamp;
char * pch;
strncpy(iso8601StringCopy, iso8601String, sizeof(iso8601StringCopy));
memset(&timestamp_struct, 0x00, sizeof(timestamp_struct));
pch = strptime(iso8601StringCopy, "%Y-%m-%dT%T", &timestamp_struct);
if(pch == NULL) {
//Serial.println("ERROR, couldn't parse timestamp");
return 0;
}
timestamp = mktime(&timestamp_struct);
/* 4 cases for timezone format:
* 1) "Z" - no offset
* 2) "+hh:mm" (or -)
* 3) "+hhmm" (or -)
* 4) "+hh" (or -)
* if string less than 3 characters, assume no offset (handles 1)
* otherwise, set null character after third digit in string, parse hh integer, parse '+' or '-'
* TODO: Ignoring minutes offset for now
* TODO: Requires editable string, instead of const
*/
// non-zero offsets all have at least three characters
if(strlen(pch) >= 3) {
// set null character after "+hh"
pch[3] = '\0';
int timezoneoffset_sec = atoi(pch + 1) * 60 * 60;
//Serial.println(timezoneoffset_sec);
if(pch[0] == '+')
timestamp -= timezoneoffset_sec;
else if (pch[0] == '-')
timestamp += timezoneoffset_sec;
}
return timestamp;
}
int wakeupHandler(String command) {
time_t wakeup_time;
char commandcstr[40];
int lightAdvanceTime_min;
char * pch;
Serial.println();
Serial.print("wakeup: \"");
Serial.print(command);
Serial.println("\"");
strncpy(commandcstr, command.c_str(), sizeof(commandcstr));
// get first token (wakeup timestamp in ISO8601 format)
pch = strtok(commandcstr, ",");
if(pch == NULL) {
Serial.println("ERROR, command string is empty");
return -1;
}
wakeup_time = convertIso8601ToTime(pch);
if(!wakeup_time) {
Serial.println("ERROR, couldn't parse timestamp");
return -1;
}
Serial.print("wakeup_time: ");
Serial.println(Time.format(wakeup_time, TIME_FORMAT_DEFAULT));
pch = strtok(NULL, ",");
if(pch == NULL) {
Serial.println("ERROR, couldn't parse advancetime");
return -1;
}
lightAdvanceTime_min = atoi(pch);
Serial.print("lightAdvanceTime: ");
Serial.println(lightAdvanceTime_min);
ledon_time = wakeup_time - (lightAdvanceTime_min * 60);
ledoff_time = wakeup_time + (30 * 60);
time_t time = Time.now();
Serial.print("current time: ");
Serial.println(Time.format(time, TIME_FORMAT_DEFAULT));
Serial.print("LED on time: ");
Serial.println(Time.format(ledon_time, TIME_FORMAT_DEFAULT));
Serial.print("LED off time: ");
Serial.println(Time.format(ledoff_time, TIME_FORMAT_DEFAULT));
}
void turnLedsOn() {
digitalWrite(D7, HIGH);
b.allLedsOn(5,5,0);
}
void turnLedsOff() {
digitalWrite(D7, LOW);
b.allLedsOff();
}
void setup() {
b.begin();
// drive onboard blue LED
pinMode(D7, OUTPUT);
Serial.println("startup");
Particle.function("wakeup", wakeupHandler);
turnLedsOn();
delay(2000);
turnLedsOff();
}
void loop() {
if(state == LIGHT_STATE_OFF) {
if(Time.now() >= ledon_time && Time.now() < ledoff_time) {
Serial.print("It's ");
Serial.print(Time.format(Time.now(), TIME_FORMAT_DEFAULT));
Serial.print(" and the light is supposed to be on at ");
Serial.print(Time.format(ledon_time, TIME_FORMAT_DEFAULT));
Serial.println(", turning light ON!");
turnLedsOn();
state = LIGHT_STATE_ON;
}
} else if (state == LIGHT_STATE_ON) {
if(Time.now() >= ledoff_time) {
Serial.print("It's ");
Serial.print(Time.format(Time.now(), TIME_FORMAT_DEFAULT));
Serial.print(" and the light is supposed to be off at ");
Serial.print(Time.format(ledoff_time, TIME_FORMAT_DEFAULT));
Serial.println(", turning light OFF!");
turnLedsOff();
state = LIGHT_STATE_OFF;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment