Paradox EVO Binding

This post has been originally created by Joao. With this post the conversation and reverse engineering started. Without his project (GitHub - ParadoxAlarmInterface/pai: Paradox Magellan, Spectra and EVO, with MQTT, Signal, Pushbullet, Pushover and others) the binding for openHAB would not be possible.
Big thanks to @jpbarraca and @Jean_Henning for making the reverse engineering which reallty lead to this binding development!
I’ve moved the original post at the end of the text for reference. Here I will add the information about the openhab binding and most common issues/configurations. Anyone feel free to add information as this post has been made a WIKI upon my request and Joao’s agreement.
If I need debug log file of binding in order to fix found bug, you need to configure binding logging as per my preference and either message me the log file or post it in this thread. Please see the bellow post how to do so.
(Konstantin)

General binding information: Paradox Alarm System binding - Bindings | openHAB
Binding latest custom binaries (outside the official and milestone releases): currently all changes are merged into 3.x codebase so custom binaries are not required or available
Installation of custom binaries can be done via putting the jar file under addons folder of openhab.

Tested and confirmed hardware: Paradox EVO192 with IP150 (v.2.x)

Tested and confirmed not supported hardware: Paradox SP-series

How to configure binding log (this configuration logs all paradox binding related information in separate file - paradox.log):
Please open the file ./userdata/etc/log4j2.xml
Under section Appenders add the following:

 <!-- Paradox custom file appender -->
                <RollingRandomAccessFile fileName="${sys:openhab.logdir}/paradox.log" filePattern="${sys:openhab.logdir}/paradox.log.%i" name="PARADOX">
                        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5.5p] [%-36.36c] - %m%n"/>
                        <Policies>
                                <OnStartupTriggeringPolicy/>
                                <SizeBasedTriggeringPolicy size="100 MB"/>
                        </Policies>
                </RollingRandomAccessFile>

Under the Loggers Section add the following:

  <!-- Paradox custom logger -->
  <Logger additivity="false" level="INFO" name="org.openhab.binding.paradoxalarm">
        <AppenderRef ref="PARADOX"/>
  </Logger>

Here you can change the value of level=“INFO” to level=“TRACE”, “DEBUG”, “ERROR”, etc… Usually for troubleshooting DEBUG level is required, if more info is needed, TRACE should be used. TRACE makes logging of the whole packets so the log file grows a lot with it…

===========================================
Original post by Joao:

Shameless advertising: GitHub - ParadoxAlarmInterface/pai: Paradox Magellan, Spectra and EVO, with MQTT, Signal, Pushbullet, Pushover and others

It supports MG/SP series but it fully processes all messages according to the protocol available. It should not be complicated to add support for the EVO series (probably only change the message parsers, tweak the login process, check the map).

My idea was to also add IP150 as a connection method (besides serial), but I do not have the hardware to test. However, the connection method is already decoupled from the main logic.

If relevant, add new issues in github and help test.

3 Likes

Has anybody worked with the .NET API from Paradox? The one written in C#? I’ve downloaded V4.1 of the API but I cannot get the “WriteUser” API method to work. More specifically, it does not seem to update the user label at all, although any other information (like access control, areas, etc) does write successfully to the panels. I’m trying to determine whether it’s an API problem or whether it’s related to possible old firmware on the EVO and/or IP150.

Hi,

Where can I download this API ? I didn’t found it. I thought there were no API working with IP 150 ?
I didn’t finish my work with ASCII requests because it will take a long time to make a good job but if an API is available…

Check your email :slight_smile:

Thank you so much. I’ll have a look as soon as possible.

Hi Jean,

I’ve tested the associated demo project and all is well working.
What is the peace of code you are trying to use for the Write User. I’ll test if you want to see if it works for me.

Have a nice day.

Hi Ingrid,

Thank you so much for trying this out for me. In the ParadoxApiDemo.exe application, under the “Users” tab there’s a “User” menu. In that menu is a “Write User 5” option.

This maps to the code file “FormParadoxAPI.cs” line 2810, function “MenuItemWriteUser5_Click”. Be careful before doing this as it’s currently coded to overwrite User 5. If you use User 5 on your EVO you can change lines 2816 & 2819 & 2826 from 5 to any other number you wish (i tried 800 to be safe).

The part I’m most interested in is panelUser.Name = “User5” (line 2818) & panelUser.UserName = “Test User 5” (line 2820). One (or both) of these lines supposedly sets the user’s label, yet no matter what I put in these fields, the user label never gets updated. The easiest way to check this is to do the Write and CLOSE the application (if you don’t close it the app seems to remember the user label giving you the false impression it was saved). Then if you reopen the demo app and do a “Read User 5” or “Read All Users” (from the same menu) you wont see the correct user label next to the user you just changed.

The other fields do seem to change, like “panelUser.UserCode”, “panelUser.UserPartitionAccess”, etc. But I cannot get the User’s label to change. I’ve tried all kinds of combinations. In my case User 800 had no user label, so I tried to write “TEST” to it. But every time it says it wrote the user successfully, but when I check that user again the user label is still blank.

Thank you for checking this!

@Jardillier I think I know why the user labels are not writing: The EVO192 & EVOHD store user labels for users > 256 at a seperate memory location. I dont think Paradox’ API supports this. I can write user labels 1 - 256, but as soon as I write user label 257 it no longer saves it but rather deletes it.

https://github.com/jpbarraca/pai now includes ALFA support for IP150 (including version >4)

How are you determining the correct protocol for communicating with the IP150?

Experienced Guesstimate?

We knew the IP150 receives standard panel messages encapsulated with a fixed size header. The structure of the header is still not fully known.

Ok :slight_smile: Yeah the only way I could test this was tracing the packets using WinLoad (with encrypt set to false). Babyware doesnt seem to support unencrypted.

Correct. Newer versions of the module also seem to not support direct connections.

Hi,

Sorry for the late response.

The test with user 5 worked well for me too.
I’ve tried with user 257 with the following code :

            PanelUser panelUser = controlPanel.Users[257];

            panelUser.Name = "User257";
            panelUser.UserNo = 257;
            panelUser.UserName = "Test User 257";
            panelUser.UserCode = "2570";
            panelUser.UserPartitionAccess = "1,2";
            panelUser.UserCanBypass = true;
            panelUser.UserRemoteSerialNo = "123456";

            Int32 returnValue = ParadoxAPI.WriteUser(controlPanel.panelID, 257, panelUser);

And the result is :

Strange, no ?

Yeah, this doesn’t work correctly. I’ve found a way to write this info directly using a TCP connection and some raw panel commands rather than using Paradox’s API.

I’ve tried reaching out to the guy that wrote this (via LinkedIn) but he no longer works for Paradox and I’m unable to find anybody else that’s willing to communicate with me regarding this.

Hi there,

I looked at your file ip_interface.py that lists the IP150 header structure. I can give some more clarity on byte 03 in the header that you list as unknown0. Byte index 03 (fourth byte) in the IP150 header indicates the message type. It has the following values (based on my investigations and comparing messages):

0x03 & 0x04 = REQUEST (sent to the panel)
0x01 & 0x02 = RESPONSE (received from the panel)

0x03: IP request
0x04: Serial / pass-through-command request
0x01: IP response
0x02: Serial / pass-through-command response

An IP request/response is when a command is sent to the IP150 module directly and typically does NOT involve the control panel (MG/SP/EVO). Examples of this is the login sequence to the IP150 module. Those dont directly talk to the control panel but rather sends commands specific to the IP150 module to initiate a connection. That doesn’t mean those commands dont interact with the control panel, but it means the commands are directed at the IP150 and not the control panel.

A serial / pass-through-command is when you send something to the control panel (MG/SP/EVO). In these cases the bytes that follow after the header is typically the serial messages based on the control panel serial protocol:

[ 16 byte Header ] [ Serial / Pass-through command ]

Then something else i’ve noticed: the header byte 05 (6th byte) is the IP commands meant for the IP150 module. It has a value of 0x00 if it’s a serial/pass-through-command. Any other value seems to be IP150 commands (e.g. 0xF0, 0xF2, etc)

Hope that helps!

Many thanks!

I was expecting those bytes to be bit flags, but the remaining paradox protocol seems to use both enums and flags. 0x03 and 0x04 do not make many sense as flags, and I assume they are enums.

I was looking at your code again in paradox_ip_message.py and am curious why you have encrypt in the struct for byte position 08? None of my IP captures indicate this is an encryption flag/value. I have however noticed that byte 04 (flags) seems to indicate encryption. I’ve noticed this in my captures:

Header Byte 04:
Bit 0: (FALSE = no encryption, TRUE = encryption)

This is purely from tracing the packets, but none of my captures indicate anything in byte position 08 as per your code. Can you explain that one please?

So far, here’s what I gathered from the values in position 04 of the header:
REQUESTS
0x08: Not encrypted
0x09: Encrypted

RESPONSES
0x30: Incorrect password (encryption doesnt matter)

0x38: Login successful
0x39: Login successful (encrypted)

0x78: IP module busy
0x79: IP module busy (encrypted)

0x3A: Unknown0
0x3B: Unknown0 (encrypted)

0x32: Unknown1
0x33: Unknown1 (encrypted)

0x7A: Unknown2
0x7B: Unknown2 (encrypted)

0x72: Returned by most serial messages
0x73: Returned by most serial messages (encrypted)

You can see from above bit 0 is typically an indication encryption is used (but it might be more than just bit 0)

I’m doing all my captures using Winload, but I also noticed that Babyware seems to start the very first login message different (both headers are traced when encryption was enabled):

WINLOAD
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
AA 08 00 03 09 F0 00 0A EE EE EE EE EE EE EE EE

BABYWARE
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
AA 08 00 03 09 F0 00 00 00 01 EE EE EE EE 19 0E

Notice that in Babyware bytes 07 - 09 is different, and that Babyware also has different values at bytes 14 & 15.

Probably it was a bad guess. I had to guess many things and I do not have access to documentation and do not own an IP150.

Maybe it indicates different ciphers? Or simply some unused flags are now used by babyware. I noticed those changes and found them strange as they are in what is supposed to be padding

Thanks for the clarification.
Pull requests are welcome :smiley:

Where did you get the code for the IP150 encryption?

I’ve noticed that the encryption/decryption works fine for the very first message (password message) but thereafter encryption/decryption doesnt match what Winload is sending. Does one use the IP module password as the encryption key all the time?