18
18
from homeassistant .exceptions import ConfigEntryNotReady
19
19
from homeassistant .helpers import config_validation as cv
20
20
from homeassistant .helpers .dispatcher import async_dispatcher_send
21
- from homeassistant .helpers .event import async_call_later , async_track_point_in_time
21
+ from homeassistant .helpers .event import async_call_later , async_track_point_in_time , async_track_time_change
22
22
import homeassistant .util .dt as dt_util
23
23
# from homeassistant.helpers import aiohttp_client
24
24
27
27
API ,
28
28
CONF_CALC_METHOD ,
29
29
DATA_UPDATED ,
30
+ UPDATE_TIME ,
30
31
DEFAULT_CALC_METHOD ,
31
32
DOMAIN ,
32
33
USERNAME ,
@@ -163,7 +164,7 @@ def get_new_prayer_times(self):
163
164
mosque_id = uuid_servers [indice ]
164
165
165
166
# 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
+ f = open ('{dir}/data/pray_time.txt' .format (dir = current_dir ), "r" )
167
168
168
169
data = json .load (f )
169
170
calendar = data ["calendar" ]
@@ -176,15 +177,19 @@ def get_new_prayer_times(self):
176
177
index_day = today .day
177
178
day_times = month_times [str (index_day )] # Today's times
178
179
179
- prayer_names = ["Fajr" , "Shurouq" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
180
+ prayer_names = ["Fajr" , "Shurouq" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
180
181
res = {prayer_names [i ]: day_times [i ] for i in range (len (prayer_names ))}
181
182
182
183
try :
183
184
day_times_tomorrow = month_times [str (index_day + 1 )]
184
185
except KeyError :
185
186
# 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" ]
187
+ # We take the first day of the following month (reset 0 if we're in december)
188
+ if index_month == 11 :
189
+ index_next_month = 0
190
+ else :
191
+ index_next_month = index_month + 1
192
+ day_times_tomorrow = calendar [index_next_month ]["1" ]
188
193
189
194
now = today .time ().strftime ("%H:%M" )
190
195
@@ -208,10 +213,9 @@ def get_new_prayer_times(self):
208
213
res ['Next Salat Time' ] = next_prayer .split (" " , 1 )[1 ].rsplit (':' , 1 )[0 ]
209
214
res ['Next Salat Name' ] = prayer_names [prayers .index (next_prayer )]
210
215
211
- # 15 minutes Before Next Prayer
212
216
countdown_next_prayer = 15
217
+ # 15 minutes Before Next Prayer
213
218
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
219
216
220
# if Jumu'a is set as Dhuhr, then Jumu'a time is the same as Friday's Dhuhr time
217
221
if data ["jumuaAsDuhr" ]:
@@ -263,70 +267,60 @@ def get_new_prayer_times(self):
263
267
res2 = {** res , ** res1 }
264
268
265
269
return res2
270
+
271
+
272
+ async def async_update_next_salat_sensor (self , * _ ):
273
+ salat_before_update = self .prayer_times_info ['Next Salat Name' ]
274
+ prayers = ["Fajr" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
275
+ if salat_before_update != "Isha" : # We just retrieve the next salat of the day.
276
+ index = prayers .index (salat_before_update ) + 1
277
+ self .prayer_times_info ['Next Salat Name' ] = prayers [index ]
278
+ self .prayer_times_info ['Next Salat Time' ] = self .prayer_times_info [prayers [index ]]
279
+
280
+ else : # We retrieve the next Fajr (more calcualtions).
281
+ current_dir = os .path .dirname (os .path .realpath (__file__ ))
282
+ f = open ('{dir}/data/pray_time.txt' .format (dir = current_dir ), "r" )
283
+ data = json .load (f )
284
+ calendar = data ["calendar" ]
266
285
286
+ today = datetime .today ()
287
+ index_month = today .month - 1
288
+ month_times = calendar [index_month ]
267
289
268
- async def async_schedule_future_update (self ):
269
- """Schedule future update for sensors.
270
-
271
- Midnight is a calculated time. The specifics of the calculation
272
- depends on the method of the prayer time calculation. This calculated
273
- midnight is the time at which the time to pray the Isha prayers have
274
- expired.
275
-
276
- Calculated Midnight: The Mawaqit midnight.
277
- Traditional Midnight: Isha time + 1 minute
278
-
279
- Update logic for prayer times:
280
-
281
- If the Calculated Midnight is before the traditional midnight then wait
282
- until the traditional midnight to run the update. This way the day
283
- will have changed over and we don't need to do any fancy calculations.
284
-
285
- If the Calculated Midnight is after the traditional midnight, then wait
286
- until after the calculated Midnight. We don't want to update the prayer
287
- times too early or else the timings might be incorrect.
288
-
289
- Example:
290
- calculated midnight = 11:23PM (before traditional midnight)
291
- Update time: 12:00AM
292
-
293
- calculated midnight = 1:35AM (after traditional midnight)
294
- update time: 1:36AM.
295
-
296
- """
297
- _LOGGER .debug ("Scheduling next update for Mawaqit prayer times" )
298
-
299
- now = dt_util .utcnow ()
300
- now = dt_util .now ()
301
-
302
- midnight_dt = self .prayer_times_info ["Next Salat Time" ]
303
- Fajr_dt = self .prayer_times_info ["Fajr" ]
304
- Dhuhr_dt = self .prayer_times_info ["Dhuhr" ]
305
- Asr_dt = self .prayer_times_info ["Asr" ]
306
- Maghrib_dt = self .prayer_times_info ["Maghrib" ]
307
- Isha_dt = self .prayer_times_info ["Isha" ]
308
-
309
- prayer_times = [Fajr_dt , Dhuhr_dt , Asr_dt , Maghrib_dt , Isha_dt ]
310
-
311
- midnight_dt = min (prayer_times )
290
+ maghrib_hour = self .prayer_times_info ['Maghrib' ]
291
+ maghrib_hour = maghrib_hour .strftime ("%H:%M" )
292
+
293
+ # isha + 1 minute because this function is launched 1 minute after 'Isha, (useful only if 'Isha is at 11:59 PM)
294
+ isha_hour = self .prayer_times_info ['Isha' ] + timedelta (minutes = 1 )
295
+ isha_hour = isha_hour .strftime ("%H:%M" )
296
+
297
+ # If 'Isha is before 12 AM (Maghrib hour < 'Isha hour), we need to get the next day's Fajr.
298
+ # Else, we get the current day's Fajr.
299
+ if maghrib_hour < isha_hour :
300
+ index_day = today .day + 1
301
+ else :
302
+ index_day = today .day
303
+
304
+ try :
305
+ day_times = month_times [str (index_day )]
306
+ except KeyError :
307
+ # If index_day + 1 == 32 (or 31) and the month contains only 31 (or 30) days
308
+ # We take the first day of the following month (reset 0 if we're in december)
309
+ if index_month == 11 :
310
+ index_next_month = 0
311
+ else :
312
+ index_next_month = index_month + 1
313
+ day_times = calendar [index_next_month ]["1" ]
314
+ fajr_hour = day_times [0 ]
312
315
313
- if now > dt_util .as_utc (midnight_dt ):
314
- next_update_at = midnight_dt + timedelta (days = 0 , minutes = 1 , seconds = 0 )
315
- _LOGGER .debug (
316
- "Midnight is after day the changes so schedule update for after Midnight the next day"
317
- )
318
- else :
319
- _LOGGER .debug (
320
- "Midnight is before the day changes so schedule update for the next start of day"
321
- )
322
- next_update_at = dt_util .start_of_local_day (now + timedelta (days = 1 ))
323
- next_update_at = midnight_dt + timedelta (days = 0 , minutes = 1 )
316
+ self .prayer_times_info ['Next Salat Name' ] = "Fajr"
317
+ self .prayer_times_info ['Next Salat Time' ] = dt_util .parse_datetime (f"{ today .year } -{ today .month } -{ index_day } { fajr_hour } :00" )
324
318
325
- _LOGGER .info ("Next update scheduled for: %s" , next_update_at )
319
+ countdown_next_prayer = 15
320
+ self .prayer_times_info ['Next Salat Preparation' ] = self .prayer_times_info ['Next Salat Time' ] - timedelta (minutes = countdown_next_prayer )
326
321
327
- self .event_unsub = async_track_point_in_time (
328
- self .hass , self .async_update , next_update_at
329
- )
322
+ _LOGGER .debug ("Next salat info updated, updating sensors" )
323
+ async_dispatcher_send (self .hass , DATA_UPDATED )
330
324
331
325
async def async_update (self , * _ ):
332
326
"""Update sensors with new prayer times."""
@@ -366,9 +360,16 @@ async def async_update(self, *_):
366
360
)
367
361
else :
368
362
self .prayer_times_info [prayer ] = time
369
-
370
-
371
- await self .async_schedule_future_update ()
363
+
364
+ # We schedule updates for next_salat_time and next_salat_name at each prayer time + 1 minute.
365
+ prayers = ["Fajr" , "Dhuhr" , "Asr" , "Maghrib" , "Isha" ]
366
+ prayer_times = [self .prayer_times_info [prayer ] for prayer in prayers ]
367
+
368
+ for prayer in prayer_times :
369
+ next_update_at = prayer + timedelta (minutes = 1 )
370
+ async_track_point_in_time (
371
+ self .hass , self .async_update_next_salat_sensor , next_update_at
372
+ )
372
373
373
374
_LOGGER .debug ("New prayer times retrieved. Updating sensors." )
374
375
async_dispatcher_send (self .hass , DATA_UPDATED )
@@ -386,6 +387,10 @@ async def async_setup(self):
386
387
await self .async_update ()
387
388
self .config_entry .add_update_listener (self .async_options_updated )
388
389
390
+ # We update time prayers every day.
391
+ h , m , s = UPDATE_TIME
392
+ async_track_time_change (self .hass , self .async_update , hour = h , minute = m , second = s )
393
+
389
394
return True
390
395
391
396
async def async_add_options (self ):
@@ -404,3 +409,4 @@ async def async_options_updated(hass, entry):
404
409
if hass .data [DOMAIN ].event_unsub :
405
410
hass .data [DOMAIN ].event_unsub ()
406
411
await hass .data [DOMAIN ].async_update ()
412
+
0 commit comments