· 6 years ago · Nov 18, 2019, 04:38 PM
1from flask import Flask,request,url_for,redirect,render_template
2import json
3import sched
4import time
5import requests
6from datetime import datetime
7import pyttsx3
8import configparser
9import logging
10import os
11
12#initiate the logging file and set logging level
13logging.basicConfig(filename='data.log',level=logging.INFO)
14#set the directory of the logging file
15log_dir = os.path.join(os.path.normpath(os.getcwd() + os.sep + os.pardir), 'logs')
16log_fname = os.path.join(log_dir,'data.log')
17
18#initiate global lists and scheduler
19s = sched.scheduler(time.time,time.sleep)
20events = []
21alarms = []
22log = []
23
24#initiate flask application and set route
25app = Flask(__name__)
26@app.route("/")
27
28
29#The main functionality of the program, will render the webpage
30def main() -> int and list:
31 #retrieve log
32 global log
33 #call to retrieve api keys
34 apis=get_apis()
35 #call weather using first api key
36 weather_api = apis[0]
37 #call news using second api key
38 news_api = apis[1]
39 news = get_news(news_api)
40 weather = get_weather(weather_api)
41 #set each variable for weather and news to indexs in each array
42 temperature = weather[0]
43 pressure = weather[1]
44 humidity = weather[2]
45 description = weather[3]
46 story1 = news[0]
47 story2 = news[1]
48 story3 = news[2]
49 #retrieve log
50 notif_log = get_alarm()
51 #refresh every 60 seconds
52 s.enter(60,1,main)
53 notif_log = log
54 s.run(blocking=False)
55 #set blocking to false to allow the user to continue using the application
56 #split the queue to allow for correct formatting in html
57 return render_template("index.html",
58 temperature=temperature,pressure=pressure,humidity=humidity,description=description,news = news,
59 story1=story1,story2=story2,story3=story3,notif_log=notif_log)
60 #render page whilst passing variables
61
62
63#function used to parse config file and retrieve api keys
64def get_apis():
65 #set flask_app as path directory name
66 flask_app = os.path.dirname(os.path.abspath(__file__))
67 #assign configuration file
68 config_file = os.path.join(flask_app,'config.json')
69 with open(config_file) as f:
70 #open and extract api keys from config file
71 data = json.load(f)
72 weather_api = data["weather"]
73 news_api = data["news"]
74 #return api keys
75 return weather_api,news_api
76
77
78#Function to update the notifications log to be displayed to the user
79def update_log(text_var: str) -> list:
80 global log
81 #append text variable to log array
82 log.append(text_var)
83 logging.info(str(text_var))
84 #log the event as an INFO
85 return log
86
87app.route("/get_alarm")
88#set route to get_alarm
89
90#Function called when the user is trying to add an alarm
91def get_alarm() -> str and list:
92 global alarms,events
93 #check to see if user is cancelling alarm
94 alarm_to_cancel = request.args.get("alarm_to_cancel")
95 if alarm_to_cancel:
96 #if yes call cancel alarm and pass time variable
97 cancel_alarm(alarm_to_cancel)
98 alarm = request.args.get("alarm")
99 #check to see if alarm is being set
100 #declare list strings which will be displayed on html
101 if alarm:
102 user = request.args.get("user")
103 #request the user name
104 engine = pyttsx3.init()
105 #initiate engine to speak
106 alarm_date_time = time.strptime(alarm,'%Y-%m-%dT%H:%M')
107 alarm_date_time = time.mktime(alarm_date_time)
108 #set alarm to a readable format for scheduler
109 alarm_formatted = alarm.replace("T"," ").strip("''")
110 #format to be readable to human
111 if alarm_formatted in alarms:
112 #if alarm is already in alarms set
113 engine.say("You have already set an alarm for this time")
114 update_log("Alarm already set for that time. No alarm added.")
115 else:
116 engine.say("Your alarm has been set")
117 update_log("Your alarm has been set for "+ str(alarm_formatted) + " with the name "+ str(user))
118 #log and tell the user that their alarm has been set
119 event = s.enterabs(alarm_date_time,1,alarm_over,argument =(alarm,user,))
120 #set the alarm using scheduler
121 events.append(event)
122 #append the alarm to global array alarms
123 s.run(blocking=False)
124 #run the alarm
125 engine.runAndWait()
126 return log
127
128
129#Called when a schedualed alarm is over
130def alarm_over(alarm: datetime ,user: str):
131 engine = pyttsx3.init()
132 engine.say("Alarm set is over")
133 update_log("Alarm for "+str(user)+" is over.")
134 engine.runAndWait()
135
136
137#Function to show the user the latest news
138def get_news(news_api: str) -> str:
139 api_key = str(news_api)
140 #set api key to string
141 url = ('https://newsapi.org/v2/top-headlines?'
142 'sources=bbc-news&'
143 'apiKey='+api_key)
144 response = requests.get(url)
145 #request json from full url
146 n = response.json()
147 titles = []
148 if n["status"] == "ok":
149 for i in n["articles"]:
150 title = (i["title"])
151 titles.append(title)
152 #parse through json and retrieve list of all headlines
153 story1 = titles[0]
154 story2 = titles[1]
155 story3= titles[2]
156 #take the first 3 headlines
157 return story1,story2,story3
158 #return first 3 headlines
159
160
161#Function to gather data of the latest weather in Exeter
162def get_weather(weather_api: str) -> str:
163 api_key = weather_api
164 weather_url = "http://api.openweathermap.org/data/2.5/weather?"
165 complete_url = weather_url + "appid=" + api_key + "&q=exeter"
166 response = requests.get(complete_url)
167 #get respones from full url including api key
168 w = response.json()
169 if w["cod"] != "404":
170 y = w["main"]
171 current_temperature = y["temp"]
172 current_pressure = y["pressure"]
173 current_humidiy = y["humidity"]
174 z = w["weather"]
175 weather_description = z[0]["description"]
176 temperature = (" Temperature (in kelvin unit) = " +
177 str(current_temperature))
178 pressure = ("Atmospheric pressure (in hPa unit) = " +
179 str(current_pressure))
180 humidity = ("Humidity (in percentage) = " + str(current_humidiy))
181 description = ("Description = " + str(weather_description))
182
183 #parse through json file extracting temp, humidity,description and current pressure
184 return temperature,pressure,humidity,description
185
186
187app.route("/")
188#Function used to cancel any currently set alarms
189def cancel_alarm(alarm: datetime):
190 global events
191 alarm_to_cancel = alarm
192 #set alarm to cancel as the alarm
193 alarm_to_cancel = time.strptime(alarm_to_cancel,'%Y-%m-%dT%H:%M')
194 alarm_to_cancel = time.mktime(alarm_to_cancel)
195 #format to a executable format for scheduler
196 alarm_formatted = alarm.replace("T"," ").strip("''")
197 #format to readable for human
198 if len(events) == 0:
199 update_log("No alarm has been set:")
200 #check if any alarms have been set
201 else:
202 cancelled = False
203 for event in events:
204 #iterate through all set alarms
205 for var in event:
206 if var == alarm_to_cancel:
207 #check if time set in event is equal to time requested for cancelling
208 s.cancel(event)
209 update_log("Alarm set for " + str(alarm_formatted)+" has been cancelled.")
210 cancelled = True
211 #log the alarm has been cancelled and set cancelled to true
212 if not cancelled:
213 #if alarm has not been cancelled log to user
214 update_log("No alarm has been found with this time.")
215
216if __name__ == '__main__':
217 app.run(debug=True)