Skip to content

Commit d1920c2

Browse files
Merge pull request #40 from mawaqit/issue-36-jumua-sensor
Issue #36 - Added Jumu'a sensors
2 parents 4578dfb + 58cecf0 commit d1920c2

File tree

4 files changed

+153
-116
lines changed

4 files changed

+153
-116
lines changed

custom_components/mawaqit/__init__.py

Lines changed: 126 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
"""The mawaqit_prayer_times component."""
2-
from datetime import timedelta
32
import logging
43
import os
54
import json
6-
import sys
5+
# import sys
76
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
1112

1213
from requests.exceptions import ConnectionError as ConnError
14+
1315
import voluptuous as vol
1416

1517
from homeassistant.config_entries import SOURCE_IMPORT
@@ -18,9 +20,7 @@
1820
from homeassistant.helpers.dispatcher import async_dispatcher_send
1921
from homeassistant.helpers.event import async_call_later, async_track_point_in_time
2022
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
2424

2525

2626
from .const import (
@@ -38,13 +38,13 @@
3838
CALC_METHODS,
3939
)
4040

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
4342

4443
_LOGGER = logging.getLogger(__name__)
4544

4645
PLATFORMS = ["sensor"]
4746

47+
4848
CONFIG_SCHEMA = vol.Schema(
4949
vol.All(
5050
cv.deprecated(DOMAIN),
@@ -59,12 +59,14 @@
5959
extra=vol.ALLOW_EXTRA,
6060
)
6161

62+
6263
def is_date_parsing(date_str):
6364
try:
6465
return bool(date_parser.parse(date_str))
6566
except ValueError:
6667
return False
67-
68+
69+
6870
async def async_setup(hass, config):
6971
"""Import the Mawaqit Prayer component from config."""
7072
if DOMAIN in config:
@@ -73,7 +75,6 @@ async def async_setup(hass, config):
7375
DOMAIN, context={"source": SOURCE_IMPORT}, data=config[DOMAIN]
7476
)
7577
)
76-
7778
return True
7879

7980

@@ -91,8 +92,6 @@ async def async_setup_entry(hass, config_entry):
9192
return True
9293

9394

94-
95-
9695
async def async_unload_entry(hass, config_entry):
9796
"""Unload Mawaqit Prayer entry from config_entry."""
9897
current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -108,10 +107,10 @@ async def async_unload_entry(hass, config_entry):
108107
except OSError as e:
109108
print("Error: %s : %s" % (dir_path, e.strerror))
110109

111-
112110
if hass.data[DOMAIN].event_unsub:
113111
hass.data[DOMAIN].event_unsub()
114112
hass.data.pop(DOMAIN)
113+
115114
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)
116115

117116

@@ -127,124 +126,143 @@ def __init__(self, hass, config_entry):
127126
self.event_unsub = None
128127

129128

130-
131129
@property
132130
def calc_method(self):
133131
"""Return the calculation method."""
134132
return self.config_entry.options[CONF_CALC_METHOD]
135133

134+
136135
def get_new_prayer_times(self):
137136
"""Fetch prayer times for today."""
138137
mawaqit_login = self.config_entry.data.get("username")
139138
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")
147141

142+
mosque = self.config_entry.options.get("calculation_method")
148143

149144
current_dir = os.path.dirname(os.path.realpath(__file__))
150145

151-
152-
153-
154-
155146
name_servers=[]
156147
uuid_servers=[]
157148
CALC_METHODS=[]
149+
158150
with open('{}/data/all_mosquee_NN.txt'.format(current_dir), "r") as f:
159151
distros_dict = json.load(f)
152+
160153
for distro in distros_dict:
161154
name_servers.extend([distro["label"]])
162155
uuid_servers.extend([distro["uuid"]])
163156
CALC_METHODS.extend([distro["label"]])
164157

165-
166-
167-
168-
if mosquee=="nearest" or mosquee=="no mosque in neighborhood" :
158+
if mosque == "nearest" or mosque == "no mosque in neighborhood":
169159
indice = 0
170160
else:
171-
indice = name_servers.index(mosquee)
172-
mosque_id = uuid_servers[indice]
161+
indice = name_servers.index(mosque)
173162

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]
182164

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+
185168
data = json.load(f)
186169
calendar = data["calendar"]
170+
171+
# Then, we get the prayer times of the day into this file
187172
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+
190176
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"]
194188

195-
maintenant = today.time().strftime("%H:%M")
189+
now = today.time().strftime("%H:%M")
196190

191+
today = datetime.today().strftime("%Y-%m-%d")
192+
tomorrow = (datetime.today() + timedelta(days=1)).strftime("%Y-%m-%d")
197193

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
209198
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"
212201
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+
220234
res['Mosque_label']=data["label"]
221235
res['Mosque_localisation']=data["localisation"]
222-
res['Mosque_url']=data["url"]
236+
res['Mosque_url']=data["url"]
223237
res['Mosque_image']=data["image"]
224238

225-
#Iqama timing
239+
# The Iqama countdown from Adhan is stored in pray_time.txt as well.
226240
iqamaCalendar = data["iqamaCalendar"]
227-
iqama= iqamaCalendar[index_month][str(index_day)]
241+
iqamas = iqamaCalendar[index_month][str(index_day)] # Today's iqama times.
228242
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]
230246
except ValueError:
231-
iqama = [0,0,0,0,0]
247+
iqamas = [0, 0, 0, 0, 0]
232248

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.
242252

243-
244-
253+
# We store the iqama times of the day in HH:MM format.
254+
iqama_times = []
245255

246-
256+
for (prayer, iqama) in zip(prayers, iqamas):
257+
iqama_times.append((prayer + timedelta(minutes=iqama)).strftime("%H:%M"))
247258

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
248266

249267

250268
async def async_schedule_future_update(self):
@@ -284,20 +302,13 @@ async def async_schedule_future_update(self):
284302
midnight_dt = self.prayer_times_info["Next Salat Time"]
285303
Fajr_dt = self.prayer_times_info["Fajr"]
286304
Dhuhr_dt = self.prayer_times_info["Dhuhr"]
287-
#Shurouq_dt = self.prayer_times_info["Shurouq"]
288305
Asr_dt = self.prayer_times_info["Asr"]
289306
Maghrib_dt = self.prayer_times_info["Maghrib"]
290307
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-
300308

309+
prayer_times = [Fajr_dt, Dhuhr_dt, Asr_dt, Maghrib_dt, Isha_dt]
310+
311+
midnight_dt = min(prayer_times)
301312

302313
if now > dt_util.as_utc(midnight_dt):
303314
next_update_at = midnight_dt + timedelta(days=0, minutes=1, seconds=0)
@@ -331,14 +342,25 @@ async def async_update(self, *_):
331342
return
332343

333344
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+
337351
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
340354
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")
342364
self.prayer_times_info[prayer] = dt_util.parse_datetime(
343365
f"{pray} {time}"
344366
)
@@ -348,19 +370,19 @@ async def async_update(self, *_):
348370

349371
await self.async_schedule_future_update()
350372

351-
_LOGGER.debug("New prayer times retrieved. Updating sensors")
373+
_LOGGER.debug("New prayer times retrieved. Updating sensors.")
352374
async_dispatcher_send(self.hass, DATA_UPDATED)
353375

354376
async def async_setup(self):
355377
"""Set up the Mawaqit prayer client."""
378+
356379
await self.async_add_options()
357380

358381
try:
359382
await self.hass.async_add_executor_job(self.get_new_prayer_times)
360383
except (BadCredentialsException, ConnError) as err:
361384
raise ConfigEntryNotReady from err
362385

363-
364386
await self.async_update()
365387
self.config_entry.add_update_listener(self.async_options_updated)
366388

custom_components/mawaqit/const.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
"Asr": "Adhan",
1212
"Maghrib": "Adhan",
1313
"Isha": "Adhan",
14+
"Jumua": "Adhan",
15+
"Jumua 2": "Adhan",
16+
#"Aid": "Adhan",
17+
#"Aid 2": "Adhan",
1418
"next_mawaqit": "time",
1519
"Fajr Iqama": "",
1620
"Dhuhr Iqama": "",

0 commit comments

Comments
 (0)