From 9a6ba5cb4407c662710e369667421c029059715c Mon Sep 17 00:00:00 2001 From: judahr Date: Wed, 6 Nov 2019 15:17:27 -0500 Subject: [PATCH 1/2] fixed weatherAPI Started on an alternate news feed. --- config.py | 11 +++-- vectorator.py | 123 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 50 deletions(-) diff --git a/config.py b/config.py index 2904f4a..7b5df66 100644 --- a/config.py +++ b/config.py @@ -1,9 +1,10 @@ -#loc_city = "No longer supported" # Enter your city name (this is for the weather) -#loc_region = "No longer supported" # Enter either your state or country -weather_location = "" # Seems pretty flexible: city, state; major city name; zip code; city, country +#loc_city = "" # Enter your city name (this is for the weather) +#loc_region = "" # Enter either your state or country +weather_location = "" news_count = 2 # How many news stories Vector should read (max is 7 to 9) vector_mood = "normal" # Normal is the only mood at the moment -temperature = "farenheit" # Enter "farenheit" or "celsius" +temperature = "imperial" # Enter "imperial" or "metric" chattiness = 6 # Enter a number between "1" and "10". The number "5" is average. ("10" is VERY chatty.) This feature still needs work. sound_volume = 1 # Vector's sound effects between "1" and "5". (5 is very loud) -voice_volume = 2 # Vector's voice volume between "1" and "5". (5 is very loud) \ No newline at end of file +voice_volume = 3 # Vector's voice volume between "1" and "5". (5 is very loud) +news_feed = "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml" #I think you can use any rss feed for this \ No newline at end of file diff --git a/vectorator.py b/vectorator.py index c2f8be1..ca18b12 100644 --- a/vectorator.py +++ b/vectorator.py @@ -15,6 +15,7 @@ from anki_vector.user_intent import UserIntent, UserIntentEvent import apis import config +import sys, traceback # (I think these are called enums in Python... They relate to my dialogue.csv file) NAME = 0 @@ -204,10 +205,15 @@ def vector_react(arg): # This makes Vector talk by looking up dialogue in the dlg file def say(arg_name): - row_start = dic[arg_name] - row_end = row_start + int(dlg[row_start][LINES]) # Use row_start and LINES (from dialogue file) to figure out where the dialogue starts/stops - num_row = get_low(row_start,row_end-1) - to_say = dlg[num_row][MOOD] # Vector's default mood is "normal", eventually he will say different dialogue based on his mood + if arg_name in dic: + row_start = dic[arg_name] + print(row_start) + row_end = row_start + int(dlg[row_start][LINES]) # Use row_start and LINES (from dialogue file) to figure out where the dialogue starts/stops + num_row = get_low(row_start,row_end-1) + to_say = dlg[num_row][MOOD] # Vector's default mood is "normal", eventually he will say different dialogue based on his mood + else: + to_say = "" + if arg_name == "wake_word" : return # If wake_word then skip talking for a bit if arg_name == "news_intro": to_say = to_say + get_news() + get_weather("forecast") # if news then add to end of intro if arg_name == "joke_intro": to_say = to_say + get_joke() # if joke then add to end of intro @@ -215,6 +221,7 @@ def say(arg_name): if arg_name == "time_intro": to_say = to_say + get_time() # Randomly announce the time if arg_name == "random_weather": to_say = get_weather("random_weather") # Randomly announce a weather fact if arg_name == "stranger": to_say = to_say + get_pickupline() + if arg_name == "weather_forecast": to_say = get_weather("forecast") to_say = randomizer(to_say) # This replaces certain words with synonyms max_attempts = 15 # Had to add this after the last update. I'm having trouble getting control of Vector to speak @@ -272,12 +279,20 @@ def say_sleep(arg_name): robot.audio.set_master_volume(VOL[config.sound_volume]) robot.conn.release_control() + +def average(number1, number2): + return (number1 + number2) / 2 + # An API call that allows Vector to deliver a weather forecast (it's not always accurate, in my experience) def get_weather(var): #10/23/2019 JDR new API endpoint (and terms) try: #location can be city, state; city, country; zip code. - url = f"http://api.weatherstack.com/current?access_key={apis.api_weather}&query={config.weather_location}&units={config.temperature[0]}" + + if var == "forecast": + url = f"http://api.openweathermap.org/data/2.5/forecast?APPID={apis.api_weather}&q={config.weather_location}&units={config.temperature}" + else: + url = f"http://api.openweathermap.org/data/2.5/weather?APPID={apis.api_weather}&q={config.weather_location}&units={config.temperature}" print(url) req = urllib.request.Request( url, @@ -286,25 +301,36 @@ def get_weather(var): ) data = urllib.request.urlopen(req).read() output = json.loads(data) - #10/23/2019 JDR free api, no forecast (weather.gov for US?) - #forecast_condition = output["forecast"]["forecastday"][0]["day"]["condition"]["text"] - #10/23/2019 JDR new API object - current_condition = output["current"]["weather_descriptions"] - #forecast_avghumidity = output["forecast"]["forecastday"][0]["day"]["avghumidity"] - current_humidity = output["current"]["humidity"] - weather_name = output["location"]["name"] - weather_region = output["location"]["region"] + print(data) - #New API, specify the units in the request - current_temp_feelslike = output["current"]["feelslike"] - current_temp = output["current"]["temperature"] - current_wind = output["current"]["wind_speed"] + if var == "forecast": + #section = + forecast_condition = output["list"]["weather"]["description"] + forecast_humidity = output["list"]["main"]["humidity"] + forecast_temp = output["list"]["main"]["temp"] + forecast_temp_high = output["list"]["main"]["temp_min"] + forecast_temp_low = output["list"]["main"]["temp_max"] + + forecast_wind = output["list"]["wind"]["speed"] + else: + #10/23/2019 JDR free api, no forecast (weather.gov for US?) + #forecast_condition = output["forecast"]["forecastday"][0]["day"]["condition"]["text"] + #10/23/2019 JDR new API object + current_condition = output["weather"]["description"] + #forecast_avghumidity = output["forecast"]["forecastday"][0]["day"]["avghumidity"] + current_humidity = output["main"]["humidity"] + + #weather_name = output["location"]["name"] + #weather_region = output["location"]["region"] + + #New API, specify the units in the request + #current_temp_feelslike = output["current"]["feelslike"] + current_temp = average(output["main"]["temp_min"], output["main"]["temp_max"]) + current_wind = output["wind"]["speed"] if config.temperature == "farenheit": #forecast_temp_avg = output["forecast"]["forecastday"][0]["day"]["avgtemp_f"] - #forecast_temp_high = output["forecast"]["forecastday"][0]["day"]["maxtemp_f"] - #forecast_temp_low = output["forecast"]["forecastday"][0]["day"]["mintemp_f"] #forecast_wind = output["forecast"]["forecastday"][0]["day"]["maxwind_mph"] wind_speed = " miles per hour" else: @@ -315,29 +341,31 @@ def get_weather(var): wind_speed = " kilometers per hour" # In the morning, Vector tells the news and weather when he sees a face - # if var == "forecast": - # weather = [] - # weather.append(f". And now for some weather. Today in {config.loc_city} {config.loc_region}, it will be {forecast_condition}, with a temperature of {forecast_temp_high} degrees, and wind speeds around {forecast_wind}{wind_speed}. Right now, it is {current_temp} degrees.") - # weather.append(f". Right now in {config.loc_city} {config.loc_region}, it is {current_temp} degrees and {current_condition}. Later today, it will be {forecast_condition}, with a high of {forecast_temp_high} degrees and a low of {forecast_temp_low} degrees.") - # weather.append(f". Here's your local weather. The temperature in {config.loc_city} {config.loc_region} right now, is {current_temp} degrees. The high today will be {forecast_temp_high} degrees, and look for a low of around {forecast_temp_low}. Winds will be {forecast_wind}{wind_speed}.") - # weather.append(f". Moving to the weather. It is currently {current_condition} in {config.loc_city} {config.loc_region}. Later today it will be {forecast_condition}, with an average temperature of {forecast_temp_avg} degrees, and wind speeds around {forecast_wind}{wind_speed}.") - # return(random.choice(weather)) + if var == "forecast": + weather = [] + weather.append(f". And now for some weather. Today, it will be {forecast_condition}, with a temperature of {forecast_temp_high} degrees, and wind speeds around {forecast_wind}{wind_speed}. Right now, it is {current_temp} degrees.") + weather.append(f". Right now in {config.loc_city} {config.loc_region}, it is {current_temp} degrees and {current_condition}. Later today, it will be {forecast_condition}, with a high of {forecast_temp_high} degrees and a low of {forecast_temp_low} degrees.") + weather.append(f". Here's your local weather. The temperature in {config.loc_city} {config.loc_region} right now, is {current_temp} degrees. The high today will be {forecast_temp_high} degrees, and look for a low of around {forecast_temp_low}. Winds will be {forecast_wind}{wind_speed}.") + weather.append(f". Moving to the weather. It is currently {current_condition} in {config.loc_city} {config.loc_region}. Later today it will be {forecast_condition}, with an average temperature of {forecast_temp_avg} degrees, and wind speeds around {forecast_wind}{wind_speed}.") + return(random.choice(weather)) # At random times, Vector will see a face and announce something about the weather - # if var == "random_weather": - rnd_weather = [] - if {current_temp} != {current_temp_feelslike}: - rnd_weather.append(f"The current temperature is {current_temp} degrees, but it feels like {current_temp_feelslike} degrees.") - rnd_weather.append(f"Right now, the temperature is {current_temp} degrees.") - if current_wind < 15: - rnd_weather.append(f"Right now, it is a relatively calm {current_temp} degrees, with winds at {current_wind}{wind_speed}.") - else: - rnd_weather.append(f"Right now, it is a blustery {current_temp} degrees, with winds at {current_wind}{wind_speed}.") - rnd_weather.append(f"At this moment, the weather is {current_condition}.") - rnd_weather.append(f"Hello. It is currently {current_temp} degrees. The humidity is {current_humidity} percent.") + if var == "random_weather": + rnd_weather = [] + #if {current_temp} != {current_temp_feelslike}: + # rnd_weather.append(f"The current temperature is {current_temp} degrees, but it feels like {current_temp_feelslike} degrees.") + rnd_weather.append(f"Right now, the temperature is {current_temp} degrees.") + + if current_wind < 15: + rnd_weather.append(f"Right now, it is a relatively calm {current_temp} degrees, with winds at {current_wind}{wind_speed}.") + else: + rnd_weather.append(f"Right now, it is a blustery {current_temp} degrees, with winds at {current_wind}{wind_speed}.") + rnd_weather.append(f"At this moment, the weather is {current_condition}.") + rnd_weather.append(f"Hello. It is currently {current_temp} degrees. The humidity is {current_humidity} percent.") + + except Exception as inst: + print(traceback.format_exc()) - except: - print("Unexpected weather error:", sys.exc_info()[0]) rnd_weather.append("I'm more of an indoor robot.") rnd_weather.append("I have no idea what it is like out there.") rnd_weather.append("I'm a robot, not a weather forecaster.") @@ -410,13 +438,17 @@ def on_wake_word(robot, event_type, event): "imperative_come", "imperative_lookatme", "weather_response"] if j['type'] == "weather_response": - #allow vector to do his built in weather - time.sleep(10) - say("random_weather") + if j["isForecast"] == "true": + print("weather_forecast") + say("weather_forecast") + else: + # allow vector to do his built in weather + time.sleep(10) + say("random_weather") else: if j['type'] in valid_response: print("valid response") - reaction78u = random.choices(["joke_intro", "fact_intro", "time_intro", "random_weather", "last_saw_name"]) + reaction = random.choices(["joke_intro", "fact_intro", "time_intro", "random_weather", "last_saw_name"]) print(reaction) say(reaction[0]) @@ -524,9 +556,10 @@ def on_cube_detected(robot, event_type, event): if not robot.status.is_on_charger: battery_state = robot.get_battery_state() - if battery_state.battery_volts < 3.6: + if battery_state.battery_volts <= 3.63: # <3.61 was too low + print(battery_state.battery_volts) robot.behavior.say_text("I need to find my charger soon.") - time.sleep(30) + time.sleep(90) #if battery_state.battery_level < 2: #robot.behavior.say_text("My battery level is low.") From 78b2fbac90dd757858e7178bcd24971f2c805264 Mon Sep 17 00:00:00 2001 From: judahr Date: Wed, 6 Nov 2019 19:42:32 -0500 Subject: [PATCH 2/2] Update vectorator.py fix post joke animation to use robot provided animations fix weather no longer say the time when prompted with an imperitive fix the mph vs kph use the news_feed in config so you can provide your own rss --- vectorator.py | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/vectorator.py b/vectorator.py index ca18b12..ec8a072 100644 --- a/vectorator.py +++ b/vectorator.py @@ -234,7 +234,10 @@ def say(arg_name): robot.audio.set_master_volume(VOL[config.voice_volume]) # Change voice volume to config setting robot.behavior.say_text(to_say, duration_scalar=1.15) # I slow voice down slightly to make him easier to understand if arg_name == "joke_intro": - robot.anim.play_animation_trigger(random.choice(JOKE_ANIM)) # If a joke, play a random animation trigger + anim_trigger_names = robot.anim.anim_trigger_list + #robot.anim.play_animation_trigger(random.choice(JOKE_ANIM)) # If a joke, play a random animation trigger + robot.anim.play_animation_trigger( + random.choice(anim_trigger_names)) # If a joke, play a random animation trigger robot.conn.release_control() robot.audio.set_master_volume(VOL[config.sound_volume]) # Change sound effects volume back to config setting return @@ -305,19 +308,19 @@ def get_weather(var): print(data) if var == "forecast": - #section = - forecast_condition = output["list"]["weather"]["description"] - forecast_humidity = output["list"]["main"]["humidity"] - forecast_temp = output["list"]["main"]["temp"] - forecast_temp_high = output["list"]["main"]["temp_min"] - forecast_temp_low = output["list"]["main"]["temp_max"] - - forecast_wind = output["list"]["wind"]["speed"] + section =output["list"][0] + forecast_condition = section["weather"][0]["description"] + forecast_humidity = section["main"]["humidity"] + forecast_temp = output["list"][0]["main"]["temp"] + forecast_temp_high = int(round(section["main"]["temp_min"])) + forecast_temp_low = int(round(section["main"]["temp_max"])) + forecast_temp_avg = int(round(average(forecast_temp_high, forecast_temp_low))) + forecast_wind = int(round(section["wind"]["speed"])) else: #10/23/2019 JDR free api, no forecast (weather.gov for US?) #forecast_condition = output["forecast"]["forecastday"][0]["day"]["condition"]["text"] #10/23/2019 JDR new API object - current_condition = output["weather"]["description"] + current_condition = output["weather"][0]["description"] #forecast_avghumidity = output["forecast"]["forecastday"][0]["day"]["avghumidity"] current_humidity = output["main"]["humidity"] @@ -326,10 +329,10 @@ def get_weather(var): #New API, specify the units in the request #current_temp_feelslike = output["current"]["feelslike"] - current_temp = average(output["main"]["temp_min"], output["main"]["temp_max"]) + current_temp = int(round(average(output["main"]["temp_min"], output["main"]["temp_max"]))) current_wind = output["wind"]["speed"] - if config.temperature == "farenheit": + if config.temperature == "imperial": #forecast_temp_avg = output["forecast"]["forecastday"][0]["day"]["avgtemp_f"] #forecast_wind = output["forecast"]["forecastday"][0]["day"]["maxwind_mph"] wind_speed = " miles per hour" @@ -343,10 +346,10 @@ def get_weather(var): # In the morning, Vector tells the news and weather when he sees a face if var == "forecast": weather = [] - weather.append(f". And now for some weather. Today, it will be {forecast_condition}, with a temperature of {forecast_temp_high} degrees, and wind speeds around {forecast_wind}{wind_speed}. Right now, it is {current_temp} degrees.") - weather.append(f". Right now in {config.loc_city} {config.loc_region}, it is {current_temp} degrees and {current_condition}. Later today, it will be {forecast_condition}, with a high of {forecast_temp_high} degrees and a low of {forecast_temp_low} degrees.") - weather.append(f". Here's your local weather. The temperature in {config.loc_city} {config.loc_region} right now, is {current_temp} degrees. The high today will be {forecast_temp_high} degrees, and look for a low of around {forecast_temp_low}. Winds will be {forecast_wind}{wind_speed}.") - weather.append(f". Moving to the weather. It is currently {current_condition} in {config.loc_city} {config.loc_region}. Later today it will be {forecast_condition}, with an average temperature of {forecast_temp_avg} degrees, and wind speeds around {forecast_wind}{wind_speed}.") + weather.append(f". And now for some weather. Today, it will be {forecast_condition}, with a temperature of {forecast_temp_high} degrees, and wind speeds around {forecast_wind}{wind_speed}.") + weather.append(f". Later today, it will be {forecast_condition}, with a high of {forecast_temp_high} degrees and a low of {forecast_temp_low} degrees.") + weather.append(f". Here's your local weather. The high today will be {forecast_temp_high} degrees, and look for a low of around {forecast_temp_low}. Winds will be {forecast_wind}{wind_speed}.") + weather.append(f". Later today it will be {forecast_condition}, with an average temperature of {forecast_temp_avg} degrees, and wind speeds around {forecast_wind}{wind_speed}.") return(random.choice(weather)) # At random times, Vector will see a face and announce something about the weather @@ -380,7 +383,7 @@ def get_news(): bridge = [". And in other news. ", ". In OTHER news... ", ". Taking a look at other news. ", ". Here is another news item. ", ". Here is an interesting story. "] news = "" news_count = config.news_count - feed = feedparser.parse("https://www.cbsnews.com/latest/rss/world") + feed = feedparser.parse(config.news_feed) for post in feed.entries: news = news + post.description say_count += 1 @@ -448,7 +451,9 @@ def on_wake_word(robot, event_type, event): else: if j['type'] in valid_response: print("valid response") - reaction = random.choices(["joke_intro", "fact_intro", "time_intro", "random_weather", "last_saw_name"]) + #took out the time, you can already ask for that. + #taking out last_saw_name until I check to see if he has seen a face he knows. + reaction = random.choices(["joke_intro", "fact_intro", "random_weather"]) print(reaction) say(reaction[0])