Files
WeatherToFreemobile/weather_to_freemobile.py

131 lines
4.6 KiB
Python
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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())