Ajax alarm system

My personal information, I work for a company and i’ve insert the information required…. Nothing more….

I have tried with my own personal information as well. I did not get any answer yet. Did you use the information of the company you work for? Is it a security related company?

This is super cool if this is allowed at scale, then just someone needs to wrap all these calls in a python package and we are off and running towards building full integration!

Year ago at least, I tried the same thing with no answer. This is why it it interesting to know what kind of information, no need to disclose the real one, that @Den901 used to go thru the gate

1 Like

Like jeedom ?
I was thinking that it may be an idea to ask Nabucasa to take the leadership. Once authorization is granted the volunteers could to do the job?

1 Like

That’s an excellent idea - just not sure how Ajax themselves regard this sort of integration - I wonder if they’re open to the idea, and whether they would object to having an official integration in place in Home Assistant

Ok alarm is working; I can only ARM/DISARM it for now…

I leave here my nodered flows

LOGIN TO API AND GET THE SESSION_TOKEN

(This flow automatically send a request to the ajax cloud and wrotes SESSION_TOKEN and CLIENT_ID to a txt file every 10 minutes, session time is 15min. don’t forget to create the text files, i’ve created a folder in config/ called “ajax” and indside it 2 text files “sessiontoken.txt” and “user_id.txt” )

[{“id”:“b9768b05f172f820”,“type”:“debug”,“z”:“f95b77a6996a67c9”,“name”:“debug 9”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“payload”,“targetType”:“msg”,“statusVal”:"",“statusType”:“auto”,“x”:1300,“y”:260,“wires”:[]},{“id”:“352f79d533d34b14”,“type”:“inject”,“z”:“f95b77a6996a67c9”,“d”:true,“name”:“LOGIN REQUEST”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“600”,“crontab”:"",“once”:false,“onceDelay”:0.1,“topic”:"",“payload”:"",“payloadType”:“date”,“x”:150,“y”:100,“wires”:[[“7bdd6b909a11c6ed”]]},{“id”:“7bdd6b909a11c6ed”,“type”:“change”,“z”:“f95b77a6996a67c9”,“name”:“GET_SESSION_TOKEN_REQUEST”,“rules”:[{“t”:“set”,“p”:“headers.accept”,“pt”:“msg”,“to”:“application/json”,“tot”:“str”},{“t”:“set”,“p”:“headers.X-Api-Key”,“pt”:“msg”,“to”:“YOUR_API_KEY”,“tot”:“str”},{“t”:“set”,“p”:“headers.Content-Type”,“pt”:“msg”,“to”:“application/json”,“tot”:“str”},{“t”:“set”,“p”:“method”,“pt”:“msg”,“to”:“POST”,“tot”:“str”},{“t”:“set”,“p”:“url”,“pt”:“msg”,“to”:“https://api.ajax.systems/api/login",“tot”:“str”},{“t”:“set”,“p”:“payload”,“pt”:“msg”,“to”:"{“login”:"<YOUR_EMAIL>",“passwordHash”:"<YOUR_PASSWORD>",“userRole”:“USER”}",“tot”:“json”}],“action”:"",“property”:"",“from”:"",“to”:"",“reg”:false,“x”:330,“y”:200,“wires”:[[“16362a97f80dbfbf”]]},{“id”:“16362a97f80dbfbf”,“type”:"http request”,“z”:“f95b77a6996a67c9”,“name”:"",“method”:“use”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"",“tls”:"",“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“x”:650,“y”:160,“wires”:[[“87761cf120671cb3”,“44e4ac01598e5023”,“6ce965ecfdf888cc”]]},{“id”:“87761cf120671cb3”,“type”:“function”,“z”:“f95b77a6996a67c9”,“name”:“GET session_token”,“func”:“msg.payload = msg.payload.sessionToken;\n\nreturn msg”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:770,“y”:260,“wires”:[[“9fe7e118cfa9145f”]]},{“id”:“9fe7e118cfa9145f”,“type”:“file”,“z”:“f95b77a6996a67c9”,“name”:“Writesession_token in file”,“filename”:"/config/ajax/sessiontoken.txt",“filenameType”:“str”,“appendNewline”:false,“createDir”:true,“overwriteFile”:“true”,“encoding”:“none”,“x”:1010,“y”:260,“wires”:[[“b9768b05f172f820”]]},{“id”:“44e4ac01598e5023”,“type”:“debug”,“z”:“f95b77a6996a67c9”,“name”:“debug 10”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“payload”,“targetType”:“msg”,“statusVal”:"",“statusType”:“auto”,“x”:940,“y”:160,“wires”:[]},{“id”:“6ce965ecfdf888cc”,“type”:“function”,“z”:“f95b77a6996a67c9”,“name”:“GET user_id”,“func”:“msg.payload = msg.payload.userId;\n\nreturn msg”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:750,“y”:320,“wires”:[[“0c8d1912bd10aeef”]]},{“id”:“0c8d1912bd10aeef”,“type”:“file”,“z”:“f95b77a6996a67c9”,“name”:“Write user_id in file”,“filename”:"/config/ajax/user_id.txt",“filenameType”:“str”,“appendNewline”:false,“createDir”:true,“overwriteFile”:“true”,“encoding”:“none”,“x”:990,“y”:320,“wires”:[[“f10250a230c17f50”]]},{“id”:“f10250a230c17f50”,“type”:“debug”,“z”:“f95b77a6996a67c9”,“name”:“debug 11”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“payload”,“targetType”:“msg”,“statusVal”:"",“statusType”:“auto”,“x”:1300,“y”:320,“wires”:[]}]

GET THE HUB STATUS

This flow ask the status of your hub and more informations like battery sensor status etc etc…

For a better integration i’ve created an input_boolean that turns to ON and OFF based of the state of the hub (armed / disarmed)

For make this flow working you need the HUB_ID; you have to launch a request to obtain it.

GET LIST OF HUBS ACCOUNTED BY SPECIFIC USER

This request returns the list of hubs accounted on a specific user

curl -X GET “https://api.ajax.systems/api/user/3344FF96/hubs” -H “accept: application/json” -H "X-Api-Key: " -H “X-Session-Token: B_vbg5SCEzPc1GCma2Xhvk8vS98”

[ {
“hubId” : “…”,
“hubBindingRole” : “MASTER”
}, {
“hubId” : “…”,
“hubBindingRole” : “MASTER”
} ]

MASTER stands for an Admin user type.

[{“id”:“9a83d36ca000f85e”,“type”:“debug”,“z”:“7eed70c7fd57591b”,“name”:“debug 12”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“payload”,“targetType”:“msg”,“statusVal”:"",“statusType”:“auto”,“x”:780,“y”:300,“wires”:[]},{“id”:“d9f4a8585ff266a3”,“type”:“change”,“z”:“7eed70c7fd57591b”,“name”:“HUB_STATUS”,“rules”:[{“t”:“set”,“p”:“headers.accept”,“pt”:“msg”,“to”:“application/json”,“tot”:“str”},{“t”:“set”,“p”:“headers.X-Api-Key”,“pt”:“msg”,“to”:“YOUR_X-API_KEY”,“tot”:“str”},{“t”:“set”,“p”:“headers.X-Session-Token”,“pt”:“msg”,“to”:“payload”,“tot”:“msg”},{“t”:“set”,“p”:“method”,“pt”:“msg”,“to”:“GET”,“tot”:“str”},{“t”:“set”,“p”:“url”,“pt”:“msg”,“to”:“https://api.ajax.systems/api/user/<YOUR_USER_ID>/hubs/<YOUR_HUB_ID>”,“tot”:“str”}],“action”:"",“property”:"",“from”:"",“to”:"",“reg”:false,“x”:440,“y”:320,“wires”:[[“4cdc44663472027a”]]},{“id”:“4cdc44663472027a”,“type”:“http request”,“z”:“7eed70c7fd57591b”,“name”:"",“method”:“use”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"",“tls”:"",“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“x”:570,“y”:380,“wires”:[[“9eed4b28c9727171”]]},{“id”:“8e6b5bf72c974591”,“type”:“file in”,“z”:“7eed70c7fd57591b”,“name”:“Get user_id”,“filename”:"/config/ajax/user_id.txt",“filenameType”:“str”,“format”:“utf8”,“chunk”:false,“sendError”:false,“encoding”:“none”,“allProps”:false,“x”:210,“y”:260,“wires”:[[]]},{“id”:“c728706072c95210”,“type”:“inject”,“z”:“7eed70c7fd57591b”,“d”:true,“name”:“LOGIN REQUEST”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“5”,“crontab”:"",“once”:false,“onceDelay”:0.1,“topic”:"",“payload”:"",“payloadType”:“date”,“x”:130,“y”:100,“wires”:[[“4d7335e18ab5f2dc”,“8e6b5bf72c974591”]]},{“id”:“4d7335e18ab5f2dc”,“type”:“file in”,“z”:“7eed70c7fd57591b”,“name”:“Get session_token”,“filename”:"/config/ajax/sessiontoken.txt",“filenameType”:“str”,“format”:“utf8”,“chunk”:false,“sendError”:false,“encoding”:“none”,“allProps”:false,“x”:290,“y”:200,“wires”:[[“d9f4a8585ff266a3”]]},{“id”:“9eed4b28c9727171”,“type”:“switch”,“z”:“7eed70c7fd57591b”,“name”:“STATUS_CHANGE”,“property”:“payload.state”,“propertyType”:“msg”,“rules”:[{“t”:“eq”,“v”:“DISARMED_NIGHT_MODE_OFF”,“vt”:“str”},{“t”:“eq”,“v”:“ARMED_NIGHT_MODE_OFF”,“vt”:“str”}],“checkall”:“true”,“repair”:false,“outputs”:2,“x”:750,“y”:440,“wires”:[[“581229153c246b6e”],[“25c7827ebc1d22fc”]]},{“id”:“25c7827ebc1d22fc”,“type”:“api-call-service”,“z”:“7eed70c7fd57591b”,“name”:“ALARM_ON”,“server”:“bad3090b.a2e298”,“version”:5,“debugenabled”:false,“domain”:“input_boolean”,“service”:“turn_on”,“areaId”:[],“deviceId”:[],“entityId”:[“input_boolean.allarme_ufficio”],“data”:"{“entity_id”:“input_boolean.allarme_ufficio”}",“dataType”:“jsonata”,“mergeContext”:"",“mustacheAltTags”:false,“outputProperties”:[],“queue”:“none”,“x”:930,“y”:500,“wires”:[[]]},{“id”:“581229153c246b6e”,“type”:“api-call-service”,“z”:“7eed70c7fd57591b”,“name”:“ALARM_OFF”,“server”:“bad3090b.a2e298”,“version”:5,“debugenabled”:false,“domain”:“input_boolean”,“service”:“turn_off”,“areaId”:[],“deviceId”:[],“entityId”:[“input_boolean.allarme_ufficio”],“data”:"{“entity_id”:“input_boolean.allarme_ufficio”}",“dataType”:“jsonata”,“mergeContext”:"",“mustacheAltTags”:false,“outputProperties”:[],“queue”:“none”,“x”:1000,“y”:360,“wires”:[[]]},{“id”:“bad3090b.a2e298”,“type”:“server”,“name”:“Home Assistant”,“version”:4,“addon”:true,“rejectUnauthorizedCerts”:true,“ha_boolean”:“y|yes|true|on|home|open”,“connectionDelay”:true,“cacheJson”:true,“heartbeat”:false,“heartbeatInterval”:30,“areaSelector”:“friendlyName”,“deviceSelector”:“friendlyName”,“entitySelector”:“friendlyName”,“statusSeparator”:"at: ",“statusYear”:“hidden”,“statusMonth”:“short”,“statusDay”:“numeric”,“statusHourCycle”:“h23”,“statusTimeFormat”:“h:m”}]

ARM/DISARM ALARM

This flow allows you to control the alarm using the input_boolean created before

[{“id”:“797965c6fd985ba0”,“type”:“http request”,“z”:“7eed70c7fd57591b”,“name”:"",“method”:“use”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"",“tls”:"",“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“x”:890,“y”:180,“wires”:[[]]},{“id”:“3d464c1917c159ad”,“type”:“file in”,“z”:“7eed70c7fd57591b”,“name”:“Get session_token”,“filename”:"/config/ajax/sessiontoken.txt",“filenameType”:“str”,“format”:“utf8”,“chunk”:false,“sendError”:false,“encoding”:“none”,“allProps”:false,“x”:350,“y”:160,“wires”:[[“efbc42627e359ef4”]]},{“id”:“b696f94a4b83aa0a”,“type”:“server-state-changed”,“z”:“7eed70c7fd57591b”,“name”:“STATUS_ALARM”,“server”:“bad3090b.a2e298”,“version”:4,“exposeToHomeAssistant”:false,“haConfig”:[{“property”:“name”,“value”:""},{“property”:“icon”,“value”:""}],“entityidfilter”:“input_boolean.allarme_ufficio”,“entityidfiltertype”:“exact”,“outputinitially”:false,“state_type”:“str”,“haltifstate”:“on”,“halt_if_type”:“str”,“halt_if_compare”:“is”,“outputs”:2,“output_only_on_state_change”:true,“for”:“0”,“forType”:“num”,“forUnits”:“seconds”,“ignorePrevStateNull”:false,“ignorePrevStateUnknown”:false,“ignorePrevStateUnavailable”:false,“ignoreCurrentStateUnknown”:false,“ignoreCurrentStateUnavailable”:false,“outputProperties”:[{“property”:“payload”,“propertyType”:“msg”,“value”:"",“valueType”:“entityState”},{“property”:“data”,“propertyType”:“msg”,“value”:"",“valueType”:“eventData”},{“property”:“topic”,“propertyType”:“msg”,“value”:"",“valueType”:“triggerId”}],“x”:100,“y”:240,“wires”:[[“3d464c1917c159ad”],[“226992382a23c189”]]},{“id”:“efbc42627e359ef4”,“type”:“function”,“z”:“7eed70c7fd57591b”,“name”:“ARMING_FUNCTION”,“func”:“const session = msg.payload\nmsg.headers = {}\nmsg.url = “https://api.ajax.systems/api/user/<YOUR_USER_ID>/hubs/<YOUR_HUB_ID>/commands/arming”\nmsg.method = “PUT”\nmsg.headers[“accept”] = “application/json” \nmsg.headers[“X-Api-Key”] = “<YOUR_X_API_KEY>” \nmsg.headers[“X-Session-Token”] = session\n\n\nmsg.payload = {\n “command”: “ARM”,\n “ignoreProblems”: true\n}\n\nreturn msg”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:640,“y”:180,“wires”:[[“797965c6fd985ba0”]]},{“id”:“2975e0085c2ab629”,“type”:“http request”,“z”:“7eed70c7fd57591b”,“name”:"",“method”:“use”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"",“tls”:"",“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“x”:830,“y”:360,“wires”:[[]]},{“id”:“226992382a23c189”,“type”:“file in”,“z”:“7eed70c7fd57591b”,“name”:“Get session_token”,“filename”:"/config/ajax/sessiontoken.txt",“filenameType”:“str”,“format”:“utf8”,“chunk”:false,“sendError”:false,“encoding”:“none”,“allProps”:false,“x”:290,“y”:340,“wires”:[[“029a79dba9778c9a”]]},{“id”:“029a79dba9778c9a”,“type”:“function”,“z”:“7eed70c7fd57591b”,“name”:“DISARMING_FUNCTION”,“func”:“const session = msg.payload\nmsg.headers = {}\nmsg.url = “https://api.ajax.systems/api/user/<YOUR_USER_ID>/hubs/<YOUR_HUB_ID>/commands/arming”\nmsg.method = “PUT”\nmsg.headers[“accept”] = “application/json” \nmsg.headers[“X-Api-Key”] = “<YOUR_X_API_KEY>” \nmsg.headers[“X-Session-Token”] = session\n\n\nmsg.payload = {\n “command”: “DISARM”,\n “ignoreProblems”: true\n}\n\nreturn msg”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:590,“y”:360,“wires”:[[“2975e0085c2ab629”]]},{“id”:“bad3090b.a2e298”,“type”:“server”,“name”:“Home Assistant”,“version”:4,“addon”:true,“rejectUnauthorizedCerts”:true,“ha_boolean”:“y|yes|true|on|home|open”,“connectionDelay”:true,“cacheJson”:true,“heartbeat”:false,“heartbeatInterval”:30,“areaSelector”:“friendlyName”,“deviceSelector”:“friendlyName”,“entitySelector”:“friendlyName”,“statusSeparator”:"at: ",“statusYear”:“hidden”,“statusMonth”:“short”,“statusDay”:“numeric”,“statusHourCycle”:“h23”,“statusTimeFormat”:“h:m”}]

At the end, you can create a classic “alarm control panel” based on the input boolean and it’s done!

I hope that this can be helpful for someone… in the next days i will add more functions like sensors, areas, night mode etc etc… Keep in mind that’s a beta…

Have you an ajax reseller near you? You can ask him to contact directly Ajax HQ…

Hi all,

I sent a request from my company. They called me and I had a long talk with him.

They will not open the API for small companies.

But he told me that if we could get home assistant to send in a request for access he wouldn’t see any reason not to give access as he is well known with home assistant.

@balloob or @frenck could maybe help on behalf of home assistant to request access and @eavanvalkenburg could make the integration :grinning::sweat_smile:

4 Likes

If that you’re saying is true i can publish my xapi token here

If your are willing to do so, I would advise to disclose it on a private network. It could be very easily revoked

I will talk with @frenck if he is interested to develop an integration using my api code

2 Likes

When i’ve requested the x-api code to ajax I’ve mentioned home assistant and I’ve noticed that the reason of my request is properly to develop an integration between ajax and HA

1 Like

Hi @Den901. Thanks for your good news and for your great job shared with us… I’m strongly interested to a “quite formal” integration with Ajax alarm system based on standard API. Is there some news about that ? Do you think something could be realised on short term? Thank you

Hi @alpat59 I believe that if someone in the group is able to develop native integration, there are now possibilities. unfortunately I do not have these skills but through nodered I was able to integrate it perfectly with the API in my possession. hopefully someone from the group is interested.

Thank you @Den901. Unfortunately I’m not able to develop … so I hope that someone could be interested and that at some time we can have the integration. Maybe @frenck could give us his position about that. Thank you to all.

Hello,

I don’t known how HA works but I known how ajax api work. There is some tricks :

  • with http request you can get some informations (not all) and set state (activate alarm for example) but it’s limited to X requests/min (for me it’s 100 requests/min). If you are alone on your x-api code no problem. But if you are about 100 users or more, this can be an issue…
  • there is a AWS SQS system wich send all information about your ajax system. With that no need get request to known state of door sensor for example. But you need to ask Ajax about your SQS id and Nabu casa need a cloud server to get all information from these SQS and send this information to HA.

I have an ajax alarm, hardware is fantastics and it’s always works but they need to add more information on SIA like door sensor state or temperature. For (de)activation it’s possible to deal with ESP and SpaceControl.

Maybe there is also a possibility with Ajax translantor, I don’t known how it’s work.

Hello,
@Zoic21 thank you for the precious information. If I understood well, the issues your explained us could be in some way managed, specially the first one because I think that each one will work with a separate Token and Client_id, so 100 requests/min means practically no limits…
Anyway there is a good real experience done by @Den901 creating NodeRed flows with function nodes incapsulating Ajax http API calls and that works …
That could be a good way to follow and the expectation now is that some good developer, starting from that, could create a “standard” integration … or, in my opinion better, someone by Nabu could ask to Ajax if the company is interested to join the “Work with Home Assistant” program and develop theirself the integration.
My personal opinions … thank you for this discussion

I created a feature request here: Ajax integration

4 Likes

I hope nabu casa will take a look at this. Maybe they can insist to add door sensor on SIA even when alarm is desarm. For me it’s the most anoying thing we need to add another door sensor to have door state…