49-713 Designing for the Internet of Things
· 26 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
In this project, I've created a clock which, instead of telling the time, tells us what to wear depending on the weather outside.
With the ever changing weather in Pittsburgh, I face a daily problem of deciding what to wear (sweater, light jacket, snow boots, heavy jacket etc.) Moreover it becomes a big hassle in the mornings to check the weather forecast, while trying to get ready and rush for the bus.
So I decided to create a device that would source weather data and quickly tell me what to wear.
With that in mind, I present to you the "What to wear" clock, a gorgeous piece of art and science.
Currently the particle code sources data from an internet source (weather.gov) via an API and webhook. This weather data is returned to the particle in the form of XML feed. The XML feed is parsed out to give the temperature and wind conditions for the day. Based on the weather, and my tolerance to it, the arms of the clock will move to point to the pair of clothes (jacket, sweater, hat & gloves or t-shirt & shorts) that I should wear.
Servo clothesServo ;
int clothesServoPin = A4;
int servoPosition = -1;
int targetPosition = 0;
const int CONNECT_DELAY_SECS = 30;
const int SLEEP_DELAY_SECS = 2 * 60;
const int SLEEP_TIME_SECS = 60 * 60;
bool manualMode = false;
bool hookResponseRequested = false;
bool hookResponseReceived = false;
unsigned long lastResponseTime = 0;
//Assigns the temperature returned from the webhook to a weather pointer value
//Will be put into cloud
int setClothes(String value) {
Serial.println("Setting clothes " + value);
lastResponseTime = millis();
//weatherPointer.pointTo(value);
int newAngle = getClothesAngle( value );
Serial.println( newAngle );
if( newAngle != targetPosition ){
Serial.print( "Target now: " );
Serial.println( targetPosition );
targetPosition = newAngle;
}
return 0;
}
int getClothesAngle( String value )
{
if( value == "hat" )
return 70 ;
else if( value == "jacket" )
return 175 ;
else if( value == "sweater" )
return 105 ;
else if( value == "tshirt" )
return 140;
return 180;
}
// Returns any text found between a start and end string inside 'str'
// example: startfooend -> returns foo
String tryExtractString(String str, const char* start, const char* end)
{
if (str == NULL) {
return NULL;
}
int idx = str.indexOf(start);
if (idx < 0) {
return NULL;
}
int endIdx = str.indexOf(end);
if (endIdx < 0) {
return NULL;
}
return str.substring(idx + strlen(start), endIdx);
}
//Calculates the time between responses, so that clock can be put to sleep
unsigned long timeSinceLastResponse() {
return millis() - lastResponseTime;
}
//Map actual weather conditions to the clothes required
String findClothes(String temperature, String wind)
{
//var precip = weather.precipitation;
// if(wind.match(/rain/i)) {
// return "umbrella";
// } else if(precip.match(/snow/i)) {
// return "shovel";
// }
int temp = temperature.toInt();
Serial.print( "temp: " );
Serial.print( temp );
Serial.print( "wind: " );
Serial.println( wind );
//var t = weather.temperature;
if(temp < 33) {
return "hat";
} else if(temp < 55) {
return "jacket";
} else if(temp < 70) {
return "sweater";
} else {
return "tshirt";
}
}
//Function that is called when hook returns data
void setDataFromHook(const char *event, const char *value)
{
String weather = String(value);
//Serial.println("Received what-to-wear response");
String locStr = tryExtractString(weather, "<location>",
"</location>");
String weathStr = tryExtractString(weather, "<weather>",
"</weather>");
String tempStr = tryExtractString(weather, "<temp_f>", "</temp_f>");
String windStr = tryExtractString(weather, "<wind_mph>",
"</wind_mph>");
Serial.println("The weather data at "+locStr+" has been received!");
hookResponseReceived = true;
hookResponseRequested = false;
lastResponseTime = millis();
String clothes = findClothes(tempStr,windStr);
setClothes(clothes);
}
//Interfaces with the hook to get weather data
void getDataFromHook() {
hookResponseRequested = true;
Serial.println("Published weather event");
Particle.publish("weather_xml", PRIVATE);
}
//Main function of the program
void setup()
{
Serial.begin(9600);
delay(200);
//powerSupply.setup();
//pointerPersistence.setup();
Serial.println("Woke from " + String(manualMode ? "pin" : "timer/reset"));
Particle.function("clothes", setClothes);
Particle.subscribe("hook-response/weather_xml", setDataFromHook, MY_DEVICES);
clothesServo.attach( clothesServoPin );
delay( 100 );
if(!manualMode) {
lastResponseTime = millis();
getDataFromHook();
}
}
void loop() {
// if(readyToSleep()) {
// Serial.println("Done waiting => Go to sleep");
// delay(200);
// goToSleep();
// }
if(timeSinceLastResponse() > SLEEP_DELAY_SECS * 1000 and !hookResponseRequested ) {
getDataFromHook();
}
if( targetPosition != servoPosition ){
Serial.print( "Setting servo to ");
Serial.println( targetPosition );
servoPosition = targetPosition;
clothesServo.write( targetPosition );
delay( 200 );
//clothesServo.detach();
}
delay( 100 );
}
Click to Expand
This project is only accessible by signed in users. Be considerate and think twice before sharing.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
In this project, I've created a clock which, instead of telling the time, tells us what to wear depending on the weather outside.
February 1st, 2017