Fixing trigger alert status and add some ancillary features#11
Fixing trigger alert status and add some ancillary features#11bigmoby wants to merge 10 commits intoRyuzakiKK:masterfrom
Conversation
|
Before I'll be able to review it, it would be great if you could keep pyialarm with your changes running for several hours, to ensure nothing breaks. In the past I remember that the API of the alarm was very sensitive and susceptible to timing issues. E.g. multiple consecutive requests without being separated by a timeout eventually leaded the API to stop responding and the only way to recover it was to restart the alarm system. |
|
This is in fact the problem I have been experiencing with the ialarm-mqtt component. @RyuzakiKK I can pull up a test instance of home assistant with no problem, however, how can I test your component if it has not yet merged into HA? |
Hi @RyuzakiKK , at moment (I tested it for about a day) appear to me quite stable. Anyway I'll continue to run it in production |
pyialarm/pyialarm.py
Outdated
| async def _receive(self): | ||
| def raise_connection_error(msg: str): | ||
| self.sock.close() | ||
| raise ConnectionError(msg) | ||
|
|
||
| try: | ||
| if self.sock is None or self.sock.fileno() == -1: | ||
| raise_connection_error("Socket is not open") |
There was a problem hiding this comment.
If self.sock is None, we can't run self.sock.close().
What about using the pre-existing _close_connection() instead?
pyialarm/pyialarm.py
Outdated
| with contextlib.suppress(OSError): | ||
| if self.sock: | ||
| self.sock.close() |
There was a problem hiding this comment.
In which instances can this raise an OSError? I.e. why do we need to suppress it?
Also, if I'm not mistaken, when we are at this point, self.sock is already guaranteed that can't be None. So the if self.sock check can probably be avoided.
There was a problem hiding this comment.
You're right! In order to suppress a Ruff hint, I modified the implementation in this incorrect way!
pyialarm/pyialarm.py
Outdated
| with contextlib.suppress(OSError): | ||
| if self.sock: | ||
| self.sock.close() |
pyialarm/pyialarm.py
Outdated
| def get_last_log_entries(self, log_list: list[LogEntryType]) -> list[LogEntryType]: | ||
| if not log_list: | ||
| return [] | ||
| return log_list[:25] |
There was a problem hiding this comment.
Is this function needed? Doesn't seem to be used.
There was a problem hiding this comment.
Ooops, I removed (and it's a mistake!) the log retrieval function! I would create a service in HA in order to have the log list.
There was a problem hiding this comment.
Another nit is that the check if not log_list: should not be necessary. self.get_log() is never expected to return a None. We are guaranteed to receive either an empty list or a list of log entries.
I would create a service in HA in order to have the log list.
Can you elaborate a bit more on that point? I'm curious how the logs are going to be used in HA.
This function in the end is only doing a list slicing. Maybe we can let HA do it itself?
| raise ConnectionError(error_message) | ||
|
|
||
| if status in {self.ARMED_AWAY, self.ARMED_STAY}: | ||
| zone_status: list[ZoneStatusType] = await self.get_zone_status() |
There was a problem hiding this comment.
Here you are sending a GetAlarmStatus request and then a GetByWay back to back. When I initially attempted it I noticed that it made the alarm would eventually stop responding to the GetbyWay. That why in 2764bbd I was using a one second timeout.
If it works, great! If it doesn't, then we probably need to add some wait before sending the second request.
There was a problem hiding this comment.
Mmm, very interesting! Honestly, I didn't notice any problems related to this, it seems to work without the timeout
|
I'm not familiar with asyncio, so I can't really comment too much on it. Ideally the PR could have been split in multiple part, a first one about the refactoring (e.g. using a But doing that now would probably require too much work, so likely not worth it. I'm just very glad you had the time to contribute those changes. |
To test it you could probably do something like this https://community.home-assistant.io/t/testing-pull-requests-via-custom-components/251587/2, where you download the updated pyialarm and place it in the custom components directory of HA. However, I guess that we'd also need some minor changes to HA itself, because now the API functions are async. @bigmoby am I right in assuming you were testing your changes to pyialarm manually? And not by updating the pyialarm component in a real HA instance? |
Hi @RyuzakiKK , You're totally right! I should have broken the PR down into smaller parts for refactoring, switching to asyncio, and adding tests. It would have been much easier to follow. I got a bit carried away trying to fix everything at once, though. 😅 I'll try to do better in future PRs! |
Thanks for the testing suggestion! I'm currently testing the new library implementation by directly modifying the code in the Home Assistant core DEV branch and applying the changes there. This allows for quicker iteration and verification. Today, I'm hoping to create the PR for the integration part as well. It's almost finalized!
|
|
I'll post the HA integration PR after this library (with new implementations) will be deployed in pypi.org of course :-) |
pyialarm/pyialarm.py
Outdated
| def _ensure_socket_is_open(self) -> None: | ||
| if self.sock is None or self.sock.fileno() == -1: | ||
| self._close_connection() | ||
|
|
||
| def _close_connection(self) -> None: | ||
| if self.sock and self.sock.fileno() != 1: | ||
| if self.sock and self.sock.fileno() != -1: | ||
| self.sock.close() |
There was a problem hiding this comment.
The implementation of _ensure_socket_is_open() seems off? I don't think it's expected to call _close_connection() when we already ensured the self.sock is None or without an open fileno.
If I'm not mistaken, probably you wanted to do something like the following?
def _is_socket_open(self) -> bool:
return self.sock and self.sock.fileno() != -1
[...]
async def ensure_connection_is_open(self) -> None:
if not _is_socket_open():
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
[...]
async def _receive(self):
if not _is_socket_open():
raise_connection_error("Socket is not open")
Thanks, having an easy to apply list of necessary changes in order to test your PR would be very useful. As I mentioned earlier, the API of that alarm is quite fragile so it would be great if we could get some additional manual testings from other users as well, before pushing this change in HA. |
|
Hi @RyuzakiKK Since the new version of the library (2.3.0?!) has not been released yet, it is necessary to copy the library files into the integration directory. |
|
Thanks @bigmoby. @andker87 if you are able to run the HA version that @bigmoby linked above, and copying the updated pyialarm from https://github.com/bigmoby/pyialarm/tree/master, in theory you should be able to test it. If we can get some additional confirmation that this is indeed working fine (especially when the alarm is set to home or away), then we can definitely proceed more comfortably, knowing that it is not causing regressions. |
|
Hi @RyuzakiKK , hi @andker87 |
|
I installed the custom component from hacs, and in the dashboard I put the two alarm_control_panels in parallel view (the first from the node-red flow and the second from the custom_component). |
|
Yes @andker87, I unfortunately noticed it too. Maybe two components pinging the alarm control panel are causing it to go into crisis? |
|
Hi @RyuzakiKK , with the latest release (v0.0.4) it's better managed the response message. At moment the single point of failure of the library is the _is_complete_message() function. I should work in order to optimize it and manage bad xml response like it's a WIP project :-) |
|
Hi guys, Alarm status is updated every 15 seconds: And with this blueprint automation I also solved the alerting feature in my mobile device (I suggest it): |
Is this the same version in this PR or is your custom component different? If it is working fine, then we can proceed to merge it and update the official integration in HA I guess. |
|
Hi @RyuzakiKK, unfortunately no, this PR is now outdated. The library has changed dramatically, there're different returning type and the integration itself should be migrated (yesterday I released the version 1.0.0 with so many improvements...). How would you like to proceed? How can I help? |
|
I didn't check the differences with your current library version. So, if anyone wants to take on the maintenance of the component, I'm more than happy. Instead, if you prefer to keep your changes here, I guess you can create a new pull request (or update this one) and I'll try to do a quick review of it. |
|
I had to fork your project and create another one, renaming it in order to release a new library on PyPI for the new integration I developed. |
As you prefer. Given that you already created a forked project for the library, and also published it on pypi, if you want to update the "official" ha integration you can probably update the HA component with the new APIs and point it to your library, instead of mine. However, if you don't want to spend time updating the HA core (given the amount of work you already put in place), we can also leave it as-is. Maybe in the future removing pyialarm from HA core and just pointing users to your HACS one. |
|
Hi @RyuzakiKK , |



As reported in the subject has been fixed trigger status and retrieved zone_status. Added some other functionalities in order to improve the ialarm integration.