rainepretorius / olarm-ha-integration

Integration for Olarm devices created by a BSC(Computer Science and Mathematics) student.
https://raine.pretoriusse.net
BSD 2-Clause "Simplified" License
30 stars 13 forks source link

Index out of range exception with Paradox MG5050 #2

Closed NeilDuToit92 closed 1 year ago

NeilDuToit92 commented 1 year ago

I am getting the following error in my logs:

File "/config/custom_components/olarm_sensors/olarm_api.py", line 189, in get_panel_states
if olarm_state["areas"][1] == "arm":
IndexError: list index out of range
During handling of the above exception, another exception occurred:
Traceback (most recent call last):

Looking at the code, it checks if ["areasLimit"] == 2 on line 188 From my payload, I can see it is 2, so this block should enter:

...
"deviceProfile": {
"ver": 2,
"areasLimit": 2,
...

Looking further into olarm_state - line 118:

olarm_state = olarm_json["deviceState"]

However, my deviceState.areas only has 1 entry:

"deviceState": {
  "timestamp": 1679142913373,
  "cmdRecv": 0,
  "type": "",
  "areas": [
    "arm"
  ],
  "areasDetail": [
    ""
  ],
  "areasStamp": [
    1677415091976
  ],

I know that the MG5050 supports 2 areas, but I am only using 1 of the 2. Olarm might be reporting the number of areas supported by the connected alarm, even if they are not utilised. I also have a EVO192 that supports 8 areas, but unfortunately it doesn't have an Olarm yet, so I can't check if that number pulls through as an 8.

Here is my full payload Olarm Payload.txt

rainepretorius commented 1 year ago

Hi Neil, Thanks for reaching out. I will have a look at this issue promptly. If I just quickly glance over it, it looks likeolarm is reporting that you have 2 zones on your alarm, but only one active. Thus the index error happens as Olarm is reporting that you have two areas, but they only send data back for one. I will see if I can implement a workaround for this issue.

NeilDuToit92 commented 1 year ago

Thanks @rainepretorius, I assume you wrote this around your setup, hence the 'indoor' and 'outdoor' name used for your variables?

Can I maybe suggest instead of doing areas[0] and areas[1], rather just iterate for the value of areasLimit. I don't know the ins and outs of how HA plugins work, and I don't know Python all that well either, but presumably something along these lines should work?

    async def get_panel_states(self):
        try:
            async with aiohttp.ClientSession() as session:
                async with session.get(
                        f"https://apiv4.olarm.co/api/v4/devices/{self.device_id}",
                        headers=self.headers,
                ) as response:
                    olarm_json = await response.json()
                    olarm_state = olarm_json["deviceState"]
                    zones = olarm_json["deviceProfile"]
                    olarm_zones = zones["areasLabels"]

                    self.panel_data = []

                    area_count = zones["areasLimit"]
                    for area_num in range(area_count):
                        try:
                            arm = "off"
                            sleep = "off"
                            stay = "off"
                            disarm = "off"
                            alarm = "off"
                            countdown = "off"

                            if olarm_zones[area_num] == "":
                                _APILOGGER.info(
                                    "This device's area names have not been set up in Olarm, generating automatically."
                                )
                                olarm_zones[area_num] = "Area 1"

                            if olarm_state["areas"][area_num] == "arm":
                                arm = "on"

                            elif olarm_state["areas"][area_num] == "sleep":
                                sleep = "on"

                            elif olarm_state["areas"][area_num] == "stay":
                                stay = "on"

                            elif (
                                    olarm_state["areas"][area_num] == "disarm"
                                    or olarm_state["areas"][area_num] == "notready"
                            ):
                                disarm = "on"

                            elif olarm_state["areas"][area_num] == "alarm":
                                alarm = "on"

                            elif olarm_state["areas"][area_num] == "countdown":
                                countdown = "on"

                            self.panel_data.extend(
                                [
                                    {"name": f"{olarm_zones[area_num]} Armed", "state": arm},
                                    {"name": f"{olarm_zones[area_num]} Sleep", "state": sleep},
                                    {"name": f"{olarm_zones[area_num]} Stay", "state": stay},
                                    {"name": f"{olarm_zones[area_num]} Disarmed", "state": disarm},
                                    {"name": f"{olarm_zones[area_num]} Countdown", "state": countdown},
                                    {"name": f"{olarm_zones[area_num]} Alarm", "state": alarm}
                                ]
                            )

                        except Exception as e:
                            _APILOGGER.error(str(e))

                    return self.panel_data

        except aiohttp.web_exceptions.Any as ex:
            _APILOGGER.error(f"Olarm API Panel error:\n{ex}")
            return self.panel_data

Edit: Init disarm to off

rainepretorius commented 1 year ago

Will check it out. This method looks a lot cleaner. Thanks for the great suggestion.