Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,17 @@ that explains its license.

----
<!-- /!\ Non OCA Context : Set here the full description of your organization. -->


## Keycloak

To integrate Keycloak as a OAuth provider in Odoo, you need to install the following OCA module:
<br/>
[auth_oidc](https://github.com/OCA/server-auth/tree/18.0/auth_oidc)


## Multi Session Odoo

If you wish to enable multiple connections for the same account with an OAuth provider in Odoo, you'll need to install this OCA module:
<br/>
[auth_oauth_multi_token](https://github.com/OCA/server-auth/tree/18.0/auth_oauth_multi_token)
4 changes: 2 additions & 2 deletions openems/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "OpenEMS",
"summary": "Everything related to OpenEMS (Open Energy Management System)",
"version": "16.0.1.0.1",
"version": "18.0.1.0.1",
"author": "OpenEMS Association e.V.",
"maintainer": "OpenEMS Association e.V.",
"contributors": [
Expand All @@ -11,7 +11,7 @@
"website": "https://openems.io",
"license": "AGPL-3",
"category": "Specific Industry Applications",
"depends": ["base", "web", "mail", "crm", "resource", "stock", "web_m2x_options", "partner_firstname"],
"depends": ["base", "web", "mail", "crm", "resource", "stock", "web_m2x_options", "partner_firstname","auth_oauth"],
"data": [
"data/ir_config_parameter.xml",
"data/res_partner_category.xml",
Expand Down
72 changes: 54 additions & 18 deletions openems/controllers/alerting.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,60 @@ class SumState(Enum):
class Message:
sentAt: datetime
edgeId: str
userIds: list[int]
userLogins: list[str]

def __init__(self, sentAt: datetime, edgeId: str, userIds: list[int]) -> None:
def __init__(self, sentAt: datetime, edgeId: str, userLogins : list[str]) -> None:
self.sentAt = sentAt
self.edgeId = edgeId
self.userIds = userIds
self.userLogins = userLogins

class SumStateMessage(Message):
state: SumState

def __init__(self, sentAt: datetime, edgeId: str, userIds: list[int], state: SumState) -> None:
super().__init__(sentAt, edgeId, userIds)
def __init__(self, sentAt: datetime, edgeId: str, userLogins: list[str], state: SumState) -> None:
super().__init__(sentAt, edgeId, userLogins)
self.state = state

class Alerting(http.Controller):
__logger = logging.getLogger("Alerting")
__datetime_format = "%Y-%m-%d %H:%M:%S"

@http.route("/openems_backend/mail/alerting_sum_state", type="json", auth="user")
def sum_state_alerting(self, sentAt: str, params: list[dict]):
def sum_state_alerting(self, sentAt: str, params: list[dict]) -> dict:
msgs = self.__get_sum_state_params(sentAt, params)
update_func = lambda role, at: { role.write({"sum_state_last_notification": at})}

if len(msgs) == 0:
self.__logger.error("Scheduled SumState-Alerting-Mail without any recipients!!!")
return {"status": "error", "message": "No recipients for sum state alerting"}

template = request.env.ref('openems.alerting_sum_state')
mails_sent = 0
for msg in msgs:
self.__send_mails(template, msg, update_func)
mails_sent += self.__send_mails(template, msg, update_func)

return {}
return {"status": "success", "mails_sent": mails_sent}

@http.route("/openems_backend/mail/alerting_offline", type="json", auth="user")
def offline_alerting(self, sentAt: str, params: list[dict]):
def offline_alerting(self, sentAt: str, params: list[dict]) -> dict:
msgs = self.__get_offline_params(sentAt, params)
update_func = lambda role, at: { role.write({"offline_last_notification": at})}

template = request.env.ref("openems.alerting_offline")
if len(msgs) == 0:
self.__logger.error("Scheduled Offline-Alerting-Mail without any recipients!!!")
return {"status": "error", "message": "No recipients for offline alerting"}

mails_sent = 0

for msg in msgs:
self.__send_mails(template, msg, update_func)
template = self.__get_template(msg.edgeId)
mails_sent += self.__send_mails(template, msg, update_func)

return {}
return {"status": "success", "mails_sent": mails_sent}

def __get_offline_params(self, sentAt, params) -> list[Message]:
msgs = list()
sent = datetime.strptime(sentAt, "%Y-%m-%d %H:%M:%S")
sent = datetime.strptime(sentAt, self.__datetime_format)
for param in params:
edgeId = param["edgeId"]
recipients = param["recipients"]
Expand All @@ -65,22 +74,49 @@ def __get_offline_params(self, sentAt, params) -> list[Message]:

def __get_sum_state_params(self, sentAt, params) -> list[SumStateMessage]:
msgs = list()
sent = datetime.strptime(sentAt, "%Y-%m-%d %H:%M:%S")
sent = datetime.strptime(sentAt, self.__datetime_format)
for param in params:
edgeId = param["edgeId"]
recipients = param["recipients"]
state = param["state"]
msgs.append(SumStateMessage(sent, edgeId, recipients, state));
return msgs

def __get_template(self, device_id):
oem, producttype = self.__get_device_data_for(device_id)
match (oem.casefold(), producttype.casefold()):
case ('openems', _):
return request.env.ref("openems.alerting_offline")

def __send_mails(self, template, msg: Message, update_func):
def __get_device_data_for(self, device_id) -> tuple[str, str]:
if device_id:
found_devices = http.request.env["openems.device"].search_read(
[("name", "=", device_id)], ["producttype", "oem"]
)
if len(found_devices) == 1:
device = found_devices[0]
oem = device.get('oem') or 'openems'
producttype = device.get('producttype') or 'other'
return oem, producttype

self.__logger.warning(f"no device with id '{device_id}' found, using fallback [oem=openems, producttype=other]")
return 'openems', 'other'

def __send_mails(self, template, msg: Message, update_func) -> int:
roles = http.request.env['openems.alerting'].search(
[('user_id','in',msg.userIds),('device_id','=',msg.edgeId)]
[('user_login','in', msg.userLogins),('device_id','=', msg.edgeId)]
)

if not roles or len(roles) == 0:
self.__logger.error(f"No AlertingSettings found for edgeId[{msg.edgeId}] and userLogins[{msg.userLogins}]!!!")
return 0

mails_sent = 0
for role in roles:
try:
template.send_mail(res_id=role.id, force_send=True)
template.send_mail(res_id=role.id)
update_func(role, msg.sentAt)
mails_sent += 1
except Exception as err:
self.__logger.error("[" + str(err) + "] Unable to send template[" + str(template.name) +"] to edgeUser[user=" + str(role.id) + ", edge=" + str(msg.edgeId)+ "]")
self.__logger.error(f"[{err}] Unable to send template[{template.name}] to edgeUser[user={role.id}, edge={msg.edgeId}]")
return mails_sent
Loading