A frosty white device composed of acrylic panels and a tear-drop shaped facade sits, a computer monitor, and a mouse sit on a table. The user begins the video by clicking on the play button with the mouse. The Rain! commercial plays, instructing the users how to turn on Rain! as well as showcasing a moral dilemma with using the device. The tear-drop contains a speaker centered on its face as well as an IR-proximity sensor just below the speaker. If the user decides to use Rain!, they set their hand directly in front of the sensor for about a second. The tear-drop plays two short messages, with a rectangular light accompanying the second message. These two messages, which berate the user, are narrated by a real yet snarky female voice. The first message corresponds to a certain live temperature range while the second message, along with the light, corresponds to a live sky condition. Once the second message is played, the rectangular light shuts off after about 4 seconds.
Progression to Final Product
Wiring Particle Argon to Arduino UNO to establish serial communication to transmit API data
Arduino receiving API data from Particle Argon
Shot of Rain! commercial, filmed in the Media Lab
Implementing API values into MusicMaker MP3 Shield and NeoPixel code
Packaging Particle Arduino in back compartment of Rain!
Rain! setup at Effervescent Shadow Bazaar
Process Reflection
Updating this project for the end-of-semester IDeATe show was a very fun experience as it allowed me to move closer to the initial vision I had for Rain!. The main additions I incorporated included implementing actual live weather data and making a commercial/video to accompany the piece. I also decided to slightly modify the title by including an exclamation mark after “Rain” as I thought that would further emphasize the product-like nature of the project.
Implementing the live weather data was possibly the hardest task of the additions but the most rewarding in terms of what I learned. Researching and writing the code to incorporate data from OpenMeteo weather API was probably the most software I’ve ever written for a project, and this was incredibly valuable since I started off this semester with pretty simple coding knowledge. Using this API as well as establishing serial communication with Arduino was straightforward; coding with the received API values in Arduino proved to be extremely tricky. It involved a lot of experimentation, especially with if/else statements. Although this took many hours, going through this process of trying and experimenting was a critical way of gaining a better understanding of writing code.
One of the major additions I incorporated for this iteration of the project was to include a video element. Given the nature of the IDeATe show, I thought including something additional to my project would draw more attention and interaction with Rain!, and I ultimately decided on using video as the medium for that since I thought making a video would be fun. I wanted to include a dystopian element to Rain!, similar to the vibe in the techno-thriller show Black Mirror. To do this, I made the video a mixture between a commercial and “found footage”, with the latter showcasing the hidden, nefarious intentions of Rain!. I don’t have a lot of experience making short movies, so the quality of the video was hindered by this. However, I think I was able to showcase a humorous product with the commercial with a contrast of malintent in the “found footage” section.
With how loud the show was, it was very difficult to hear the video and Rain!. One would have to put their ears up close to the devices to be able to hear properly. I used the speakers on the computer monitor for the video; having separate speakers connected to the monitor for the video would have made the hearing situation better. As for Rain!, I don’t think there was else much I could do given the size of its speaker.
I plan on using Rain! personally in my dorm room as I really enjoy using it, especially as it is properly configured with live weather data. I do think it’s lacking in a bit of utility which would provide more incentive for its use. I plan on having Rain! provide the user with the current temperature in addition to the insults, perhaps with an intimidating text-to-speech generator to create the MP3 files for each temperature value.
Code
Arduino Uno
/*
Rain!
Gabriel Prado
Code implements live weather data from Particle Argon to initiate MP3 files and NeoPixels
Use of NeoPixels and Adafruit MusicMaker MP3 Shield libraries
*/
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
// These are the pins used for the breakout example
/*
Rain!
Gabriel Prado
Code implements live weather data from Particle Argon to initiate MP3 files and NeoPixels
Use of NeoPixels and Adafruit MusicMaker MP3 Shield libraries
*/
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
// These are the pins used for the breakout example
#define BREAKOUT_RESET 9 // VS1053 reset pin (output)
#define BREAKOUT_CS 10 // VS1053 chip select pin (output)
#define BREAKOUT_DCS 8 // VS1053 Data/command select pin (output)
// These are the pins used for the music maker shield
#define SHIELD_RESET -1 // VS1053 reset pin (unused!)
#define SHIELD_CS 7 // VS1053 chip select pin (output)
#define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
// These are common pins between breakout and shield
#define CARDCS 4 // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 32 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
int temps[] = {"/track001.mp3" , "/track002.mp3", "/track003.mp3" , "/track004.mp3" , "/track005.mp3", "/track006.mp3",
"/track007.mp3" , "/track008.mp3", "/track009.mp3" , "/track010.mp3" , "/track011.mp3" , "/track012.mp3" , "/track013.mp3" ,
"/track014.mp3" , "/track015.mp3" , "/track016.mp3" , "/track017.mp3" , "/track018.mp3" , "/track019.mp3" , "/track020.mp3",
"/track021.mp3" , "/track022.mp3" , "/track023.mp3" , "/track024.mp3" ,"/track025.mp3" , "/track026.mp3"}; //all MP3 files
#include <SoftwareSerial.h>
SoftwareSerial mySerial(5, 12); //pins used for serial connection to Particle Argon
void setup() {
pinMode(A0,INPUT); //input for IR proximity sensor
Serial.begin(9600);
mySerial.begin(9600);
musicPlayer.begin();
SD.begin(CARDCS);
musicPlayer.setVolume(10,10);
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}
int Temp = 0;
int Skies = 0;
void loop() {
if(mySerial.available()){ //all actions occur within this if statement
int TempRead = mySerial.parseFloat(); //Temperature value from API
int SkiesRead = mySerial.parseFloat(); //Sky Condition value from API
if (TempRead != 0){
Temp = TempRead;
}
if (SkiesRead != 0){
Skies = SkiesRead;
}
Serial.println(Temp);
Serial.println(Skies);
pixels.clear();
if(analogRead(A0) >= 200){ //user presses finger on IV proximity sensor
int a = Temp; //a is the live temperature in Farenheit
if(a == 0 or a == 1 or a == 2 or a == 3 or a == 4 or a == 5 or a ==6){
musicPlayer.playFullFile(temps[0]);
}
else if(a == 7 or a ==8 or a == 9 or a == 10 or a == 11 or a == 12){
musicPlayer.playFullFile(temps[1]);
}
else if (a == 13 or a == 14 or a == 15 or a ==16 or a ==17 or a == 18 or a == 19){
musicPlayer.playFullFile(temps[2]);
}
else if (a == 20 or a == 21 or a == 22){
musicPlayer.playFullFile(temps[3]);
}
else if (a == 23 or a == 24){
musicPlayer.playFullFile(temps[4]);
}
else if (a == 25 or a == 26 or a == 27 or a == 28 or a == 29){
musicPlayer.playFullFile(temps[5]);
}
else if (a == 30 or a == 31 or a == 32 or a == 33 or a == 34){
musicPlayer.playFullFile(temps[6]);
}
else if (a == 35 or a == 36 or a == 37 or a == 38 or a == 39){
musicPlayer.playFullFile(temps[7]);
}
else if (a == 40 or a == 41 or a == 42 or a == 43 or a == 44){
musicPlayer.playFullFile(temps[8]);
}
else if (a == 45 or a == 46 or a == 47 or a == 48 or a == 49){
musicPlayer.playFullFile(temps[9]);
}
else if (a == 50 or a == 51 or a == 52 or a == 53 or a == 54){
musicPlayer.playFullFile(temps[10]);
}
else if (a == 55 or a == 56 or a == 57 or a == 58 or a == 59){
musicPlayer.playFullFile(temps[11]);
}
else if (a == 60 or a == 61 or a == 62 or a == 63 or a == 64){
musicPlayer.playFullFile(temps[12]);
}
else if (a == 65 or a == 66 or a == 67 or a == 68 or a == 69){
musicPlayer.playFullFile(temps[13]);
}
else if (a == 70 or a == 71 or a == 72 or a == 73 or a == 74){
musicPlayer.playFullFile(temps[14]);
}
else if (a == 75 or a == 76 or a == 77 or a == 78 or a == 79){
musicPlayer.playFullFile(temps[15]);
}
else if (a == 80 or a == 81 or a == 82 or a == 83 or a == 84){
musicPlayer.playFullFile(temps[16]);
}
else if (a == 85 or a == 86 or a == 87 or a == 88 or a == 89){
musicPlayer.playFullFile(temps[17]);
}
else if (a == 90 or a == 91 or a == 92 or a == 93 or a == 94){
musicPlayer.playFullFile(temps[18]);
}
else if (a == 95 or a == 96 or a == 97 or a == 98 or a == 99 or a == 100){
musicPlayer.playFullFile(temps[19]);
}
int b = Skies; //b is the sky condition number
if(b == 61 or b == 63 or b == 65 or b == 66 or b == 67 or b == 80 or b == 81 or b == 82 or b == 51 or b == 53 or b == 55 or b == 56 or b == 57){
for(int i=0; i<NUMPIXELS; i++){ //blue
pixels.setPixelColor(i, pixels.Color(0, 191, 255));
pixels.show();
}
musicPlayer.playFullFile("/track021.mp3"); //rainy
delay(4000);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++){ //NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
else if(b == 0 or b == 1){
for(int i=0; i<NUMPIXELS; i++){ //currently pink for clear, but can be coded to red for sunny
pixels.setPixelColor(i,pixels.Color(255,102,255));
pixels.show();
}
musicPlayer.playFullFile("/track026.mp3"); //sunny/clear
delay(4000);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++) { //NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
else if(b == 2 or b == 3 or b == 45 or b == 48){
for(int i=0; i<NUMPIXELS; i++){ //gray
pixels.setPixelColor(i, pixels.Color(32, 32, 32));
pixels.show(); // Send the updated pixel colors to the hardware.
}
musicPlayer.playFullFile("/track023.mp3"); //cloudy
delay(4000);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++){ //NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
else if(b == 71 or b == 73 or b == 75 or b == 77 or b == 85 or b == 86){
for(int i=0; i<NUMPIXELS; i++){ //white
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
pixels.show();
}
musicPlayer.playFullFile("/track024.mp3"); //snowy
delay(4000);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++){ //NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
else if(b == 95 or b == 96 or b == 99){
for(int i=0; i<NUMPIXELS; i++){ //yellow
pixels.setPixelColor(i, pixels.Color(255, 100, 0));
pixels.show();
}
musicPlayer.playFullFile("/track025.mp3"); //stormy
delay(4000);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++){ //NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
}
}
}
/*
Rain!
Gabriel Prado
Code implements live weather data from Particle Argon to initiate MP3 files and NeoPixels
Use of NeoPixels and Adafruit MusicMaker MP3 Shield libraries
*/#include<SPI.h>#include<Adafruit_VS1053.h>#include<SD.h>// These are the pins used for the breakout example#define BREAKOUT_RESET 9// VS1053 reset pin (output)#define BREAKOUT_CS 10// VS1053 chip select pin (output)#define BREAKOUT_DCS 8// VS1053 Data/command select pin (output)// These are the pins used for the music maker shield#define SHIELD_RESET -1// VS1053 reset pin (unused!)#define SHIELD_CS 7// VS1053 chip select pin (output)#define SHIELD_DCS 6// VS1053 Data/command select pin (output)// These are common pins between breakout and shield#define CARDCS 4// Card chip select pin// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt#define DREQ 3// VS1053 Data request, ideally an Interrupt pinAdafruit_VS1053_FilePlayer musicPlayer =Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);#include<Adafruit_NeoPixel.h>#ifdef __AVR__
#include<avr/power.h>// Required for 16 MHz Adafruit Trinket#endif// Which pin on the Arduino is connected to the NeoPixels?#define PIN 6// On Trinket or Gemma, suggest changing this to 1// How many NeoPixels are attached to the Arduino?#define NUMPIXELS 32// Popular NeoPixel ring sizeAdafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);#define DELAYVAL 500// Time (in milliseconds) to pause between pixelsint temps[]={"/track001.mp3","/track002.mp3","/track003.mp3","/track004.mp3","/track005.mp3","/track006.mp3","/track007.mp3","/track008.mp3","/track009.mp3","/track010.mp3","/track011.mp3","/track012.mp3","/track013.mp3","/track014.mp3","/track015.mp3","/track016.mp3","/track017.mp3","/track018.mp3","/track019.mp3","/track020.mp3","/track021.mp3","/track022.mp3","/track023.mp3","/track024.mp3","/track025.mp3","/track026.mp3"};//all MP3 files#include<SoftwareSerial.h>SoftwareSerial mySerial(5,12);//pins used for serial connection to Particle Argon void setup(){
pinMode(A0,INPUT);//input for IR proximity sensorSerial.begin(9600);
mySerial.begin(9600);
musicPlayer.begin();
SD.begin(CARDCS);
musicPlayer.setVolume(10,10);#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);#endif
pixels.begin();// INITIALIZE NeoPixel strip object (REQUIRED)}intTemp=0;intSkies=0;void loop(){if(mySerial.available()){//all actions occur within this if statementintTempRead= mySerial.parseFloat();//Temperature value from APIintSkiesRead= mySerial.parseFloat();//Sky Condition value from APIif(TempRead!=0){Temp=TempRead;}if(SkiesRead!=0){Skies=SkiesRead;}Serial.println(Temp);Serial.println(Skies);
pixels.clear();if(analogRead(A0)>=200){//user presses finger on IV proximity sensorint a =Temp;//a is the live temperature in Farenheitif(a ==0or a ==1or a ==2or a ==3or a ==4or a ==5or a ==6){
musicPlayer.playFullFile(temps[0]);}elseif(a ==7or a ==8or a ==9or a ==10or a ==11or a ==12){
musicPlayer.playFullFile(temps[1]);}elseif(a ==13or a ==14or a ==15or a ==16or a ==17or a ==18or a ==19){
musicPlayer.playFullFile(temps[2]);}elseif(a ==20or a ==21or a ==22){
musicPlayer.playFullFile(temps[3]);}elseif(a ==23or a ==24){
musicPlayer.playFullFile(temps[4]);}elseif(a ==25or a ==26or a ==27or a ==28or a ==29){
musicPlayer.playFullFile(temps[5]);}elseif(a ==30or a ==31or a ==32or a ==33or a ==34){
musicPlayer.playFullFile(temps[6]);}elseif(a ==35or a ==36or a ==37or a ==38or a ==39){
musicPlayer.playFullFile(temps[7]);}elseif(a ==40or a ==41or a ==42or a ==43or a ==44){
musicPlayer.playFullFile(temps[8]);}elseif(a ==45or a ==46or a ==47or a ==48or a ==49){
musicPlayer.playFullFile(temps[9]);}elseif(a ==50or a ==51or a ==52or a ==53or a ==54){
musicPlayer.playFullFile(temps[10]);}elseif(a ==55or a ==56or a ==57or a ==58or a ==59){
musicPlayer.playFullFile(temps[11]);}elseif(a ==60or a ==61or a ==62or a ==63or a ==64){
musicPlayer.playFullFile(temps[12]);}elseif(a ==65or a ==66or a ==67or a ==68or a ==69){
musicPlayer.playFullFile(temps[13]);}elseif(a ==70or a ==71or a ==72or a ==73or a ==74){
musicPlayer.playFullFile(temps[14]);}elseif(a ==75or a ==76or a ==77or a ==78or a ==79){
musicPlayer.playFullFile(temps[15]);}elseif(a ==80or a ==81or a ==82or a ==83or a ==84){
musicPlayer.playFullFile(temps[16]);}elseif(a ==85or a ==86or a ==87or a ==88or a ==89){
musicPlayer.playFullFile(temps[17]);}elseif(a ==90or a ==91or a ==92or a ==93or a ==94){
musicPlayer.playFullFile(temps[18]);}elseif(a ==95or a ==96or a ==97or a ==98or a ==99or a ==100){
musicPlayer.playFullFile(temps[19]);}int b =Skies;//b is the sky condition numberif(b ==61or b ==63or b ==65or b ==66or b ==67or b ==80or b ==81or b ==82or b ==51or b ==53or b ==55or b ==56or b ==57){for(int i=0; i<NUMPIXELS; i++){//blue
pixels.setPixelColor(i, pixels.Color(0,191,255));
pixels.show();}
musicPlayer.playFullFile("/track021.mp3");//rainy
delay(4000);
pixels.clear();for(int i=0; i<NUMPIXELS; i++){//NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0,0,0));
pixels.show();}}elseif(b ==0or b ==1){for(int i=0; i<NUMPIXELS; i++){//currently pink for clear, but can be coded to red for sunny
pixels.setPixelColor(i,pixels.Color(255,102,255));
pixels.show();}
musicPlayer.playFullFile("/track026.mp3");//sunny/clear
delay(4000);
pixels.clear();for(int i=0; i<NUMPIXELS; i++){//NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0,0,0));
pixels.show();}}elseif(b ==2or b ==3or b ==45or b ==48){for(int i=0; i<NUMPIXELS; i++){//gray
pixels.setPixelColor(i, pixels.Color(32,32,32));
pixels.show();// Send the updated pixel colors to the hardware.}
musicPlayer.playFullFile("/track023.mp3");//cloudy
delay(4000);
pixels.clear();for(int i=0; i<NUMPIXELS; i++){//NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0,0,0));
pixels.show();}}elseif(b ==71or b ==73or b ==75or b ==77or b ==85or b ==86){for(int i=0; i<NUMPIXELS; i++){//white
pixels.setPixelColor(i, pixels.Color(255,255,255));
pixels.show();}
musicPlayer.playFullFile("/track024.mp3");//snowy
delay(4000);
pixels.clear();for(int i=0; i<NUMPIXELS; i++){//NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0,0,0));
pixels.show();}}elseif(b ==95or b ==96or b ==99){for(int i=0; i<NUMPIXELS; i++){//yellow
pixels.setPixelColor(i, pixels.Color(255,100,0));
pixels.show();}
musicPlayer.playFullFile("/track025.mp3");//stormy
delay(4000);
pixels.clear();for(int i=0; i<NUMPIXELS; i++){//NeoPixel reset
pixels.setPixelColor(i, pixels.Color(0,0,0));
pixels.show();}}}}}
Particle Argon
/*
Rain!
Gabriel Prado
Code sends temperature and sky condition data from OpenMeteo API to Arduino Uno via Serial
This code is from Daragh Byrne's work with OpenMeteo (https://diotlabs.daraghbyrne.me/docs/working-with-data/webhooks/openmeteo_weather)
Serial1.print(temperature); //Temperature sent to Arduino
Serial1.print(",");
Serial1.println(weatherCode); //Sky condition sent to Arduino
}
/*
Rain!
Gabriel Prado
Code sends temperature and sky condition data from OpenMeteo API to Arduino Uno via Serial
This code is from Daragh Byrne's work with OpenMeteo (https://diotlabs.daraghbyrne.me/docs/working-with-data/webhooks/openmeteo_weather)
*/
void setup() {
// Subscribe to the integration response event
Serial.begin(9600);
Serial1.begin(9600);
Particle.subscribe("hook-response/get-forecast", handleForecastReceived );
}
void loop() {\
getData();
delay(10000);
}
void getData()
{
// Publish an event to trigger the webhook
Particle.publish( "get-forecast" );
}
String temperature = "";
int weatherCode = 0;
// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
// Handle the integration response
String receivedStr = String( data );
int loc1 = 0;
int loc2 = 0;
loc1 = receivedStr.indexOf("~");
temperature = receivedStr.substring(0,loc1); //Temperature in F
loc2 = receivedStr.indexOf("~",loc1+1);
weatherCode = (double) String(receivedStr.substring(loc1+1,loc2)).toFloat(); //Sky condition
Serial1.print(temperature); //Temperature sent to Arduino
Serial1.print(",");
Serial1.println(weatherCode); //Sky condition sent to Arduino
}
/*
Rain!
Gabriel Prado
Code sends temperature and sky condition data from OpenMeteo API to Arduino Uno via Serial
This code is from Daragh Byrne's work with OpenMeteo (https://diotlabs.daraghbyrne.me/docs/working-with-data/webhooks/openmeteo_weather)
*/void setup(){// Subscribe to the integration response eventSerial.begin(9600);Serial1.begin(9600);Particle.subscribe("hook-response/get-forecast", handleForecastReceived );}void loop(){\
getData();
delay(10000);}void getData(){// Publish an event to trigger the webhookParticle.publish("get-forecast");}String temperature ="";int weatherCode =0;// This function will handle data received back from the webhookvoid handleForecastReceived(constchar*event,constchar*data){// Handle the integration responseString receivedStr =String( data );int loc1 =0;int loc2 =0;
loc1 = receivedStr.indexOf("~");
temperature = receivedStr.substring(0,loc1);//Temperature in F
loc2 = receivedStr.indexOf("~",loc1+1);
weatherCode =(double)String(receivedStr.substring(loc1+1,loc2)).toFloat();//Sky conditionSerial1.print(temperature);//Temperature sent to ArduinoSerial1.print(",");Serial1.println(weatherCode);//Sky condition sent to Arduino}
Insults
Rain (0) --> 21. And don't bother getting your umbrella, you'll need a shower anyways
Sunny (1) --> 22. Looks like we're gonna have sun today. Here's a fun tip: stare at it
Cloudy (2) --> 23. The sky is gray,not the brightest. I'm sure you can relate
Snow (3) --> 24. The snow is so pure and wonderful, and you're a disgusting blemish
Stormy (4) --> 25. It's getting rough out there, have fun!
Clear (1) --> 26. The sky is clear, but I'll be sincere: I hate you
0-20 degree range
1. I just wanna see you freeze to death
2.Ready to freeze, scum?
3. The weather outside looks frightful, but you look even more frightful. Seriously, just look at yourself.
20-30 degree range
4. See if I liked you, I would tell you to stay inside. But, I don't so, get out there!
5. You should wear your jacket, but seriously it makes you look like a balloon
6. The freezing point of human blood is 31 degrees, so let's keep our fingers crossed shall we?
30 - 40 degree range
7. It's too cold to for a walk and too hot to go sledding, so go screw yourself
8. Looks like you'll be looking for warmth again, we all know how that will go
40 - 50 degree range
9. Whatever drink you get to keep you warm, I hope you spill it all over yourself
10. The temperature right now is the number of reasons why you're a loser
50 - 60 degree range
11. Slightly cool, slightly warm. I don't know anymore, so screw you
12. The temperature is as meh as your looks
60 - 70 degree range
13.It's getting kind of hot in here, I hope your body oder doesn't show
14. You should go outside and enjoy the weather. Oh wait, you're a loser my bad
70 - 80 degree range
15. It's so warm, unlike your personality
16. The temperature right now is pretty great to be honest. The only thing in my way is you
80 - 90 degree range
17. It' really hot, unlike you
18. Global warming is coming for you!
90 - 100 degree range
19. Time to starting wearing less, but no one wants to see that
20. Some people wanna watch the world burn, like me
Rain (0) --> 21. And don't bother getting your umbrella, you'll need a shower anyways
Sunny (1) --> 22. Looks like we're gonna have sun today. Here's a fun tip: stare at it
Cloudy (2) --> 23. The sky is gray,not the brightest. I'm sure you can relate
Snow (3) --> 24. The snow is so pure and wonderful, and you're a disgusting blemish
Stormy (4) --> 25. It's getting rough out there, have fun!
Clear (1) --> 26. The sky is clear, but I'll be sincere: I hate you
0-20 degree range
1. I just wanna see you freeze to death
2.Ready to freeze, scum?
3. The weather outside looks frightful, but you look even more frightful. Seriously, just look at yourself.
20-30 degree range
4. See if I liked you, I would tell you to stay inside. But, I don't so, get out there!
5. You should wear your jacket, but seriously it makes you look like a balloon
6. The freezing point of human blood is 31 degrees, so let's keep our fingers crossed shall we?
30 - 40 degree range
7. It's too cold to for a walk and too hot to go sledding, so go screw yourself
8. Looks like you'll be looking for warmth again, we all know how that will go
40 - 50 degree range
9. Whatever drink you get to keep you warm, I hope you spill it all over yourself
10. The temperature right now is the number of reasons why you're a loser
50 - 60 degree range
11. Slightly cool, slightly warm. I don't know anymore, so screw you
12. The temperature is as meh as your looks
60 - 70 degree range
13.It's getting kind of hot in here, I hope your body oder doesn't show
14. You should go outside and enjoy the weather. Oh wait, you're a loser my bad
70 - 80 degree range
15. It's so warm, unlike your personality
16. The temperature right now is pretty great to be honest. The only thing in my way is you
80 - 90 degree range
17. It' really hot, unlike you
18. Global warming is coming for you!
90 - 100 degree range
19. Time to starting wearing less, but no one wants to see that
20. Some people wanna watch the world burn, like me
Rain(0)-->21.And don't bother getting your umbrella, you'll need a shower anyways
Sunny(1)-->22.Looks like we're gonna have sun today. Here's a fun tip: stare at it
Cloudy(2)-->23.The sky is gray,not the brightest. I'm sure you can relate
Snow (3) --> 24. The snow is so pure and wonderful, and you're a disgusting blemish
Stormy(4)-->25.It's getting rough out there, have fun!
Clear (1) --> 26. The sky is clear, but I'll be sincere: I hate you
0-20 degree range
1. I just wanna see you freeze to death
2.Ready to freeze, scum?3.The weather outside looks frightful, but you look even more frightful.Seriously, just look at yourself.20-30 degree range
4.Seeif I liked you, I would tell you to stay inside.But, I don't so, get out there!
5. You should wear your jacket, but seriously it makes you look like a balloon
6. The freezing point of human blood is 31 degrees, so let's keep our fingers crossed shall we?30-40 degree range
7.It's too cold to for a walk and too hot to go sledding, so go screw yourself
8. Looks like you'll be looking for warmth again, we all know how that will go
40-50 degree range
9.Whatever drink you get to keep you warm, I hope you spill it all over yourself
10.The temperature right now is the number of reasons why you're a loser
50 - 60 degree range
11. Slightly cool, slightly warm. I don't know anymore, so screw you
12.The temperature isas meh as your looks
60-70 degree range
13.It's getting kind of hot in here, I hope your body oder doesn't show
14.You should go outside and enjoy the weather.Oh wait, you're a loser my bad
70 - 80 degree range
15. It's so warm, unlike your personality
16.The temperature right now is pretty great to be honest.The only thing inmy way is you
80-90 degree range
17.It' really hot, unlike you
18. Global warming is coming for you!
90 - 100 degree range
19. Time to starting wearing less, but no one wants to see that
20. Some people wanna watch the world burn, like me
Sources
Snarky Female Voice –> Jolie Ma
Robotic Male Voice –> https://voicemaker.in/
Insults –> Katarina Garcia, Soomin Kong, Jolie Ma, Gabriel Prado
OpenMeteo API Code –> https://diotlabs.daraghbyrne.me/docs/working-with-data/webhooks/openmeteo_weather (by Daragh Byrne)