bryan-bartow / homebridge-alarm.com

Alarm.com plugin for Homebridge
ISC License
43 stars 11 forks source link

Replace selenium with 'request' #3

Closed Danimal4326 closed 8 years ago

Danimal4326 commented 8 years ago

I have a 'somewhat' working implementation that uses 'request' and cookies to log into the alarm.com mobile site to get the arming state and to set it. I think this has less overhead than selenium and should be easier to install.

If you'd like, take a look at https://github.com/Danimal4326/homebridge-alarm_dot_com

I can help you port over if possible instead of creating another plugin..

bryanbartow commented 8 years ago

@Danimal4326 What's not working? I'm not familiar with Cheerio, but it looks like you're using a lot of jQuery-like syntax. After a quick glance through your code I couldn't see where you were actually setting the state. I'd say if this works better / faster let's go with it.

Danimal4326 commented 8 years ago

Not that its not working, its just that Selenium has a pretty big overhead.
I use cheerio for web scraping.

AlarmDotComAccessory.prototype.fetchStatus gets the current arming state.

I don't have a set state yet. I'm fairly new to node.js so its a lot of hacked together code..
the mobile site also lets you stay logged in, which might be good for the homebridge plugin..

bmartin5692 commented 8 years ago

I just tested @Danimal4326's code. It seems to be much more responsive and a lot faster than the current implementation. With the selenium implementation I am consistently getting timeouts.

Danimal4326 commented 8 years ago

The code is almost there.. need some help cleaning it up and adding a "set" function.. Also, I think with the 'remember me' option, we should be able to do the login only once on startup and there should be no need to logout..

bryanbartow commented 8 years ago

@bmartin5692 Even with the my latest push, which points to the mobile site?

bryanbartow commented 8 years ago

@Danimal4326 I'm not familiar with Cheerio, so I'll need to get up to speed on it before I can really comment or contribute. Maybe I can look at it this weekend. Concerning the "Remember me" login option, I'm not sure when or if that cookie expires, so logging in only once may or may not be a good idea. Maybe someone can look into that, as it could be a useful addition to even the current selenium-based iteration. I'll create a separate ticket for it.

bmartin5692 commented 8 years ago

Yes. I am still getting timeouts.

/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/goog/async/nexttick.js:41 goog.global.setTimeout(function() { throw exception; }, 0); ^

Error: Timed out waiting for the WebDriver server at http://10.0.1.249:42233/ at Error (native) at onResponse (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/http/util.js:89:11) at /usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/http/util.js:44:21 at /usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/http/http.js:140:5 at ClientRequest. (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/http/index.js:172:7) at emitOne (events.js:77:13) at ClientRequest.emit (events.js:169:7) at Socket.socketErrorListener (_http_client.js:258:9) at emitOne (events.js:77:13) at Socket.emit (events.js:169:7) at emitErrorNT (net.js:1256:8) at nextTickCallbackWith2Args (node.js:441:9) at process.tickCallback (node.js:355:17) From: Task: WebDriver.createSession() at Function.webdriver.WebDriver.acquireSession (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:157:22) at Function.webdriver.WebDriver.createSession (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:131:30) at new Driver (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/phantomjs.js:190:36) at AlarmcomAccessory.getState (/usr/local/lib/node_modules/homebridge-alarmdotcom/index.js:42:18) at emitTwo (events.js:87:13) at emit (events.js:172:7) at Characteristic.getValue (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Characteristic.js:119:10) at Bridge. (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:532:20) at Array.forEach (native) at Bridge.Accessory._handleGetCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:499:8) at emitThree (events.js:97:13) at HAPServer.emit (events.js:175:7) at HAPServer._handleCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:672:10) at HAPServer. (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:178:39) at emitNone (events.js:67:13) at IncomingMessage.emit (events.js:166:7) From: Task: WebDriver.navigate().to(https://www.alarm.com/pda/Default.aspx) at webdriver.WebDriver.schedule (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:362:15) at webdriver.WebDriver.Navigation.to (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:1099:23) at webdriver.WebDriver.get (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:793:26) at AlarmcomAccessory.getState (/usr/local/lib/node_modules/homebridge-alarmdotcom/index.js:44:10) at emitTwo (events.js:87:13) at emit (events.js:172:7) at Characteristic.getValue (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Characteristic.js:119:10) at Bridge. (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:532:20) at Array.forEach (native) at Bridge.Accessory._handleGetCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:499:8) at emitThree (events.js:97:13) at HAPServer.emit (events.js:175:7) at HAPServer._handleCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:672:10) at HAPServer. (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/HAPServer.js:178:39) at emitNone (events.js:67:13) at IncomingMessage.emit (events.js:166:7)

bryanbartow commented 8 years ago

@bmartin5692 Interesting. Are you on a particularly slow network connection? The "mobile" page consistently loads for me in less than a second. It's too bad Alarm.com won't just publicly release their API, which their mobile app uses.

Danimal4326 commented 8 years ago

@bryanbartow exactly, that would be best.. I even tried to sniff it out from the iOS ap, but, fortunately, its encrypted..

bmartin5692 commented 8 years ago

Definitely not a "slow" connection (60 down), but this is running on a Raspberry Pi2. I'll give it a shot from a proper Linux box later and see if that is part of the issue.

bmartin5692 commented 8 years ago

I ran it on a Mac and it is working great. Seems the timeouts are related to the Pi. I'm not sure if is related to a bad module install, but that would be my guess.

bryanbartow commented 8 years ago

@Danimal4326 Same here...

bryanbartow commented 8 years ago

@bmartin5692 Hopefully we can get @Danimal4326 solution fully implemented and it will run faster for everyone on everything.

Danimal4326 commented 8 years ago

I haven't had much time to work on this lately, hence I posted it here, since you released your plugin.
The hard part was getting the login to work via request and cookies.
The mobile page is pretty simple and easy to scrape to read status. The only thing left to do is setting the desired state.

bryanbartow commented 8 years ago

@Danimal4326 I've haven't had a lot of free time either, but I'm hoping maybe I can look at this over the weekend.

amitgandhinz commented 8 years ago

I am also experiencing the timeout issue on the raspberry pi 2

bryanbartow commented 8 years ago

@amitgandhinz I've been slammed, so I haven't been able to pay much attention to this lately. Unfortunately, I don't have a raspberry pi to test on, so any help would have to come from others. As for the larger issue, I still haven't had much time to mess with this. @Danimal4326, have you had any?

bryanbartow commented 8 years ago

I made a big update to the plugin tonight. I used WrapAPI.com to wrap the mobile site with a REST API. The plugin now only needs to make HTTP requests. I'm closing this issue, but anyone feel free to keep a fork at the previous version and finish implementing this.

amitgandhinz commented 8 years ago

@bryanbartow - Thanks for this update!

I am seeing a bug when i run it however.

Apr 09 13:56:08 raspberrypi homebridge[6996]: Sat, 09 Apr 2016 17:56:08 GMT Accessory [Homebridge] Getting value for Characteristic "Security System Current State" Apr 09 13:56:08 raspberrypi homebridge[6996]: [Security Panel] getting sessionUrl Apr 09 13:56:09 raspberrypi homebridge[6996]: /usr/local/lib/node_modules/homebridge-alarmdotcom/index.js:52 Apr 09 13:56:09 raspberrypi homebridge[6996]: this.sessionUrl = json.data.sessionUrl; Apr 09 13:56:09 raspberrypi homebridge[6996]: ^ Apr 09 13:56:09 raspberrypi homebridge[6996]: TypeError: Cannot read property 'sessionUrl' of undefined Apr 09 13:56:09 raspberrypi homebridge[6996]: at AlarmcomAccessory. (/usr/local/lib/node_modules/homebridge-alarmdotcom/index.js:52:34) Apr 09 13:56:09 raspberrypi homebridge[6996]: at Request.self.callback (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/request/request.js:200:22) Apr 09 13:56:09 raspberrypi homebridge[6996]: at emitTwo (events.js:87:13) Apr 09 13:56:09 raspberrypi homebridge[6996]: at Request.emit (events.js:172:7) Apr 09 13:56:09 raspberrypi homebridge[6996]: at Request. (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/request/request.js:1041:10) Apr 09 13:56:09 raspberrypi homebridge[6996]: at emitOne (events.js:82:20) Apr 09 13:56:09 raspberrypi homebridge[6996]: at Request.emit (events.js:169:7) Apr 09 13:56:09 raspberrypi homebridge[6996]: at IncomingMessage. (/usr/local/lib/node_modules/homebridge-alarmdotcom/node_modules/request/request.js:968:12) Apr 09 13:56:09 raspberrypi homebridge[6996]: at emitNone (events.js:72:20) Apr 09 13:56:09 raspberrypi homebridge[6996]: at IncomingMessage.emit (events.js:166:7) Apr 09 13:56:09 raspberrypi homebridge[6996]: at endReadableNT (_stream_readable.js:893:12) Apr 09 13:56:09 raspberrypi homebridge[6996]: at doNTCallback2 (node.js:429:9) Apr 09 13:56:09 raspberrypi homebridge[6996]: at process._tickCallback (node.js:343:17) Apr 09 13:56:09 raspberrypi systemd[1]: homebridge.service: main process exited, code=exited, status=1/FAILURE Apr 09 13:56:09 raspberrypi systemd[1]: Unit homebridge.service entered failed state.

The issue is likely here: https://github.com/bryanbartow/homebridge-alarm.com/blob/master/index.js#L114

You appear to have the WrapAPI links hardcoded to your "bryanbartow" bookmarks. From what I understand reading the WrapAPI docs, my API key will only work against my own bookmarks. Thus this endpoint to wrapAPI should be driven from the configuration. I would suggest a parameter in the config for WrapAPIUsername, and then use that in the code.

eg GET https://wrapapi.com/use/amitgandhinz/alarmdotcom/initlogin/0.0.2?wrapAPIKey=[MYAPIKEY] works (via the browser)

GET https://wrapapi.com/use/bryanbartow/alarmdotcom/initlogin/0.0.2?wrapAPIKey=[MYAPIKEY] will fail (via the browser).

Thanks again for working on this. I am looking forward to seeing it work =)

bryanbartow commented 8 years ago

@amitgandhinz My bad. What was I thinking? I guess that's what I get for working past midnight ;) I'll push a fix soon.

bryanbartow commented 8 years ago

@amitgandhinz It's fixed now.

amitgandhinz commented 8 years ago

@bryanbartow Awesome! This worked. Thanks this is really cool.

On a side note - do you sometimes experience your system loses connectivity to alarm.com and thus even the iOS app struggles to communicate with it to change state? I noticed that initially, then about 5 minutes later the state changed. After that it was working consistently. I feel this is more an alarm.com issue more than a homebridge issue as the same thing happens with the iOS app occassionally.

bryanbartow commented 8 years ago

@amitgandhinz Glad it worked. I have not experienced this, although I rarely use the iOS app. One thing I have noticed is once I do connect and send a command, it can sometimes take up to a minute for my system to actually change state. Like you said, it's probably an Alarm.com issue.

bryanbartow commented 7 years ago

The move to WrapAPI negated this entire conversation.