A simple Python script that sends OpenWeatherMap forecasts to a FreeMobile phone
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

130 lines
4.6 KiB

#!/usr/bin/python3
"""
A simple script that sends the daily weather to a FreeMobile phone
"""
import datetime
import json
import locale
import logging
import os
import pyowm
import requests
import sys
class WeatherToFreemobile():
def __init__(self, config_file):
logging.info('Load configuration from {}'.format(config_file))
with open(config_file) as configuration:
self.config = json.load(configuration)
logging.info('Setting locale')
try:
locale.setlocale(locale.LC_TIME, self.config['locale'])
except locale.Error:
logging.warning(
'Error setting locale {}'.format(self.config['locale'])
)
logging.info('Opening OpenWeatherMap API')
apikey = self.config['openweathermap_apikey']
apilanguage = self.config['openweathermap_language']
self.owm = pyowm.OWM(apikey, language=apilanguage)
def send_sms_to_freemobile(self, message):
"""
Sends a SMS using the FreeMobile API
https://mobile.free.fr/moncompte/index.php?page=options
"""
data = {
'user': self.config['freemobile_user'],
'pass': self.config['freemobile_apikey'],
'msg': bytes(message, 'utf-8').decode('iso-8859-1')
}
logging.debug(data)
logging.info('Contacting FreeMobile API')
r = requests.post('https://smsapi.free-mobile.fr/sendmsg', json=data)
if r.status_code == 200:
logging.info('SMS sent')
else:
logging.warning('SMS *not* sent. Status code %s', r.status_code)
def get_weather(self):
"""
Gets the weather forecast from OpenWeatherMap
"""
city = self.config['openweathermap_city']
number_of_days = self.config['number_of_days']
fc = self.owm.daily_forecast(city, limit=number_of_days+1)
f = fc.get_forecast()
return_message = ["{}".format(city)]
return_message.append("")
for weather in f:
weather_date = weather.get_reference_time('date')
date_diff = weather_date.date() - datetime.date.today()
# Workaround API returning yesterday's weather"
# https://openweathermap.desk.com/customer/en/portal/questions/
# 17649060-between-hours-of-12-midnight-and-7am-gmt-we-are-receiving
# -the-wrong-data-for-most-locations
if(
date_diff < datetime.timedelta(0)
or
date_diff >= datetime.timedelta(number_of_days)
):
logging.info('Skipped {} (cf. API Bug)'.format(weather_date))
else:
temp = weather.get_temperature(unit='celsius')
rain = weather.get_rain().get('all', 0)
return_message.append(
'{date} : {weather}{rain}, {mini}ºC - {maxi}ºC'.format(
date=weather_date.strftime('%A %d').title(),
weather=weather.get_detailed_status(),
mini=round(float(temp['min'])),
maxi=round(float(temp['max'])),
rain=" ({:.1f}mm)".format(rain) if rain else ""
)
)
if(rain and date_diff == datetime.timedelta(0)):
return_message.append(self.get_rain())
return_message.append("")
logging.info("Got the following weather: {}".format(return_message))
return "\n".join(return_message)
def get_rain(self):
"""
Gets the rain forecast from OpenWeatherMap
"""
city = self.config['openweathermap_city']
fc = self.owm.three_hours_forecast(city)
f = fc.get_forecast()
return_message = []
for weather in f:
weather_date = weather.get_reference_time('date')
if(weather_date.date() != datetime.date.today()):
break
return_message.append(" - {:2d}h : {}mm".format(
weather_date.hour,
round(float(weather.get_rain().get('3h', 0)), 1)
))
return "\n".join(return_message)
if __name__ == "__main__":
logging.basicConfig(
level=logging.WARNING,
format=' %(asctime)s - %(levelname)s - %(message)s'
)
if len(sys.argv) > 1:
wtf = WeatherToFreemobile(sys.argv[1])
else:
config_file = os.path.join(
os.path.dirname(os.path.realpath(sys.argv[0])),
'config.json'
)
wtf = WeatherToFreemobile(config_file)
wtf.send_sms_to_freemobile(wtf.get_weather())