1
1
"""The mawaqit_prayer_times component."""
2
- from datetime import timedelta
3
2
import logging
4
3
import os
5
4
import json
6
- import sys
5
+ # import sys
7
6
import shutil
8
- from datetime import datetime
9
- #from mawaqit_times_calculator import MawaqitClient, exceptions
10
- from .mawaqit import MawaqitClient , BadCredentialsException
7
+
8
+ from datetime import datetime , timedelta
9
+ from dateutil import parser as date_parser
10
+
11
+ from .mawaqit import BadCredentialsException #, MawaqitClient
11
12
12
13
from requests .exceptions import ConnectionError as ConnError
14
+
13
15
import voluptuous as vol
14
16
15
17
from homeassistant .config_entries import SOURCE_IMPORT
18
20
from homeassistant .helpers .dispatcher import async_dispatcher_send
19
21
from homeassistant .helpers .event import async_call_later , async_track_point_in_time
20
22
import homeassistant .util .dt as dt_util
21
- from homeassistant .helpers import aiohttp_client
22
- from datetime import datetime , timedelta
23
- from dateutil import parser as date_parser
23
+ # from homeassistant.helpers import aiohttp_client
24
24
25
25
26
26
from .const import (
38
38
CALC_METHODS ,
39
39
)
40
40
41
- from homeassistant .const import CONF_LATITUDE , CONF_LONGITUDE , CONF_PASSWORD , CONF_USERNAME , CONF_API_KEY , CONF_TOKEN
42
-
41
+ # from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_PASSWORD, CONF_USERNAME, CONF_API_KEY, CONF_TOKEN
43
42
44
43
_LOGGER = logging .getLogger (__name__ )
45
44
46
45
PLATFORMS = ["sensor" ]
47
46
47
+
48
48
CONFIG_SCHEMA = vol .Schema (
49
49
vol .All (
50
50
cv .deprecated (DOMAIN ),
59
59
extra = vol .ALLOW_EXTRA ,
60
60
)
61
61
62
+
62
63
def is_date_parsing (date_str ):
63
64
try :
64
65
return bool (date_parser .parse (date_str ))
65
66
except ValueError :
66
67
return False
67
-
68
+
69
+
68
70
async def async_setup (hass , config ):
69
71
"""Import the Mawaqit Prayer component from config."""
70
72
if DOMAIN in config :
@@ -73,7 +75,6 @@ async def async_setup(hass, config):
73
75
DOMAIN , context = {"source" : SOURCE_IMPORT }, data = config [DOMAIN ]
74
76
)
75
77
)
76
-
77
78
return True
78
79
79
80
@@ -91,8 +92,6 @@ async def async_setup_entry(hass, config_entry):
91
92
return True
92
93
93
94
94
-
95
-
96
95
async def async_unload_entry (hass , config_entry ):
97
96
"""Unload Mawaqit Prayer entry from config_entry."""
98
97
current_dir = os .path .dirname (os .path .realpath (__file__ ))
@@ -108,10 +107,10 @@ async def async_unload_entry(hass, config_entry):
108
107
except OSError as e :
109
108
print ("Error: %s : %s" % (dir_path , e .strerror ))
110
109
111
-
112
110
if hass .data [DOMAIN ].event_unsub :
113
111
hass .data [DOMAIN ].event_unsub ()
114
112
hass .data .pop (DOMAIN )
113
+
115
114
return await hass .config_entries .async_unload_platforms (config_entry , PLATFORMS )
116
115
117
116
@@ -127,124 +126,143 @@ def __init__(self, hass, config_entry):
127
126
self .event_unsub = None
128
127
129
128
130
-
131
129
@property
132
130
def calc_method (self ):
133
131
"""Return the calculation method."""
134
132
return self .config_entry .options [CONF_CALC_METHOD ]
135
133
134
+
136
135
def get_new_prayer_times (self ):
137
136
"""Fetch prayer times for today."""
138
137
mawaqit_login = self .config_entry .data .get ("username" )
139
138
mawaqit_password = self .config_entry .data .get ("password" )
140
- mawaqit_latitude = self .config_entry .data .get ("latitude" ) # self.hass.config.latitude
141
- mawaqit_longitude = self .config_entry .data .get ("longitude" ) #self.hass.config.longitude
142
-
143
- mosquee = self .config_entry .options .get ("calculation_method" )
144
-
145
-
146
-
139
+ mawaqit_latitude = self .config_entry .data .get ("latitude" )
140
+ mawaqit_longitude = self .config_entry .data .get ("longitude" )
147
141
142
+ mosque = self .config_entry .options .get ("calculation_method" )
148
143
149
144
current_dir = os .path .dirname (os .path .realpath (__file__ ))
150
145
151
-
152
-
153
-
154
-
155
146
name_servers = []
156
147
uuid_servers = []
157
148
CALC_METHODS = []
149
+
158
150
with open ('{}/data/all_mosquee_NN.txt' .format (current_dir ), "r" ) as f :
159
151
distros_dict = json .load (f )
152
+
160
153
for distro in distros_dict :
161
154
name_servers .extend ([distro ["label" ]])
162
155
uuid_servers .extend ([distro ["uuid" ]])
163
156
CALC_METHODS .extend ([distro ["label" ]])
164
157
165
-
166
-
167
-
168
- if mosquee == "nearest" or mosquee == "no mosque in neighborhood" :
158
+ if mosque == "nearest" or mosque == "no mosque in neighborhood" :
169
159
indice = 0
170
160
else :
171
- indice = name_servers .index (mosquee )
172
- mosque_id = uuid_servers [indice ]
161
+ indice = name_servers .index (mosque )
173
162
174
-
175
-
176
- #update my_mosque file whenever the user changes it in the option
177
- #f = open('{dir}/data/all_mosquee_NN.txt'.format(dir=current_dir ))
178
- #data = json.load(f)
179
- #text_file = open('{}/data/my_mosquee_NN.txt'.format(current_dir), "w")
180
- #json.dump(data[indice], text_file)
181
- #text_file.close()
163
+ mosque_id = uuid_servers [indice ]
182
164
183
- #readiding prayer times
184
- f = open ('{dir}/data/pray_time.txt' .format (dir = current_dir , name = "" ))
165
+ # We get the prayer times of the year from pray_time.txt
166
+ f = open ('{dir}/data/pray_time.txt' .format (dir = current_dir , name = "" ))
167
+
185
168
data = json .load (f )
186
169
calendar = data ["calendar" ]
170
+
171
+ # Then, we get the prayer times of the day into this file
187
172
today = datetime .today ()
188
- index_month = month = today .month - 1
189
- month_times = calendar [index_month ]
173
+ index_month = today .month - 1
174
+ month_times = calendar [index_month ] # Calendar of the month
175
+
190
176
index_day = today .day
191
- day_times = month_times [str (index_day )]
192
- salat_name = ["Fajr" , "Shurouq" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
193
- res = {salat_name [i ]: day_times [i ] for i in range (len (salat_name ))}
177
+ day_times = month_times [str (index_day )] # Today's times
178
+
179
+ prayer_names = ["Fajr" , "Shurouq" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
180
+ res = {prayer_names [i ]: day_times [i ] for i in range (len (prayer_names ))}
181
+
182
+ try :
183
+ day_times_tomorrow = month_times [str (index_day + 1 )]
184
+ except KeyError :
185
+ # If index_day + 1 == 32 (or 31) and the month contains only 31 (or 30) days
186
+ # We take the first prayer of the following month
187
+ day_times_tomorrow = calendar [index_month + 1 ]["1" ]
194
188
195
- maintenant = today .time ().strftime ("%H:%M" )
189
+ now = today .time ().strftime ("%H:%M" )
196
190
191
+ today = datetime .today ().strftime ("%Y-%m-%d" )
192
+ tomorrow = (datetime .today () + timedelta (days = 1 )).strftime ("%Y-%m-%d" )
197
193
198
-
199
- day_times = month_times [str (index_day )]
200
- day_times_tomorrow = month_times [str (index_day + 1 )]
201
- maintenant = today .time ().strftime ("%H:%M" )
202
- tomorrow = (datetime .today ()+ timedelta (days = 1 )).strftime ("%Y-%m-%d" )
203
- aujourdhui = (datetime .today ()+ timedelta (days = 0 )).strftime ("%Y-%m-%d" )
204
- print (tomorrow )
205
- liste = []
206
- for j in range (len (salat_name )):
207
- if salat_name [j ] == "Shurouq" :
208
- pray = tomorrow + " " + "23:59:00" #never account shurouq in the calculation of next_salat
194
+ prayers = []
195
+ for j in range (len (prayer_names )):
196
+ if prayer_names [j ] == "Shurouq" :
197
+ pray = tomorrow + " " + "23:59:00" # We never take in account shurouq in the calculation of next_salat
209
198
else :
210
- if datetime .strptime (day_times [j ], '%H:%M' ) < datetime .strptime (maintenant , '%H:%M' ):
211
- pray = tomorrow + " " + day_times_tomorrow [j ] + ":00"
199
+ if datetime .strptime (day_times [j ], '%H:%M' ) < datetime .strptime (now , '%H:%M' ):
200
+ pray = tomorrow + " " + day_times_tomorrow [j ] + ":00"
212
201
else :
213
- pray = aujourdhui + " " + day_times [j ] + ":00"
214
- liste .append (pray )
215
-
216
- res ['Next Salat Time' ]= min (liste ).split (" " ,1 )[1 ].rsplit (':' , 1 )[0 ]
217
- res ['Next Salat Name' ]= salat_name [liste .index (min (liste ))]
218
- #15 minutes before next salat
219
- res ['Next Salat Preparation' ] = (datetime .strptime (min (liste ), '%Y-%m-%d %H:%M:%S' )- timedelta (minutes = 15 )).strftime ('%Y-%m-%d %H:%M:%S' ).split (" " ,1 )[1 ].rsplit (':' , 1 )[0 ]
202
+ pray = today + " " + day_times [j ] + ":00"
203
+
204
+ prayers .append (pray )
205
+
206
+ # Then the next prayer is the nearest prayer time, so the min of the prayers list
207
+ next_prayer = min (prayers )
208
+ res ['Next Salat Time' ] = next_prayer .split (" " , 1 )[1 ].rsplit (':' , 1 )[0 ]
209
+ res ['Next Salat Name' ] = prayer_names [prayers .index (next_prayer )]
210
+
211
+ # 15 minutes Before Next Prayer
212
+ countdown_next_prayer = 15
213
+ res ['Next Salat Preparation' ] = (datetime .strptime (next_prayer , '%Y-%m-%d %H:%M:%S' )- timedelta (minutes = countdown_next_prayer )).strftime ('%Y-%m-%d %H:%M:%S' ).split (" " , 1 )[1 ].rsplit (':' , 1 )[0 ]
214
+
215
+
216
+ # if Jumu'a is set as Dhuhr, then Jumu'a time is the same as Friday's Dhuhr time
217
+ if data ["jumuaAsDuhr" ]:
218
+ # Then, Jumu'a time should be the Dhuhr time of the next Friday
219
+ today = datetime .today ()
220
+ # We get the next Friday
221
+ next_friday = today + timedelta ((4 - today .weekday () + 7 ) % 7 )
222
+ # We get the next Friday's Dhuhr time from the calendar
223
+ next_friday_dhuhr = calendar [next_friday .month - 1 ][str (next_friday .day )][2 ]
224
+ res ['Jumua' ] = next_friday_dhuhr
225
+
226
+ # If jumu'a is set as a specific time, then we use that time
227
+ elif data ["jumua" ] is not None :
228
+ res ['Jumua' ] = data ["jumua" ]
229
+
230
+ # if mosque has only one jumu'a, then 'Jumua 2' can be None.
231
+ if data ["jumua2" ] is not None :
232
+ res ['Jumua 2' ] = data ["jumua2" ]
233
+
220
234
res ['Mosque_label' ]= data ["label" ]
221
235
res ['Mosque_localisation' ]= data ["localisation" ]
222
- res ['Mosque_url' ]= data ["url" ]
236
+ res ['Mosque_url' ]= data ["url" ]
223
237
res ['Mosque_image' ]= data ["image" ]
224
238
225
- #Iqama timing
239
+ # The Iqama countdown from Adhan is stored in pray_time.txt as well.
226
240
iqamaCalendar = data ["iqamaCalendar" ]
227
- iqama = iqamaCalendar [index_month ][str (index_day )]
241
+ iqamas = iqamaCalendar [index_month ][str (index_day )] # Today's iqama times.
228
242
try :
229
- iqama = [int (s .replace ("+" , "" )) for s in iqama ]
243
+ # The iqama countdown is stored as a string with a + sign.
244
+ # So, we need to remove the + and convert the countdown to an int.
245
+ iqamas = [int (countdown .replace ("+" , "" )) for countdown in iqamas ]
230
246
except ValueError :
231
- iqama = [0 ,0 , 0 , 0 , 0 ]
247
+ iqamas = [0 , 0 , 0 , 0 , 0 ]
232
248
233
- salat = [datetime .strptime (s , '%H:%M' ) for s in day_times ]
234
- del salat [1 ] #no iqama for shurouq
235
- iqama_list = []
236
- for (item1 , item2 ) in zip (salat , iqama ):
237
- iqama_list .append ((item1 + timedelta (minutes = item2 )).strftime ("%H:%M" ))
238
- iqama_name = ["Fajr Iqama" , "Dhuhr Iqama" , "Asr Iqama" , "Maghrib Iqama" , "Isha Iqama" ]
239
- res1 = {iqama_name [i ]: iqama_list [i ] for i in range (len (iqama_name ))}
240
- res2 = {** res , ** res1 }
241
- return res2
249
+ # We store the prayer times of the day in HH:MM format.
250
+ prayers = [datetime .strptime (prayer , '%H:%M' ) for prayer in day_times ]
251
+ del prayers [1 ] # Because there's no iqama for shurouq.
242
252
243
-
244
-
253
+ # We store the iqama times of the day in HH:MM format.
254
+ iqama_times = []
245
255
246
-
256
+ for (prayer , iqama ) in zip (prayers , iqamas ):
257
+ iqama_times .append ((prayer + timedelta (minutes = iqama )).strftime ("%H:%M" ))
247
258
259
+ iqama_names = ["Fajr Iqama" , "Dhuhr Iqama" , "Asr Iqama" , "Maghrib Iqama" , "Isha Iqama" ]
260
+
261
+ res1 = {iqama_names [i ]: iqama_times [i ] for i in range (len (iqama_names ))}
262
+
263
+ res2 = {** res , ** res1 }
264
+
265
+ return res2
248
266
249
267
250
268
async def async_schedule_future_update (self ):
@@ -284,20 +302,13 @@ async def async_schedule_future_update(self):
284
302
midnight_dt = self .prayer_times_info ["Next Salat Time" ]
285
303
Fajr_dt = self .prayer_times_info ["Fajr" ]
286
304
Dhuhr_dt = self .prayer_times_info ["Dhuhr" ]
287
- #Shurouq_dt = self.prayer_times_info["Shurouq"]
288
305
Asr_dt = self .prayer_times_info ["Asr" ]
289
306
Maghrib_dt = self .prayer_times_info ["Maghrib" ]
290
307
Isha_dt = self .prayer_times_info ["Isha" ]
291
- liste = []
292
- liste .append (Fajr_dt )
293
- #liste.append(Shurouq_dt)
294
- liste .append (Dhuhr_dt )
295
- liste .append (Asr_dt )
296
- liste .append (Maghrib_dt )
297
- liste .append (Isha_dt )
298
- midnight_dt = min (liste )
299
-
300
308
309
+ prayer_times = [Fajr_dt , Dhuhr_dt , Asr_dt , Maghrib_dt , Isha_dt ]
310
+
311
+ midnight_dt = min (prayer_times )
301
312
302
313
if now > dt_util .as_utc (midnight_dt ):
303
314
next_update_at = midnight_dt + timedelta (days = 0 , minutes = 1 , seconds = 0 )
@@ -331,14 +342,25 @@ async def async_update(self, *_):
331
342
return
332
343
333
344
for prayer , time in prayer_times .items ():
334
- tomorrow = (dt_util .now ().date ()+ timedelta (days = 1 )).strftime ("%Y-%m-%d" )
335
- aujourdhui = dt_util .now ().date ()
336
- maintenant = dt_util .now ().time ().strftime ("%H:%M" )
345
+
346
+ tomorrow = (dt_util .now ().date () + timedelta (days = 1 )).strftime ("%Y-%m-%d" )
347
+ today = dt_util .now ().date ().strftime ("%Y-%m-%d" )
348
+
349
+ now = dt_util .now ().time ().strftime ("%H:%M" )
350
+
337
351
if is_date_parsing (time ):
338
- if datetime .strptime (time , '%H:%M' ) < datetime .strptime (maintenant , '%H:%M' ):
339
- pray = tomorrow
352
+ if datetime .strptime (time , '%H:%M' ) < datetime .strptime (now , '%H:%M' ):
353
+ pray = tomorrow
340
354
else :
341
- pray = aujourdhui
355
+ pray = today
356
+
357
+ if prayer == "Jumua" or prayer == "Jumua 2" :
358
+ # We convert the date to datetime to be able to do calculations on it.
359
+ pray_date = datetime .strptime (pray , "%Y-%m-%d" )
360
+ # The calculation below allows to add the number of days necessary to arrive at the next Friday.
361
+ pray_date += timedelta (days = (4 - pray_date .weekday () + 7 ) % 7 )
362
+ # We convert the date to string to be able to put it in the dictionary.
363
+ pray = pray_date .strftime ("%Y-%m-%d" )
342
364
self .prayer_times_info [prayer ] = dt_util .parse_datetime (
343
365
f"{ pray } { time } "
344
366
)
@@ -348,19 +370,19 @@ async def async_update(self, *_):
348
370
349
371
await self .async_schedule_future_update ()
350
372
351
- _LOGGER .debug ("New prayer times retrieved. Updating sensors" )
373
+ _LOGGER .debug ("New prayer times retrieved. Updating sensors. " )
352
374
async_dispatcher_send (self .hass , DATA_UPDATED )
353
375
354
376
async def async_setup (self ):
355
377
"""Set up the Mawaqit prayer client."""
378
+
356
379
await self .async_add_options ()
357
380
358
381
try :
359
382
await self .hass .async_add_executor_job (self .get_new_prayer_times )
360
383
except (BadCredentialsException , ConnError ) as err :
361
384
raise ConfigEntryNotReady from err
362
385
363
-
364
386
await self .async_update ()
365
387
self .config_entry .add_update_listener (self .async_options_updated )
366
388
0 commit comments