home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
69.74k stars 28.91k forks source link

0.115 RISCO integration risco panel does not appear on the lovelace alarm panel card entity list #40290

Closed karlismaj closed 3 years ago

karlismaj commented 3 years ago

The problem

Cannot select Risco alarm as an entity when adding lovelace card. The entity is simply missing there. I've even done a fresh installation of HA with only Risco integration just to be sure that this is not related to any custom config. I have successfully connected my risco account. The app recognizes all my zones. I have following sensors available along with my zone sensors (replaced real numbers with XXX): sensor.risco_0000000XXXXX_alarm_events sensor.risco_0000000XXXXX_other_events sensor.risco_0000000XXXXX_status_events sensor.risco_0000000XXXXX_trouble_events

Environment

Problem-relevant configuration.yaml

Clean configuration.yaml because of clean fresh installation of HA

Traceback/Error logs

Additional information

karlismaj commented 5 months ago

Hello. Was not using HA for some time bur recently installed and have the same issues with Risco. Does anyone if things has changes since last time this was discussed? 2-3 years have passed.

OnFreund commented 5 months ago

@karlismaj the integration has changed quite a lot, and now support both a cloud version and a local version. Non-partitioned systems are still not supported though.

karlismaj commented 5 months ago

Hi and thanks for quick reply. Ive noticed changes. What does "partitioned" mean? I think I have only one. I have one zone with several detectors. I can omit and unomit zones from HA. In HA I can also see events like arming and disarming from the device itself (not HA). But I cannot get it armed/disarmed. Getting the same error as in my initial request in 2021. Maybe someone from the community can guide me how to troubleshoot and solve this together?

In config file I have basic records for alarm panel:

alarm_control_panel: -platform: manual name: Home-Alarm code: 'xxxx' code_arm_required: false

Thanks in advance.

karlismaj commented 5 months ago

@OnFreund in the past you've suggested me to look into communication log using Charles proxy. Do you think this is still valid thing to do? If I'm getting states of sensors, it seems that connectivity is working. Maybe there is a config issue in HA?

karlismaj commented 5 months ago

I've tried to sniff the traffic using mitmproxy tool on Windows PC but it seems that Risco is good on protecting the traffic as the web page recognizes that SSL certificate does not match Risco's and i cannot access the page. Getting error that my connection is not private. @OnFreund, have you tried Charles proxy yourself on Riscocloud? Did it work?

OnFreund commented 5 months ago

in the past you've suggested me to look into communication log using Charles proxy. Do you think this is still valid thing to do?

Yes, that could help, but I want to set the expectations straight - I don't know if I'll have time to look at it, if I will I won't necessarily be able to make sense of it, and even if I do, I won't necessarily be able to turn it into a functioning integration.

If I'm getting states of sensors, it seems that connectivity is working. Maybe there is a config issue in HA?

It's not - it's because your system doesn't have partitions and is using a different API. We discussed this in the past.

it seems that Risco is good on protecting the traffic as the web page recognizes that SSL certificate does not match Risco's and i cannot access the page.

Highly unlikely Risco is doing any such thing. It's most likely your browser, which means you haven't set up the certificate needed to get mitmproxy to work. However, your browser will most likely still have some way to visit the site anyway.

karlismaj commented 5 months ago

Can you see the entity in Dev Tools -> States?

Just to reply to past request. I have following in the states: code_format: null changed_by: null code_arm_required: false friendly_name: Home_Alarm supported_features: 63

If i change state to arm_away or arm_home, i'm getting notification that it is armed but actual arming does not happen.

karlismaj commented 5 months ago

I've installed the mitm certificate as per instruction but it did not help. I'll investigate this further.

OnFreund commented 5 months ago

In the past you mentioned you don't have an alarm entity. You do see one now? Other than arming not working, does the entity accurately reflect the state? (e.g. if you arm from the panel or app, does the state of the entity change accordingly?)

karlismaj commented 5 months ago

i see the alarm entity and the panel but the state does not reflect actual state. Managed to catch the traffic. What type of traffic i need to send. there is a lot of it.

OnFreund commented 5 months ago

What about logs? Are you still getting that error? A different one?

What type of traffic i need to send.

First step would be to figure out the command and response to get the alarm status...

karlismaj commented 5 months ago

The logs looks the same as 4 years ago: ERROR (MainThread) [homeassistant.components.alarm_control_panel] Error while setting up risco platform for alarm_control_panel Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 360, in _async_setup_platform await asyncio.shield(task) File "/usr/src/homeassistant/homeassistant/components/risco/alarm_control_panel.py", line 83, in async_setup_entry for partition_id in coordinator.data.partitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pyrisco/cloud/alarm.py", line 18, in partitions self._partitions = {p["id"]: Partition(self._api, p) for p in self._raw["partitions"]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: 'NoneType' object is not iterable

karlismaj commented 5 months ago

Here is the traffic info for the state of alarm. I've removed some elements of Cookies. Not sure if there is some security risk sending those.

Path

https://www.riscocloud.com/elas/webui/Security/GetCPState

Request

POST https://www.riscocloud.com/elas/webui/Security/GetCPState HTTP/2.0 content-length: 0 sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120" accept: / x-requested-with: XMLHttpRequest sec-ch-ua-mobile: ?0 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0 sec-ch-ua-platform: "Windows" origin: https://www.riscocloud.com sec-fetch-site: same-origin sec-fetch-mode: cors sec-fetch-dest: empty referer: https://www.riscocloud.com/elas/webui/MainPage/MainPage accept-encoding: gzip, deflate, br accept-language: lv,en;q=0.9,en-US;q=0.8,ru;q=0.7 cookie: .AspNetCore.Antiforgery.VyLW6ORzMgk=CfL9Jc9edlvS1Pp6_XjvsMdLP9RmQgDHh2ztCQ80m1FVb3dx7RJ2-KYZKKz1L6FPz2P84Az_UjPwdsRnKXDeMo17eD27iiWEznsM cookie: _gid=GA1.2.1792191185.1704649034 cookie: riscoGdpr=agree cookie: .WebUI.LangId=c%3Den-GB%7Cuic%3Den-GB cookie: _clck=1cn26zt%7C2%7Cfi7%7C0%7C1467 cookie: CONFIRM_COOKIES_USAGE=true cookie: _clsk=x56rx9%7C1704649352878%7C2%7C1%7Cs.clarity.ms%2Fcollect cookie: _ga_Y53121XMZC=GS1.1.1704649342.1.0.1704649355.0.0.0 cookie: _gat_gtag_UA_111781723_10=1 cookie: RUCCookie=c2ewBesVZpTUSCdzgkW0a%2FnXcA4gcUkw%3D cookie: .AspNetCore.Session=CfDJ8FvGvwqVfdWHlKg0WcKMZKCL9MfCXaLHnzCjD8Vj2tlZZOUl8p5xfLNvt0ZfrdNizydVFslOkX5Ketpu6F1cmDFG1NLLXs0s0Gzzl90DGowhTQc3Ea%2FkcVTkMyxY8%2B1Z cookie: _ga=GA1.1.1823835030.1704649034 cookie: _ga_JKBC4BKHP8=GS1.1.1704649033.1.1.1704653906.0.0.0

Response

{ "ExitDelayTimeout": [ 0 ], "FullArmString": "Set ", "HideDisarmOption": true, "IsOffline": false, "MemoryAlarm": true, "OfflineSince": "N/A", "OngoingAlarm": false, "PartArmFailures": null, "PartArmString": "Partial ", "ShowRearmButton": false, "allGrpState": null, "detectors": null, "eh": null, "error": 0, "haSwitch": null, "overview": null, "strResult": null, "unix_time": 1704653917.4844775 }

karlismaj commented 5 months ago

Does it make sense?

OnFreund commented 5 months ago

Is there a request to a url that ends with ControlPanel/GetState?

As for the entity - given that log, it's not supposed to be created. Maybe it belongs to a different integration.

karlismaj commented 5 months ago

Nope, no url ending ControlPanel/GetState

Only: https://www.riscocloud.com/elas/webui/Security/GetCPState https://www.riscocloud.com/elas/webui/Security/ArmDisarm

karlismaj commented 5 months ago

I've disabled all other integrations and still getting same error in log. Do you know what line i should add for logger in config to have a debug logging? Currently i have this but seems not to be correct: logger: alarm_control_panel.home_alarm: debug

OnFreund commented 5 months ago

I've disabled all other integrations and still getting same error in log.

Of course, the log is coming from the Risco integration. It's the entity that I'm not sure about.

Can you add outputs of GetCPState with different states? (e.g. disarmed, fully armed, partially armed, group armed if your alarm supports it)

karlismaj commented 5 months ago

Ok, i've sniffed iPhone traffic used the Risco app and i see url https://www.riscocloud.com/webapi/api/wuws/site/XXXXX/ControlPanel/GetState

The response is very long and some devices are repeating therefore i've shortened it, e.g. removed some similar devices from list. And also replaced real names with XXX

{
    "errorText": null,
    "errorTextCodeID": "0",
    "response": {
        "classVersion": 0,
        "cpid": "000000xxx",
        "id": xxxx,
        "state": {
            "classVersion": 0,
            "cpDescEncName": "windows-1252",
            "features": null,
            "isOnline": true,
            "lastConnectedTime": "2024-01-08T18:46:12.4179229Z",
            "lastEvReported": "2024-01-08T18:16:55.4126703Z",
            "lastLogUpdate": "2024-01-08T18:17:22.52Z",
            "lastStatusUpdate": "2024-01-08T18:46:12.4147854Z",
            "media": 1,
            "status": {
                "acLost": false,
                "alarmPending": false,
                "armNotAllowed": false,
                "batteryLow": false,
                "bellOn": false,
                "bellStatus": 0,
                "classVersion": 0,
                "cpTime": "2024-01-08T20:43:48",
                "devCollection": [
                    {
                        "devList": [
                            {
                                "desc": "KEYFOB #1",
                                "extra": "0C|13E9600F",
                                "num": 0
                            }
                         ],
                        "devType": 15
                    },
                    {
                        "devList": [
                            {
                                "desc": "",
                                "extra": "0C|1FFFFFFFF",
                                "num": 0
                            }
                        ],
                        "devType": 17
                    },
                    {
                        "devList": [
                            {
                                "desc": "KEYPAD #1",
                                "extra": "14303468",
                                "num": 0
                            }
                        ],
                        "devType": 19
                    },
                    {
                        "devList": [
                            {
                                "desc": "REPEATER 1",
                                "extra": null,
                                "num": 0
                            }
                        ],
                        "devType": 20
                    },
                    {
                        "devList": [],
                        "devType": 21
                    }
                ],
                "disarmNotAllowed": false,
                "exitDelayTimeout": 0,
                "haDevices": [],
                "haEnabled": true,
                "part1Ready": false,
                "part2Ready": false,
                "partFullReady": false,
                "partReadySupported": false,
                "partitions": null,
                "systemReady": true,
                "systemStatus": 0,
                "trouble": true,
                "type": 1,
                "users": [
                    {
                        "part": 0,
                        "partAssocMask": null,
                        "passCode": "XXX",
                        "userID": 0,
                        "userName": "XXXX",
                        "userType": 0
                    }
                ],
                "zones": [
                    {
                        "part": 7,
                        "partAssocMask": null,
                        "pirCam": null,
                        "presenceMuted": 2,
                        "regDevSN": "XXXXX",
                        "status": 0,
                        "trouble": false,
                        "zoneID": 0,
                        "zoneName": "XXXX",
                        "zoneType": 2
                    },
                    {
                        "part": 3,
                        "partAssocMask": null,
                        "pirCam": null,
                        "presenceMuted": 2,
                        "regDevSN": "XXXXX",
                        "status": 0,
                        "trouble": false,
                        "zoneID": 1,
                        "zoneName": "XXXXX",
                        "zoneType": 3
                    }
                ]
            },
            "type": 1
        }
    },
    "result": 0,
    "status": 200,
    "validationErrors": null
}
OnFreund commented 5 months ago

Can you share outputs with different states? (e.g. disarmed, fully armed, partially armed, group armed if your alarm supports it)

karlismaj commented 5 months ago

These are requests from links: https://www.riscocloud.com/webapi/api/wuws/site/*xxxxx*/ControlPanel/Arm

I have not armed full because it is live alarm and will trigger a lot of noise. But if you see a light at the end of the tunnel, I'll do that.

Arm partial

{ "newSystemStatus": 2, "sessionToken": "xxx" }

Disarm

{ "newSystemStatus": 0, "sessionToken": "xxx" }

Arm perimeter

{ "newSystemStatus": 4, "sessionToken": "xxx" }

Disarm

{ "newSystemStatus": 0, "sessionToken": "xxx" }

The response on requests is exactly the same as in the reply above https://github.com/home-assistant/core/issues/40290#issuecomment-1881661306

The only diference between the states is in this row: "systemStatus": 0 the number changes to match "newSystemStatus" from request.

karlismaj commented 5 months ago

Hi, @OnFreund Do you think you can solve this? Anything else is needed from API data?

OnFreund commented 5 months ago

So far this is helpful, but I didn't have the capacity to dig into it yet. Next step - can you capture the commands for arming in various arming modes and disarming?

OnFreund commented 5 months ago

Oh wait, you answered that already

OnFreund commented 5 months ago

OK, so two more things:

  1. We need to get the status when the alarm is triggered (tricky, I know)
  2. Does the exitDelayTimeout value change when you arm from the panel and you have a countdown?
karlismaj commented 5 months ago
  1. i have a countdown in the panel which is different than 0 in the "exitDelayTimeout" field. I do not get any countdown in app either.

  2. I do not get anything specific event in API when alarm is triggered. It seems that only thing with some signs of alarm is this link: https://www.riscocloud.com/webapi/api/wuws/site/XXXXXX/ControlPanel/GetEventLog

It consist of some number of past events including the alarm. Seems that "eventDescriptorHint": "%UW" unset using mobile app or web "%Z" - alarm triggered "%U" - unset using panel "" - alarming using panel

Response is: { "errorText": null, "errorTextCodeID": "0", "response": { "controlPanelEventsList": [ { "eventDescriptorHint": "%UW", "eventId": 70, "eventName": "Open After Alarm - 'USERNAME' WEB", "eventText": "", "group": 2, "groupName": "Alarms", "lineNumber": 1, "logTime": "2024-01-22T19:15:02", "msd": null, "partAssociationCSV": null, "priority": 2, "reportStatus": 131, "sourceID": 1, "sourceName": "User", "sourceType": 2, "viUID": null }, { "eventDescriptorHint": "%Z", "eventId": 3, "eventName": "Alarm - 'ZONENAME'", "eventText": "Your security system has gone off. The authorities have been notified.", "group": 2, "groupName": "Alarms", "lineNumber": 2, "logTime": "2024-01-22T19:14:00", "msd": null, "partAssociationCSV": null, "priority": 0, "reportStatus": 131, "sourceID": 1, "sourceName": "Zone", "sourceType": 1, "viUID": null }, { "eventDescriptorHint": "%UW", "eventId": 15, "eventName": "Perimeter Set - 'USER' WEB", "eventText": "Your security system has been set in perimeter/part mode.", "group": 4, "groupName": "System Status", "lineNumber": 3, "logTime": "2024-01-22T19:13:01", "msd": null, "partAssociationCSV": null, "priority": 2, "reportStatus": 131, "sourceID": 1, "sourceName": "User", "sourceType": 2, "viUID": null }, { "eventDescriptorHint": "", "eventId": 14, "eventName": "Part Set - Wired Keypad#1", "eventText": "Your security system has been set in part set mode.", "group": 4, "groupName": "System Status", "lineNumber": 8, "logTime": "2024-01-22T00:08:00", "msd": null, "partAssociationCSV": null, "priority": 2, "reportStatus": 131, "sourceID": 1, "sourceName": "WiredKeypad", "sourceType": 2, "viUID": null }, { "eventDescriptorHint": "%U", "eventId": 16, "eventName": "Unset - 'USER'", "eventText": "", "group": 4, "groupName": "System Status", "lineNumber": 29, "logTime": "2024-01-12T10:30:00", "msd": null, "partAssociationCSV": null, "priority": 2, "reportStatus": 131, "sourceID": 1, "sourceName": "User", "sourceType": 2, "viUID": null }, { "eventDescriptorHint": "", "eventId": 14, "eventName": "Part Set - Wired Keypad#1", "eventText": "Your security system has been set in part set mode.", "group": 4, "groupName": "System Status", "lineNumber": 30, "logTime": "2024-01-12T10:15:00", "msd": null, "partAssociationCSV": null, "priority": 2, "reportStatus": 131, "sourceID": 1, "sourceName": "WiredKeypad", "sourceType": 2, "viUID": null } ], "totalCount": 1233 }, "result": 0, "status": 200, "validationErrors": null

OnFreund commented 5 months ago

What does https://www.riscocloud.com/webapi/api/wuws/site/XXXXX/ControlPanel/GetState show when the alarm is triggered?

karlismaj commented 5 months ago

I did line level comparison of GetState responses and the only thing that has changed was bellStatus

When the "bellStatus": 0 it means there is no alarm sound ongoing When the bellStatus is above 0, then alarm is sounding. I don't know why there are three numbers and what is the difference. I was refreshing mobile app and there were no notifications at all. Quite crappy app!! That is why i want HA to work. So i killed and refreshed app several times and that looked to refresh the bellstatus (maybe??). The alarm was sounding all the time and no actions were done but bellstatus was changing. I've added also event log times from GetEventLog but it seems that those do not match exactly. For example alarm was triggered at 21:58 according to log but the bell status at 21:58:02 still shows 0. I guess that is API design.

"bellStatus": 0, "cpTime": "2024-01-22T21:58:02",

"bellStatus": 5 "cpTime": "2024-01-22T21:58:28"

"bellStatus": 3 "cpTime": "2024-01-22T21:58:48",

"bellStatus": 2, "cpTime": "2024-01-22T21:58:58"

"bellStatus": 0, "cpTime": "2024-01-22T21:59:18",

Eventlog times:

"logTime": "2024-01-22T21:56:00" - Alarm set "logTime": "2024-01-22T21:58:00" - Alarm Triggered "logTime": "2024-01-22T21:59:02" - Disarmed

To make things more difficult, i've got unusual result for Arm request. You can see the bellStatus there is 2. But the cpTime is crap. It is unclear when this has happened after "bellStatus": 3. I was trying to set different arming states but could not get such request. Request { "newSystemStatus": 0, "sessionToken": "0fcdd62e537b4509" } Response { "errorText": null, "errorTextCodeID": "0", "response": { "acLost": false, "alarmPending": false, "armNotAllowed": false, "batteryLow": false, "bellOn": false, "bellStatus": 2, "classVersion": 0, "cpTime": "2024-01-22T20:01:24.8811996+00:00", "devCollection": null, "disarmNotAllowed": false, "exitDelayTimeout": 0, "haDevices": null, "haEnabled": true, "part1Ready": false, "part2Ready": false, "partFullReady": false, "partReadySupported": false, "partitions": null, "systemReady": true, "systemStatus": 4, "trouble": true, "type": 1, "users": null, "zones": null }, "result": 52, "status": 200, "validationErrors": null }

hughlewisuk commented 5 months ago

Hi, I am having the same issue. I have an old iConnect2 alarm panel that works with the Risco Android app and also web log in. I get all the sensors returned when I set up for the cloud implementation but do not get the alarm panel.

It seems that in Alarm class, a partition is required

_def partitions(self): """Alarm partitions.""" if self._partitions is None: self._partitions = {p["id"]: Partition(self._api, p) for p in self._raw["partitions"]} return self.partitions

But the response from the Risco panel is "partitions":null so the partition ID cannot be set and hence an exception i thrown

Am I wrong in my understanding? I am new to Python. I have been coding for Windows for 30 years using C++ right down to writing device drivers. But python and Linux is still a bit baffling and I am finding running the Visual Studio Code debugging a bit problematic.