· 6 years ago · Nov 19, 2019, 01:48 AM
1from flask import Flask, render_template
2import time
3import sched
4import pyttsx3
5import logging
6import json
7import requests
8import datetime
9
10engine1 = pyttsx3.init() # Initialises the text to speech engine
11WeatherData : list = [] # List to store weather data fetched via the API
12NewsData : list = [] # List to store news data fetched via the API
13CurrentEvents: list =[] #List to store various events
14EventCounter: int = 0 #List to count the various elements
15
16
17
18Alarms : list = [{'name', 'date', 'time' }] # A list consisting of the basic features of the alarm
19
20app=Flask(__name__)
21
22def get_APIdata (Location, Weatherkey, Newskey):
23 """Function to get data from the internet, and append these to their
24 relative global lists
25 Arguments:
26 Location-String which stores the location to use when getting data
27 Weatherkey-String which stores the API key for weather when getting data
28 Newskey-String which stores the API key for news when getting data
29 """
30 global News_info #Global list which stores news information
31 global Weather_info #Global list which stores weather information
32
33 while True: # Ensures the loop works until the application closes
34 weather_api_url #should be a link to the api site, usin the weatherkey and the location
35 weather_data = requests.get(weather_api_url).json() #Takes the data in JSON form from weather_api_url
36 tempweather: list = [weather_data['main'], weather_data['weather'], weather_data['clouds'], weather_data['wind']] #list stores weather info from the online source
37 WeatherData.append(tempweather[0][0].get('description')) #Adds the data from the online source to the Weather_Data list
38 temp_celsius = tempweather.get('temp')-273.15 #Converts the temperature to celsius
39 WeatherData.append(round(temp_celsius)) #Adds the data (rounded value) to the WeatherData list
40 WeatherData.append(tempweather.get('humidity'))#Adds the humidity data to the WeatherData list
41 WeatherData.append(tempweather.get('speed'))#Adds the wind speed data to the WeatherData list
42 WeatherData.append(tempweather.get('pressure'))#Adds the pressure data to the WeatherData list
43 WeatherData.append(tempweather.get('deg'))#Adds the wind heating data to the WeatherData list
44
45 newsapi_url = ''+ Newskey #similarly to the weather api link, could not get this to work
46 news_data=requests.get(newsapi_url).json()#Takes the data in JSON form from newsapi_url
47 article = news_data["headlines"] #Creates a list to store the "headlines from the url
48
49 for hd in headline:# Loops through each "headline"
50 NewsData.append(hd["title"], hd["link"])#Append the appropriate and title to the NewsData list
51 time.sleep(180)# sleep for 3 mins
52 NewsData=[]#resets the news data list
53 WeatherData=[]#reset the weather data list
54
55def set_output (content, priority_level):
56 """This function takes a notification message and its corresponding priority level
57 , it then adds (logs) it to the logfile and adds it to the Eventslist list
58
59 Arguments
60 priority_level- Stores the priority message as a string
61 content-Stores the actual notification message as a string
62 """
63 global EventCounter #Initialises EventCounter
64 if (priority_level != "debug"): #Checks whether the priority level is the "debug" level
65 logging.info(content) #if the content is not of the "debug" priority level
66 else:# selectio statement for if the priority level is of debug
67 logging.debug(content) # logs the content as debug
68 CurrentEvents.append([int(EventCounter), priority_level, content]) #Add the notification message to the Events list
69 EventCounter+=1 #the value of th eventcounter is increased by1
70 engine1.say(content) #Loads the notification message, using the text to speech engine
71 engine1.runAndWait() #"Says" the message using the text to speech engine
72 engine1.stop() # Stops the text to speech engine
73 print("[level:" + priority_level + "]"+ content) #Displays the priority level and the content of the notification
74
75@app.route('/')
76def home():
77 """Contains all the code to run for each "GET" request for the data
78 Each get request takes data form the config.JSON file
79 """
80 ##sort ?
81 with open('system.json') as json_data_file: #opens system.json
82 data= json.load(json_data_file) #data is read from the json file
83 LocationData = data['API']['Location'] #Gets the location data for the weather
84 return render_template('homepage.html', NewsData = NewsData, Location=LocationData, Location=WeatherLocation, CurrentEvents=CurrentEvents)
85
86def alarm_notification(alarmname='default'):
87 """Function to check for alarm, and create an appropriate notification if the check returns a value of true
88
89 Arguments
90 alarmname-name of the alarm
91 """
92 alarm_check = false; #Initially set the alarm_check as false
93 for (int i=0; i<len(Alarms)-1; i++) { #Check thru the Alarms
94 if Alarms[i].get('name')==alarmname: # Checks thru the Alarms list for alarms with matching names
95 alarm_check=True #Sets the value of alarm_check as true, if there is a match
96 }
97 if alarm_check =True: #Check if the vaue of alarm_check is equal to true
98 output = "Your alarm:" + alarmname + " has been sounded!" # Crates an output variable that contains a message
99 set_output("alert", output) # Uses the output variable as an argument , and creates an "alert" notification
100
101def schedulealarm(alarmname, timetoalarm):
102 """Utilises the scheduler module to add an alarm to the scheduler. This also creates a "set alarm" notification
103
104 Arguments
105 alarmname- Name of the alarm
106 timetoalarm- Difference (in seconds) between current time and the alarm time
107 """
108 notification="Your alarm:" + alarmname + " has been set!" #creates a notification message consisting of the alarmname
109 set_output("Great Success", notification) #Uses the notification message in the function call for set_output
110 q.enter(timetoalarm, 1, alarm_notification, kwargs={'alarmname':alarmname} ) # Creates a scheduler event using timetoalarm.
111
112
113@app.route('/alarms')
114def alarmpage():
115 """Details the sections of code that are to be run a request is made to the
116 alarms directory
117 """
118 return render_template('alarms.html', Alarms=Alarms)
119 # alarms.html page is displayed in the web client
120
121@app.route('/alarms', method=['POST'])
122def setalarm():
123 """
124 Details the code to run for POST requests to the /alarms section
125
126
127 """
128 tempdata = { #creates a temporary list which stores the date, name and time of the alarm
129 "date": (request.form['alarmdate'])
130 "name": (request.form['alarmname'])
131 "time": (request.form['alarmtime'])
132 }
133
134 date = (request.form['alarmdate'].split("-")) #Creates a list called date, which splits the data from the web form
135 time = (request.form['alarmtime'].split(":")) #Creates a list called time, which splits the data from the web form
136
137 Alarms.append(tempdata) #Adds the list to Alarms
138 currentdatetime = datetime.datetime.now() #gets the current time and date
139 currentdate=datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, now.second)
140 alarmdate=datetime.datetime(int(date[0]), int (date[0]), int(time1[0]), int(time1[1]), 0)
141 timediff = (b-a).timetoseconds() #calculates the difference in time between the 2 datetime variables above
142 t=threading.Thread(target=schedulealarm, args=(Alarms[i].get('name'),timediff)) #create a thread called t , using the various listed arguments
143 t.start() #starts the thread
144 return redirect("/")
145
146@app.route('/alarms/<alarm_id>')
147def alarm_ID(alarm_id):
148 if request.form['button'] == "UpdateAlarm": # Checks whether the button has been clicked/pressed
149 for i in range (len(Alarms)): #Loops through the ALarms list
150 if Alarms[i]['name']==alarm_id: #Checks whether the alarm id matches
151 datelist= Alarms[i].get('date').split("-") #Creates a list from the date in the list
152 timelist=Alarms[i].get('time').split(":") #Creates a list from the time in the list
153
154 Alarms[i]['name'] = request.form['alarmname']
155 Alarms[i]['date'] = request.form['alarmdate']
156 Alarms[i]['time'] = request.form['alarmtime'] #Updates the name, date and time respectively of the alarm
157
158 currenttime=datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, now.second)
159 alarmtime = datetime.datetime(int(date[0]), int(datelist[0]), int(datelist[1]), int(datelist[2]), int(timelist[0]), int(time_1[1]),0)
160 timediff =(alarmtime-currenttime).total_seconds() #Calculates the difference(in seconds) between the current time and the time of the alarm
161 alarmthread=threading.Thread(target=schedulealarm, args=(Alarms[i].get('name'), temptime))
162 alarmthread.start()
163 #creates and starts a thread called alarmthread
164
165
166
167 notif_warning ="Settings for Alarm '"+ str(Alarms[i]['name'])+ "'were updated" #Notification displayed when the alarm is updated
168 set_output("warning", notif_warning)#calls the set_output function using the arguments message and warning
169 now=datetime.datetime.now()
170
171
172 return redirect("/alarms")
173 elif request.form['submit']=="Delete": #Selection statement for if the user decides to delete an alarm
174 for i in range(len(Alarms)): #Loops through the Alarms list
175 if Alarms[i]['name']==alarm_ID: #Selection statement for if
176 ouptut ="Alarm "+ str(Alarms[i]['name']) + "'was deleted!" #Shows an appropriate message in the event that the user deletes an alarm
177 set_output("warning", ouput) #Calls the set_output function using the warning and output arguments
178 del Alarms[i] #Delete the specified alarm
179 break #break
180 return redirect("/alarms")
181
182@app.route('/notifications/<notification_id>')
183def clear_notification(notificationindex):
184 """
185 Details the code required for each GET request
186
187 Arguments
188 notificationindex: Name of the current web page
189 """
190
191 for notification in Events: #Loops through the Events list
192 if int(notification[0]) == int(notification_id): #Selection statement for if the notifications indicated match
193 CurrentEvents.remove(notification) #Removes the indicated notification
194 return redirect("/") #Redirects the user to "/"
195
196
197
198if __name__ == '__main__':
199 with open('system.json') as json_data_file: #Opens the system.json file
200 dataconfig=json.load(json_data_file) # Gets the data from the file
201 WeatherKey=dataconfig['API']['WeatherKey'] #Gets the WeatherKey from the data file
202 NewsKey=dataconfig['API']['NewsKey']#Gets the NewsKey from the data file
203 Location =dataconfig['API']['Location']#Gets the location from the data file
204 for alarm in Alarms:# Loops through the Alarms list
205 dateofalarm=alarm.get('date').split(":")
206 timeofalarm=alarm.get('time').split(":")#Split the date and time into lists
207 nameofalarm=alarm.get('name') #Get the name of the alarm
208 currentdetails=datetime.datetime.now() # Get the current date and time
209
210 currentdatetime=datetime.datetime(now.year, now.month, now.day, now.minute, now.second)
211 alarmdatetime=datetime(int(date[0]), int(date[1]), int(dateofalarm[2]), int(timeofalarm[0]), int(timeofalarm[1]),0)
212 timediff= (alarmdatetime-currentdatetime) # Calculate the difference between the current time and the alarm time
213 new_thread=threading.Thread(target=schedulealarm, args=(nameofalarm, timediff))
214 #Create a thread called new_thread that has the target of schedulealarm, with
215 new_thread.start()
216
217 #Creates a log with the name Alarmlogm and saves it as a .log
218 AlarmLog=(data['']['']+ datetime.datetime.now().replace(microsecond=0).isoformat()+ '.log')
219 #Alters the configuration of the built-in logger, and allows for logging at the "info" level diagnostics
220 logging.basicConfig(filename=AlarmLog, filemode='w', level = logging.INFO, format='%(asctime)s-%(levelname)s-%(message)s')
221 #Creates a thread called background, which has a target of pull data, alongside APIkey and location
222 background=threading.Thread(target=pull_data, args=(WeatherKey, NewsKey, Location))