Git Product home page Git Product logo

abodepy's People

Contributors

amelchio avatar arsaboo avatar clang13 avatar dependabot[bot] avatar kevdliu avatar m2k2 avatar milad-soufastai avatar misterwil avatar paillom avatar sarvjeets avatar scop avatar shred86 avatar thedeany avatar vickyg3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

abodepy's Issues

Time Settings and Gateway Sound Settings

Any chance you've managed to get the api info for system settings?
Specifically i'm trying to work it so that I can easily (via a script) turn off arming sounds in the morning so that I don't wake up anyone else.

I'd love to run a script that

  1. silences all sounds (door chimes, arming beeps)
  2. arms the system
  3. resets the sounds back to 'normal'

This way I can leave and arm the house with no one else waking up.

Thanks for what you've already done!

Indoor Siren

  {
    "id": "RF:008ffeb0",
    "type_tag": "device_type.siren",
    "type": "Siren",
    "name": "Basement Siren",
    "area": "1",
    "zone": "8",
    "sort_order": null,
    "is_window": "",
    "bypass": "0",
    "schar_24hr": "0",
    "sresp_mode_0": "5",
    "sresp_entry_0": "5",
    "sresp_exit_0": "5",
    "sresp_mode_1": "5",
    "sresp_entry_1": "5",
    "sresp_exit_1": "5",
    "sresp_mode_2": "5",
    "sresp_entry_2": "5",
    "sresp_exit_2": "5",
    "sresp_mode_3": "5",
    "sresp_entry_3": "5",
    "sresp_exit_3": "5",
    "version": "",
    "origin": "abode",
    "has_subscription": null,
    "control_url": "",
    "deep_link": null,
    "status_color": "#5cb85c",
    "faults": {
      "low_battery": 0,
      "tempered": 0,
      "supervision": 0,
      "out_of_order": 0,
      "no_response": 0
    },
    "status": "Online",
    "statuses": {
      "hvac_mode": ""
    },
    "status_ex": "",
    "actions": [],
    "status_icons": [],
    "siren_default": "7405",
    "siren_default_ext2": "",
    "icon": "assets/icons/indoor-siren.svg"
  }

Outstanding Devices

Below is an incomplete and possibly duplicated list of devices that are supported by Abode but that are not currently supported by this library because I do not have the device json responses of.

If these devices are to be added to this library then I need the json values of the devices. This can be done by inspecting the network activity on the Abode webapp and pulling the data from the devices request.

Getting Devices through Web App

  1. Go to https://my.goabode.com/#/login
  2. Press Ctrl+Shift+I or Menu -> More Tools -> Developer Tools
  3. Click on "Network" to record network activity
  4. Login
  5. Find "devices" under the Name column
  6. Right click on the row and Copy -> Copy Response
  7. Remove identifying info (if applicable) and create an issue with the data OR DM the response to @MisterWil or email

Getting Devices through AbodePy

  1. Follow the install directions
  2. Run abodepy -u USERNAME -p PASSWORD --devices to get a list of devices
  3. Run abodepy -u USERNAME -p PASSWORD --json DEVICE_ID with the device ID of the device you'd like to share
  4. Copy JSON data from command prompt
  5. Remove identifying info (if applicable) and create an issue with the data OR DM the response to @MisterWil or email

Devices and Open Issues

  • Indoor and/or Outdoor Siren - #15
  • Streaming Camera
  • Shock/Vibration Sensor
  • Indoor Motion Sensor - #13
  • Occupancy Sensor
  • Abode Multi Sensor
  • Temp/Humidity/Light Sensor
  • ZigBee Light
  • ZigBee Smart Plug
  • ZigBee Outlet
  • Z-Wave Light
  • Z-Wave Outlets
  • Z-Wave Flood Sensor - Might already be implemented as water sensor?
  • Z-Wave Dimmers
  • Z-Wave Switches - #9

Occupancy Sensor

In case this helps

No motion

[{
  "id": "ZB:5f2401",
  "type_tag": "device_type.povs",
  "type": "Occupancy",
  "name": "Garage Occupancy",
  "area": "1",
  "zone": "10",
  "sort_order": "",
  "is_window": "",
  "bypass": "0",
  "schar_24hr": "0",
  "sresp_24hr": "0",
  "sresp_mode_0": "0",
  "sresp_entry_0": "0",
  "sresp_exit_0": "0",
  "group_name": "Ungrouped",
  "group_id": "1",
  "default_group_id": "1",
  "sort_id": "10000",
  "sresp_mode_1": "0",
  "sresp_entry_1": "0",
  "sresp_exit_1": "0",
  "sresp_mode_2": "0",
  "sresp_entry_2": "0",
  "sresp_exit_2": "0",
  "sresp_mode_3": "0",
  "uuid": "be29d39bfa7ea4e0add232c2d5fe5ebc",
  "sresp_entry_3": "0",
  "sresp_exit_3": "0",
  "sresp_mode_4": "0",
  "sresp_entry_4": "0",
  "sresp_exit_4": "0",
  "version": "POVS_00.00.03.18TC",
  "origin": "abode",
  "has_subscription": null,
  "control_url": "",
  "deep_link": null,
  "status_color": "#5cb85c",
  "faults": {
    "low_battery": 0,
    "tempered": 0,
    "supervision": 0,
    "out_of_order": 0,
    "no_response": 0
  },
  "status": "Online",
  "statuses": {
    "motion": "0"
  },
  "status_ex": "",
  "actions": [],
  "status_icons": [],
  "sresp_trigger": "0",
  "sresp_restore": "0",
  "occupancy_timer": "30",
  "sensitivity": "4",
  "model": "L1",
  "icon": "assets\/icons\/occupancy-sensor.svg"
}]

Motion detected

[{
  "id": "ZB:5f2401",
  "type_tag": "device_type.povs",
  "type": "Occupancy",
  "name": "Garage Occupancy",
  "area": "1",
  "zone": "10",
  "sort_order": "",
  "is_window": "",
  "bypass": "0",
  "schar_24hr": "0",
  "sresp_24hr": "0",
  "sresp_mode_0": "0",
  "sresp_entry_0": "0",
  "sresp_exit_0": "0",
  "group_name": "Ungrouped",
  "group_id": "1",
  "default_group_id": "1",
  "sort_id": "10000",
  "sresp_mode_1": "0",
  "sresp_entry_1": "0",
  "sresp_exit_1": "0",
  "sresp_mode_2": "0",
  "sresp_entry_2": "0",
  "sresp_exit_2": "0",
  "sresp_mode_3": "0",
  "uuid": "be29d39bfa7ea4e0add232c2d5fe5ebc",
  "sresp_entry_3": "0",
  "sresp_exit_3": "0",
  "sresp_mode_4": "0",
  "sresp_entry_4": "0",
  "sresp_exit_4": "0",
  "version": "POVS_00.00.03.18TC",
  "origin": "abode",
  "has_subscription": null,
  "control_url": "",
  "deep_link": null,
  "status_color": "#5cb85c",
  "faults": {
    "low_battery": 0,
    "tempered": 0,
    "supervision": 0,
    "out_of_order": 0,
    "no_response": 0
  },
  "status": "Motion Detected!",
  "statuses": {
    "motion": "1"
  },
  "status_ex": "",
  "actions": [],
  "status_icons": [],
  "sresp_trigger": "0",
  "sresp_restore": "0",
  "occupancy_timer": "30",
  "sensitivity": "4",
  "model": "L1",
  "icon": "assets\/icons\/occupancy-sensor.svg"
}]

Security Issue: Specify user/password via config file rather than command line

It is a rather large security problem to have user/password be on the command line, since any other user on the same machine can potentially see the login credentials simply with ps.

The user/password should be able to be specified via a config file of some kind. This also makes using command line functionality easier since the user and password don't have to be specified every time.

Ability to hide "Got device update for unknown device..." from logs?

Is there any way to hide the following messages from my Home Assistant logs without hiding all warning messages?

2018-02-20 18:56:53 WARNING (SocketIOThread) [abodepy.event_controller] Got device update for unknown device: XXX

They are coming from my Nest devices that are integrated with Abode but I don't want integrated with Home Assistant.

AbodeEventController being created before login validated

I'm working on adding the MFA config flow for the Abode integration and I noticed something that we should maybe change.

Right now, AbodeEventController is being instantiated towards the beginning of initializing the Abode class.

This results in is each time we try to log into Abode by instantiating the Abode class from HA, it creates an instance of AbodeEventController even if the login fails (i.e. invalid credentials). Each time AbodeEventController is instantiated, a bunch of callbacks are added:

2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: started
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: connected
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: disconnected
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: com.goabode.device.update
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: com.goabode.gateway.mode
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: com.goabode.gateway.timeline
2020-11-25 18:11:15 DEBUG (SyncWorker_6) [abodepy.socketio] Adding callback for event name: com.goabode.automation

I'm not sure if this is really that big of an issue but it seems like this is something that should occur after a valid connection is established or confirmed. An easy solution would be to move this after the self.login() method here. However, if you were able to create an instance of Abode and pass in auto_login=False, then it would self._event_controller would never be set. That being said, I'm not even sure if that's a valid use case.

Thoughts?

Temperature, Humidity, & Light Sensor

  {
    "id": "ZB:6b1301",
    "type_tag": "device_type.lm",
    "type": "LM",
    "name": "Freezer",
    "area": "1",
    "zone": "17",
    "sort_order": "",
    "is_window": "",
    "bypass": "0",
    "schar_24hr": "0",
    "sresp_24hr": "0",
    "sresp_mode_0": "0",
    "sresp_entry_0": "0",
    "sresp_exit_0": "0",
    "group_name": "Sensors",
    "group_id": "<snip>",
    "default_group_id": "1",
    "sort_id": "1",
    "sresp_mode_1": "0",
    "sresp_entry_1": "0",
    "sresp_exit_1": "0",
    "sresp_mode_2": "0",
    "sresp_entry_2": "0",
    "sresp_exit_2": "0",
    "sresp_mode_3": "0",
    "uuid": "<snip>",
    "sresp_entry_3": "0",
    "sresp_exit_3": "0",
    "sresp_mode_4": "0",
    "sresp_entry_4": "0",
    "sresp_exit_4": "0",
    "version": "LMHT_00.00.03.06TC",
    "origin": "abode",
    "has_subscription": null,
    "control_url": "",
    "deep_link": null,
    "status_color": "#5cb85c",
    "faults": {
      "low_battery": 0,
      "tempered": 0,
      "supervision": 0,
      "out_of_order": 0,
      "no_response": 0
    },
    "status": "-5 \u00b0F",
    "statuses": {
      "temperature": "-5 \u00b0F",
      "temp": "-20.65",
      "lux": "0 lx",
      "humidity": "0 %"
    },
    "status_ex": "",
    "actions": [
      { "label": "High Temperature Alarm", "value": "a=1&z=17&trigger=TSH;" },
      { "label": "Low Temperature Alarm", "value": "a=1&z=17&trigger=TSL;" },
      { "label": "High Humidity Alarm", "value": "a=1&z=17&trigger=HMH;" },
      { "label": "Low Humidity Alarm", "value": "a=1&z=17&trigger=HML;" }
    ],
    "status_icons": [],
    "statusEx": "0",
    "icon": "assets/icons/occupancy-sensor.svg"
  }

Trigger a Panic or Silent Duress Alarm?

Is it possible to programmatically trigger a panic or silent duress alarm with abodepy? Maybe I'm just missing it somewhere. I saw that timeline.py can identify those events but I'm not seeing where they can be triggered. I'm trying to use a physical button as a panic button without needing a keypad or a key fob.

Key Fob

{
    "id": "RF:00416b00",
    "type_tag": "device_type.remote_controller",
    "type": "Remote Controller",
    "name": "Remote",
    "area": "1",
    "zone": "4",
    "sort_order": null,
    "is_window": "",
    "bypass": "0",
    "schar_24hr": "0",
    "sresp_mode_0": "0",
    "sresp_entry_0": "0",
    "sresp_exit_0": "0",
    "sresp_mode_1": "0",
    "sresp_entry_1": "0",
    "sresp_exit_1": "0",
    "sresp_mode_2": "0",
    "sresp_entry_2": "0",
    "sresp_exit_2": "0",
    "sresp_mode_3": "0",
    "sresp_entry_3": "0",
    "sresp_exit_3": "0",
    "version": "",
    "origin": "abode",
    "has_subscription": null,
    "control_url": "",
    "deep_link": null,
    "status_color": "#5cb85c",
    "faults": {
      "low_battery": 0,
      "tempered": 0,
      "supervision": 0,
      "out_of_order": 0,
      "no_response": 0
    },
    "status": "Online",
    "statuses": {
      "hvac_mode": null
    },
    "status_ex": "",
    "actions": [],
    "status_icons": [],
    "icon": "assets/icons/key-fob.svg"
  }

SocketIO Error: "Not Authorized"

I've noticed this occurring in the logs anywhere from every 1-3 days which causes for a lot of entries in the Home Assistant logs. My only guess is the session is expiring resulting in the "Not Authorized", but I don't know much about how sockets work (still trying to learn).

2019-09-30 02:55:35 WARNING (SocketIOThread) [lomond] disconnecting websocket
2019-09-30 02:55:35 WARNING (SocketIOThread) [abodepy.socketio] SocketIO Error: "Not Authorized"
2019-09-30 02:55:35 WARNING (SocketIOThread) [abodepy.socketio] Waiting 5.717237 seconds before reconnecting...

URL for socketIO connection

Abodepy is working great for me. However, I'm looking for the socketIO URL. I want to ensure that SSL is being used and my username and password are not being passed unencrypted. Thanks.

HASSIO Status Unavailable - SocketIO Exception: Expecting value: line 1 column 1 (char 0)

The past week or so (sorry that I don't have more details on when exactly) I noticed that my Home Assistant was showing Abode as unavailable. I restarted the HA server and Abode came back. It happened again a day or so later, so I went ahead and updated to 113.1. It appears to fix it for a bit, but the same thing has happened again today. I have looked at the logs, but this is all I really found. I'm not sure if there are any other logs with more detail by default, but I'm going to try to increase the logging level to see if i can get some debug info for you.

2020-07-31 18:02:20 WARNING (SocketIOThread) [abodepy.socketio] Captured exception during SocketIO event callback: Expecting value: line 1 column 1 (char 0)
2020-07-31 18:02:20 WARNING (SocketIOThread) [abodepy.socketio] SocketIO Server Ping Timeout
2020-07-31 18:03:26 WARNING (SocketIOThread) [abodepy.socketio] Captured exception during SocketIO event callback: Expecting value: line 1 column 1 (char 0)
2020-07-31 18:04:26 WARNING (SocketIOThread) [abodepy.socketio] Captured exception during SocketIO event callback: Expecting value: line 1 column 1 (char 0)
2020-07-31 18:04:26 WARNING (SocketIOThread) [abodepy.socketio] SocketIO Server Ping Timeout
2020-07-31 18:05:26 WARNING (SocketIOThread) [abodepy.socketio] Captured exception during SocketIO event callback: Expecting value: line 1 column 1 (char 0)
2020-07-31 18:05:26 WARNING (SocketIOThread) [abodepy.socketio] SocketIO Server Ping Timeout
2020-07-31 18:05:32 WARNING (SocketIOThread) [abodepy.socketio] Captured exception during SocketIO event callback: Expecting value: line 1 column 1 (char 0)

abodecl --listen argument not working

Trying to use the --listen argument to listen to Abode events, but it gives unexpected status code error. Here are the complete logs.

arsaboo@aloknuc:~$ python3 /home/arsaboo/abodepy/abodecl.py --username USERNAME --password PASSWORD --listen
No devices specified, adding all devices to listener...
Listening for device updates...
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /api/v1/panel HTTP/1.1" 200 739
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): my.goabode.com
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /socket.io/?EIO=3&t=1503009522268-0&transport=polling HTTP/1.1" 403 None
WARNING:socketIO-client:my.goabode.com:443/socket.io [engine.io waiting for connection] unexpected status code (403 {"code":4,"message":"origin not allowed"})
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /socket.io/?EIO=3&t=1503009523619-0&transport=polling HTTP/1.1" 403 None
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /socket.io/?EIO=3&t=1503009524704-0&transport=polling HTTP/1.1" 403 None
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /socket.io/?EIO=3&t=1503009525792-0&transport=polling HTTP/1.1" 403 None
DEBUG:urllib3.connectionpool:https://my.goabode.com:443 "GET /socket.io/?EIO=3&t=1503009526878-0&transport=polling HTTP/1.1" 403 None

Not sure what am I missing here. Also, marking @amelchio so that he can be updated on the progress.

lomond issues with Python 3.7

If you try to use abodepy with Python 3.7, it breaks the lomond web listener. Here's the error in Home Assistant:

Traceback (most recent call last):
  File "/Users/shred/venv/homeassistant/lib/python3.7/site-packages/lomond/session.py", line 414, in run
    for event in self.websocket.feed(data):
  File "/Users/shred/venv/homeassistant/lib/python3.7/site-packages/lomond/websocket.py", line 263, in feed
    for message in self.stream.feed(data):
RuntimeError: generator raised StopIteration
2018-09-09 10:02:06 INFO (SocketIOThread) [abodepy.socketio] Websocket Disconnected
^C2018-09-09 10:02:07 INFO (MainThread) [homeassistant.core] Bus:Handling <Event homeassistant_stop[L]>
2018-09-09 10:02:07 INFO (SyncWorker_6) [abodepy.socketio] Stopping SocketIO thread...
2018-09-09 10:02:07 DEBUG (SyncWorker_6) [abodepy] Logout Response: {"code":200,"message":"Logout successful."}
2018-09-09 10:02:07 INFO (SyncWorker_6) [abodepy] Logout successful
2018-09-09 10:02:07 INFO (SyncWorker_6) [homeassistant.components.abode] Logged out of Abode
2018-09-09 10:02:07 INFO (MainThread) [homeassistant.core] Bus:Handling <Event homeassistant_close[L]>

Works fine with Python 3.6.5.

Camera capture method broken

The camera.py module's capture method no longer works. When trying to call the capture method, I get:

2019-11-04 18:27:11 WARNING (SyncWorker_8) [abodepy.devices.camera] Failed to capture image: Request failed

I believe PR #47 is what caused it to stop working. When I view the request using developers tool while logged into the Abode web app, I see the following when requesting an image with the Iota camera:

:method: PUT
:scheme: https
:authority: my.goabode.com
:path: /api/v1/cams/XF:b0c5caxxxxxx/capture

Which is what CAMS_ID_CAPTURE_URL use to be. However, with PR #47, it changed capture to snapshot.

@milad-soufastai Where did you see the path change to capture? I'm wondering if maybe the put request path is different depending on the type of camera you have.

Requesting camera snapshot broken for older Abode cameras

This was brought up in an issue over on the Home Assistant repo: home-assistant/core#29895

There was a previous issue where requesting a camera snapshot for Iota (and possibly the "newer" circular Abode streaming cameras) was broken. The solution was changing the last word for CAMS_ID_CAPTURE_URL in constants.py from snapshot to capture. It appears the older streaming camera still uses snapshot thus breaking this functionality when using the older streaming camera.

I only have the Iota streaming camera but I'll need someone to provide the JSON data for the older (square) 720p streaming camera and newer (round) 1080p streaming camera. We need a way to check the type of camera when the capture method is being called in cameras.py.

Edit: I think I have a simple and more robust fix for this in cameras.py. Currently, the url variable in the capture method is being defined by:

url = str.replace(CONST.CAMS_ID_CAPTURE_URL, '$DEVID$', self.device_id)

Instead, we can change this to:

url = CONST.BASE_URL + self._json_state["control_url_snapshot"]

The JSON data for the Iota camera has a key called control_url_snapshot which specifics the URL for the snapshot feature which we can use. Two obvious benefits:

  1. This will pull the correct "control url" for whichever camera is being used. This assumes all Abode cameras have the key control_url_snapshot in their JSON data. I need someone to confirm this for the older 720p camera and newer 1080p camera (standalone cameras).

  2. If Abode ever updates the control URL, it won't break this capture method.

First Alert ZWave Smoke/CO Detectors not recognized

There is no class created in the devices folder or CONST values for smoke detectors. I got something hacked together last night that got at minimum will recognize the device to test it but doesn’t create the any of the methods or attributes for the class. If it’s ok with you I’ll put together a more proper solution and submit it to you so we can get those devices working in apps like home assistant.

Listen stack trace error

Occasionally, but not always, on connection to the Abode SocketIO server a packet is received:
b'2:401:3'

This packet results in a stack trace from the socketIO_client:
ValueError: invalid literal for int() with base 10: '2:401'

This is due to a minor logic bug in socketIO_client/parsers.py where in _read_packet_length() the logic needs to be that packet_length_string starts at the start index and not 0:

def _read_packet_length(content, content_index):
    indx = content_index
    while content.decode()[content_index] != ':':
        content_index += 1
    packet_length_string = content.decode()[indx:content_index]
    return content_index, int(packet_length_string)

However, when the bug is fixed the socketIO_client seems to get stuck in some sort of reconnect loop. Further debugging is required.

Unable to run abodecl

Thanks for your excellent work. I installed abodeby using
pip3 install abodepy on my Ubunto box, but python abodecl.py --username USERNAME --password PASSWORD --mode gives me the error: python: can't open file 'abodecl.py': [Errno 2] No such file or directory.

Manually searching the file find / abodecl.py also returns find: ‘abodecl.py’: No such file or directory.

Any thoughts?

Add command line --json argument

Add an argument to output the device._json_state to simplify the process of obtaining device json data for future development. Write a section in the readme to describe how to use this functionality to add an issue to request the addition of the device.

Random error in sensor.py

I’ve noticed this for a while but figured I’d post this here for reference. Every now and then I’ll see these errors in my Home Assistant logs that’s pointing to abodepy. This must be coming from my Abode multi-sensor but it doesn’t appear to have any issues in Home Assistant.

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 284, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 330, in _async_write_ha_state
    unit_of_measurement = self.unit_of_measurement
  File "/usr/src/homeassistant/homeassistant/components/abode/sensor.py", line 83, in unit_of_measurement
    return self._device.humidity_unit
  File "/usr/local/lib/python3.7/site-packages/abodepy/devices/sensor.py", line 46, in humidity_unit
    if CONST.UNIT_PERCENT in self._get_status(CONST.HUMI_STATUS_KEY):
TypeError: argument of type 'NoneType' is not iterable
Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 284, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 330, in _async_write_ha_state
    unit_of_measurement = self.unit_of_measurement
  File "/usr/src/homeassistant/homeassistant/components/abode/sensor.py", line 85, in unit_of_measurement
    return self._device.lux_unit
  File "/usr/local/lib/python3.7/site-packages/abodepy/devices/sensor.py", line 58, in lux_unit
    if CONST.UNIT_LUX in self._get_status(CONST.LUX_STATUS_KEY):
TypeError: argument of type 'NoneType' is not iterable

Installing as locally editable package fails

When trying to install a local editable version (checked out directly from github):

pip install -e abodepy/

It fails with the following error:

Obtaining file:///[obscured]/abodepy
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "[obscured]/abodepy/setup.py", line 4, in <module>
        from abodepy.helpers.constants import (__version__, PROJECT_PACKAGE_NAME,
      File "abodepy/__init__.py", line 29, in <module>
        from abodepy.automation import AbodeAutomation
      File "abodepy/automation.py", line 6, in <module>
        import abodepy.helpers.constants as CONST
      File "abodepy/helpers/constants.py", line 202
    SyntaxError: Non-ASCII character '\xc2' in file abodepy/helpers/constants.py on line 202, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in [obscured]/abodepy/

Improve Event Listener

A big problem with the Event Listener is that the socketio client libraries for Python all basically suck. I did, however, find a Websocket library that doesn't suck... so I've written a very light weight EngineIO/SocketIO client that sits on top of this Websocket library. Below are the notes I've compiled for this EngineIO/SocketIO code:

The SocketIO protocol is in fact two protocols. The "transport" is EngineIO and the messaging protocol is SocketIO.

EngineIO Protocol
<packet type id>[<data>]
Ex: 0{"sid":"kOeJt3LgKj2im3UVAFiO","upgrades":[],"pingInterval":25000,"pingTimeout":60000}
Ex: 2probe
Ex: 3probe
Ex: 2
Ex: 3
Ex: 40
Ex: 42["com.goabode.device.update","ZW:00000005"]

Packet Types:

0 open
Sent from the server when a new transport is opened with JSON-encoded handshake data:
sid session ID
upgrades possible transport upgrades
pingTimeout server configured ping timeout - Time to wait for pong response from server before disconnecting
pingInterval server configured ping interval - Time between client sends ping packets

1 close
Request to close the polling interface since polling will open and close sockets regularly. Not required for websockets but will still react to just in case.

2 ping
Sent by the client to the server. Should be sent every pingInterval.

3 pong
Sent by the server to the client to respond to a ping. Should be received within pingTimeout after the last ping.

4 message
Messages to or from the server. We only care about recieving data.

5 upgrade
Upgrade test from one transport to another. Since we're only using websockets we can ignore this.

6 noop
A "no op" packet. Ignored.

Ping Timeouts
The client must send a ping packet every pingInteveral. The client will consider the server unresponsive after not recieving a
reply from the server for pingTimeout. Since the two values are shared between the server and the client, the server
will also be able to detect whether the client becomes unresponsive when it does not receive any data within pingTimeout + pingInterval

SocketIO Protocol
The data portion of an EngineIO packet type 4 will utilize the SocketIO protocol.
Ex: 40
Ex: 42["com.goabode.device.update","ZW:00000005"]
Ex: 42["com.goabode.gateway.timeline",{"mac":"B0:C5:CA:30:0A:C8","id":213014558,"date":"04/03/2018","time":"01:15 PM","event_utc":1522786544,"event_cid":"","event_code":"5125","device_id":"ZW:00000005","device_type_id":"66","device_type":"Dimmer","nest_has_motion":"","nest_has_sound":"","nest_has_person":"","device_name":"Kitchen Lights","file_path":"","deep_link":"","file_name":"","file_size":"","file_count":"","file_is_del":0,"event_type":"On","severity":"8","pos":"l","color":"
000000","is_alarm":"0","icon":"assets/email/lightbulb-on.png","user_id":"","user_name":"","mobile_name":"","parent_tid":"","app_type":"","viewed_by_uid":"","verified_by_tid":"","event_name":"Kitchen Lights On","event_by":""}]

In the above examples the first '4' is the EngineIO message type and everything after it is the SocketIO message type.

The SocketIO message itself if some sort of format like: [data] (ex: 42/chat,[“join”,”{room:1}”])
where optional namespace is "/chat", defaulting to /, and ID is used for the ack. The data portion is essentially a json array where the first index is a string for the event name
and the second index onward can be a string or json object.

We will dumb this down: When we receive an event we will parse out only the [data] portion and parse it as json into a dict, pull out the event_name, and then pass that along with
the event data through to an on_event method.

Message Types:

0 connect Confirms SocketIO Message Connection
1 disconnect Transmitted before SocketIO Disconnect? Not sure where this is used but will similarly react.
2 event Event message - What We've Done This For
3 ack Acknowledge an event - Ignored
4 error Error message (for example, authentication failure).
5 binary event Binary data event - Ignored for our purposes currently
6 binary ack Acknowledge a binary event - Ignored

https://github.com/wildfoundry/dataplicity-lomond/
https://www.willmcgugan.com/blog/tech/post/announcing-lomond/
http://lomond.readthedocs.io/en/latest/
https://github.com/socketio/engine.io-protocol
https://github.com/socketio/socket.io-protocol

Cache Corruption

Seems that there exists an edge case where if the cache exists but is corrupted in some way (failure to write due to disk full or incorrect permissions), logins will fail to work.

Possible solutions are perhaps to verify the integrity of the data.
If the username and password are given then confirm that these values match the cached values?

See this stack overflow for how to append a checksum to the end of a pickle file to verify integrity: https://stackoverflow.com/questions/1653897/if-pickling-was-interrupted-will-unpickling-necessarily-always-fail-python

Occupancy Sensor

Looks like the Occupancy Sensor and the Temperature,Humidity, and Light sensor are considered the same so I see an error in my HA logs on every restart since the Occupancy Sensor doesn't provide Humidity information.
Error doing job: Task exception was never retrieved Traceback (most recent call last): File "/usr/src/app/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity await entity.async_update_ha_state() File "/usr/src/app/homeassistant/helpers/entity.py", line 244, in async_update_ha_state unit_of_measurement = self.unit_of_measurement File "/usr/src/app/homeassistant/components/abode/sensor.py", line 76, in unit_of_measurement return self._device.humidity_unit File "/usr/local/lib/python3.7/site-packages/abodepy/devices/sensor.py", line 44, in humidity_unit if CONST.UNIT_PERCENT in self._get_status(CONST.HUMI_STATUS_KEY): TypeError: argument of type 'NoneType' is not iterable

List and Activate/Deactivate CUE Automations

Are the new CUE Automations built in such a way that it would be possible to list and activate/deactivate them similar to how legacy automations work? Or are they not accessible via API?

Not receiving gateway mode events from Abode websocket

I noticed a few days ago that the alarm panel state in abodepy no longer syncs with the actual gateway state. I added some logging in socketio.py and discovered that it's not getting any gateway mode events. It still gets device update events interestingly, just not mode change events. Not sure if this is just me or are other people seeing this as well.

Support 2FA

Abode now supports 2FA. This ties in to issue #30 which requires a UUID for login requests now. I assume this UUID is to allow Abode to keep track of which 'devices' have logged in previously and used 2FA to complete the process.

I'll need to enable 2FA on my account and then I'll note the new packets that are used to complete this login process. I'll also need to save this UUID somewhere - probably the new config file option as per #20.

abode_alarm_end event not triggered by alarm deactivation

I was testing some home assistant automations today and noticed that the abode_alarm_end event was not fired when I deactivated the alarm. It looks like abodepy groups the alarm end event by code 3100 to 3199. I checked my abode timeline and the "Alarm Disabled" event fired after I deactivated the alarm has code 4001. I think Abode might have changed the code of this event.

Question on Listening long term

Not sure if opening an Issue was the correct way to ask this question, but I didn't see a better way to ask the question. I'm assuming that using the --listen flag is what I would want to use to tie in my Home Automation system (Homeseer) to immediately react to changes in Abode state. I'm interested to know if there are any concerns, perhaps around load on the Abode servers, or other potential issues, with using this for the long haul? If I were to script something to open a listening connection to Abode, it would be 24/7/365 (and reconnect anytime a disconnect happens). Has anyone been doing this or should I avoid it?

If I should avoid it, then I'll need to see if I can find some way to have Abode trigger an external event when states change.

thanks!

Paul

Indoor Motion Sensor

{
    "id": "RF:001d2730",
    "type_tag": "device_type.pir",
    "type": "IR",
    "name": "Foyer Motion",
    "area": "1",
    "zone": "13",
    "sort_order": null,
    "is_window": "",
    "bypass": "0",
    "schar_24hr": "0",
    "sresp_mode_0": "0",
    "sresp_entry_0": "0",
    "sresp_exit_0": "0",
    "sresp_mode_1": "5",
    "sresp_entry_1": "4",
    "sresp_exit_1": "0",
    "sresp_mode_2": "0",
    "sresp_entry_2": "4",
    "sresp_exit_2": "0",
    "sresp_mode_3": "0",
    "sresp_entry_3": "0",
    "sresp_exit_3": "0",
    "version": "",
    "origin": "abode",
    "has_subscription": null,
    "control_url": "",
    "deep_link": null,
    "status_color": "#5cb85c",
    "faults": {
      "low_battery": 0,
      "tempered": 0,
      "supervision": 0,
      "out_of_order": 0,
      "no_response": 0
    },
    "status": "Online",
    "statuses": {
      "hvac_mode": null
    },
    "status_ex": "",
    "actions": [],
    "status_icons": [],
    "model": "L1",
    "icon": "assets/icons/motioncamera-a.svg"
  }

Dimmer

This is the JSON for a Z-Wave dimmer (GE Z-Wave Plus In-Wall Smart Dimmer) connected through Abode.

I am able to control the on/off state through HASS currently (the dimmer shows up as a light), but not the dimmer percentage.

{
  "id": "ZW:0000000b",
  "type_tag": "device_type.dimmer",
  "type": "Dimmer",
  "name": "West Deck Light",
  "area": "1",
  "zone": "10",
  "sort_order": "",
  "is_window": "",
  "bypass": "0",
  "schar_24hr": "0",
  "sresp_24hr": "0",
  "sresp_mode_0": "0",
  "sresp_entry_0": "0",
  "sresp_exit_0": "0",
  "group_name": "Lights",
  "group_id": "<snip>",
  "default_group_id": "1",
  "sort_id": "1",
  "sresp_mode_1": "0",
  "sresp_entry_1": "0",
  "sresp_exit_1": "0",
  "sresp_mode_2": "0",
  "sresp_entry_2": "0",
  "sresp_exit_2": "0",
  "sresp_mode_3": "0",
  "uuid": "<snip>",
  "sresp_entry_3": "0",
  "sresp_exit_3": "0",
  "sresp_mode_4": "0",
  "sresp_entry_4": "0",
  "sresp_exit_4": "0",
  "version": "",
  "origin": "abode",
  "has_subscription": null,
  "control_url": "api/v1/control/light/ZW:0000000b",
  "deep_link": null,
  "status_color": "#5cb85c",
  "faults": {
    "low_battery": 0,
    "tempered": 0,
    "supervision": 0,
    "out_of_order": 0,
    "no_response": 0
  },
  "status": "Off",
  "statuses": {
    "saturation": "N/A",
    "hue": "N/A",
    "level": "0",
    "switch": "0",
    "color_temp": "N/A",
    "color_mode": "N/A"
  },
  "status_ex": "",
  "actions": [
    { "label": "Switch off", "value": "a=1&z=10&sw=off;" },
    { "label": "Switch on", "value": "a=1&z=10&sw=on;" },
    { "label": "Toggle", "value": "a=1&z=10&sw=toggle;" },
    { "label": "0%", "value": "a=1&z=10&sw=0;" },
    { "label": "10%", "value": "a=1&z=10&sw=10;" },
    { "label": "20%", "value": "a=1&z=10&sw=20;" },
    { "label": "30%", "value": "a=1&z=10&sw=30;" },
    { "label": "40%", "value": "a=1&z=10&sw=40;" },
    { "label": "50%", "value": "a=1&z=10&sw=50;" },
    { "label": "60%", "value": "a=1&z=10&sw=60;" },
    { "label": "70%", "value": "a=1&z=10&sw=70;" },
    { "label": "80%", "value": "a=1&z=10&sw=80;" },
    { "label": "90%", "value": "a=1&z=10&sw=90;" },
    { "label": "100%", "value": "a=1&z=10&sw=99;" }
  ],
  "status_icons": [],
  "statusEx": "0",
  "icon": "assets/icons/bulb-1.svg"
}

"Armed with fault" event_codes have updated?

I was curious why I was not getting an abode_panel_fault event triggered in Home Assistant when arming the system with a fault. I set the integration to show debug logs, and I think what I'm seeing is that the fault codes are no longer in the 13xx range, at least for my configuration (I have no delay timer on setting "Home" but I have a 30-second delay on setting "Away"), but rather in the 60xx range. The relevant portions of the debug log are below.

2020-06-26 10:28:11 DEBUG (SyncWorker_28) [abodepy.devices.alarm] Set Alarm Home Response: {"area":"1","mode":"home"}
2020-06-26 10:28:11 INFO (SyncWorker_28) [abodepy.devices.alarm] Set alarm area_1 mode to: home
2020-06-26 10:28:12 DEBUG (SocketIOThread) [abodepy.event_controller] Timeline event received: Gateway Armed w/ Faults(s) - Home - Armed w/ Faults(s) - Home (6077)
2020-06-26 10:28:12 DEBUG (SocketIOThread) [abodepy.event_controller] Alarm mode change event to: home
2020-06-26 10:28:48 DEBUG (SyncWorker_7) [abodepy.devices.alarm] Set Alarm Home Response: {"area":"1","mode":"away"}
2020-06-26 10:28:48 INFO (SyncWorker_7) [abodepy.devices.alarm] Set alarm area_1 mode to: away
2020-06-26 10:28:49 DEBUG (SocketIOThread) [abodepy.event_controller] Timeline event received: Gateway Arming w/ Fault(s) - Away (Exit Timer Started) - Arming w/ Fault(s) - Away (Exit Timer Started) (6055)
2020-06-26 10:29:20 DEBUG (SocketIOThread) [abodepy.event_controller] Timeline event received: Gateway Armed w/ Faults(s) - Away - Armed w/ Faults(s) - Away (6071)
2020-06-26 10:29:20 DEBUG (SocketIOThread) [abodepy.event_controller] Alarm mode change event to: away

Is anyone still seeing fault codes in the 13xx range, or is there something unique to my configuration? Abode did just recently (the last month or so?) release a new version of their app and web interface, so perhaps a minor update to the API/events was made.

Let me know if I can provide any other helpful debug information.

Trouble running from command line

I have a fresh install from today install using:
pip3 install abodepy
seems to be a success:
Installing collected packages: colorlog, six, lomond, certifi, urllib3, idna, chardet, requests, abodepy
Successfully installed abodepy-1.2.0 certifi-2020.12.5 chardet-3.0.4 colorlog-4.6.2 idna-2.10 lomond-0.3.3 requests-2.25.0 six-1.15.0 urllib3-1.26.2

But from command line I get
$ abodepy --help
abodepy: command not found

Is there some additional step needed between pip3 install and running it from command line?

Philips Hue White & Color Bulb

JSON for Philips Hue bulb paired to Abode gateway.

{
"actions": [
{
"label": "Switch off",
"value": "a=1&z=29&sw=off;"
},
{
"label": "Switch on",
"value": "a=1&z=29&sw=on;"
},
{
"label": "Toggle",
"value": "a=1&z=29&sw=toggle;"
},
{
"label": "0%",
"value": "a=1&z=29&sw=0;"
},
{
"label": "10%",
"value": "a=1&z=29&sw=10;"
},
{
"label": "20%",
"value": "a=1&z=29&sw=20;"
},
{
"label": "30%",
"value": "a=1&z=29&sw=30;"
},
{
"label": "40%",
"value": "a=1&z=29&sw=40;"
},
{
"label": "50%",
"value": "a=1&z=29&sw=50;"
},
{
"label": "60%",
"value": "a=1&z=29&sw=60;"
},
{
"label": "70%",
"value": "a=1&z=29&sw=70;"
},
{
"label": "80%",
"value": "a=1&z=29&sw=80;"
},
{
"label": "90%",
"value": "a=1&z=29&sw=90;"
},
{
"label": "100%",
"value": "a=1&z=29&sw=99;"
}
],
"area": "1",
"bypass": "0",
"control_url": "api/v1/control/light/ZB:XXXXXX",
"deep_link": null,
"default_group_id": "1",
"faults": {
"low_battery": 0,
"no_response": 0,
"out_of_order": 0,
"supervision": 0,
"tempered": 0
},
"generic_type": "light",
"group_id": "33092",
"group_name": "Lights",
"has_subscription": null,
"icon": "assets/icons/unknown.svg",
"id": "ZB:XXXXXX",
"is_window": "",
"name": "Bedroom Lamp",
"origin": "abode",
"schar_24hr": "0",
"sort_id": "5",
"sort_order": "",
"sresp_24hr": "0",
"sresp_entry_0": "0",
"sresp_entry_1": "0",
"sresp_entry_2": "0",
"sresp_entry_3": "0",
"sresp_entry_4": "0",
"sresp_exit_0": "0",
"sresp_exit_1": "0",
"sresp_exit_2": "0",
"sresp_exit_3": "0",
"sresp_exit_4": "0",
"sresp_mode_0": "0",
"sresp_mode_1": "0",
"sresp_mode_2": "0",
"sresp_mode_3": "0",
"sresp_mode_4": "0",
"status": "Off",
"statusEx": "0",
"status_color": "#5cb85c",
"status_ex": "",
"status_icons": [],
"statuses": {
"color_mode": "0",
"color_temp": 2695,
"hue": 228,
"level": "50",
"saturation": 56,
"switch": "0"
},
"type": "RGB Dimmer",
"type_tag": "device_type.hue",
"uuid": "",
"version": "LCT014",
"zone": "29"
}

Also, I noticed when using the developer view in Chrome, this is the payload that is passed when adjusting the brightness from the Abode website:

{action: "setpercent", percentage: 40}

This is different than how generic dimmers seem to work which is through changing the 'level' key value pair. However, changing the 'level' key value pair still works with these Philips bulbs.

It's also executing a POST method to this URL: Request URL: https://my.goabode.com/integrations/v1/devices/deviceidehere

'lower' and 'is_on' attribute

AttributeError: 'NoneType' object has no attribute 'lower'
AttributeError: 'AbodeDevice' object has no attribute 'is_on'

I think these may be related to Nest items integrating with abode.

Shock/vibration sensor

  {
    "id": "RF:0059b180",
    "type_tag": "device_type.glass",
    "type": "GLASS",
    "name": "Back door",
    "area": "1",
    "zone": "2",
    "sort_order": "",
    "is_window": "",
    "bypass": "0",
    "schar_24hr": "0",
    "sresp_24hr": "0",
    "sresp_mode_0": "0",
    "sresp_entry_0": "0",
    "sresp_exit_0": "0",
    "group_name": "Ungrouped",
    "group_id": "1",
    "default_group_id": "1",
    "sort_id": "10000",
    "sresp_mode_1": "5",
    "sresp_entry_1": "5",
    "sresp_exit_1": "0",
    "sresp_mode_2": "5",
    "sresp_entry_2": "5",
    "sresp_exit_2": "0",
    "sresp_mode_3": "5",
    "uuid": "xxxx",
    "sresp_entry_3": "5",
    "sresp_exit_3": "0",
    "sresp_mode_4": "5",
    "sresp_entry_4": "5",
    "sresp_exit_4": "0",
    "version": "",
    "origin": "abode",
    "has_subscription": null,
    "control_url": "",
    "deep_link": null,
    "status_color": "#5cb85c",
    "faults": {
      "low_battery": 0,
      "tempered": 0,
      "supervision": 0,
      "out_of_order": 0,
      "no_response": 0
    },
    "status": "Online",
    "statuses": [],
    "status_ex": "",
    "actions": [],
    "status_icons": [],
    "icon": "assets/icons/acoustic-sensor.svg"
  }

Set alarm state to "triggered" when alarm is activated?

Is there any way to set the alarm state to "triggered" when the alarm is activated? I noticed it's being reported in the Home Assistant debug message:

2019-05-25 17:19:25 DEBUG (SocketIOThread) [abodepy.event_controller] Timeline event received: Front Door Interior Alarm Activated - Interior Alarm Activated (1132)

Here is the json data when the alarm is triggered:

[{
    "id": "743443290",
    "event_utc": "1558831901",
    "date": "05\/25\/2019",
    "time": "05:51 PM",
    "event_cid": "",
    "viewed_by_uid": "0",
    "verified_by_tid": "743443663",
    "event_code": "1132",
    "event_type": "Interior Alarm Activated",
    "color": "#cc3f44",
    "user_id": "",
    "user_name": "",
    "mobile_name": "",
    "parent_tid": "",
    "app_type": "",
    "device_id": "SR:PIR",
    "device_type_id": "9",
    "icon": "assets\/email\/alarm-activated.png",
    "device_name": "Living Room Motion",
    "event_name": "Living Room Motion Interior Alarm Activated"
}, {
    "id": "743443285",
    "event_utc": "1558831900",
    "date": "05\/25\/2019",
    "time": "05:51 PM",
    "event_cid": "",
    "viewed_by_uid": "0",
    "verified_by_tid": "743443663",
    "event_code": "1132",
    "event_type": "Interior Alarm Activated",
    "color": "#cc3f44",
    "user_id": "",
    "user_name": "",
    "mobile_name": "",
    "parent_tid": "",
    "app_type": "",
    "device_id": "RF:XXXXXX",
    "device_type_id": "4",
    "icon": "assets\/email\/alarm-activated.png",
    "device_name": "Front Door",
    "event_name": "Front Door Interior Alarm Activated"
}]

Nest Cam, Thermostat, Protect Devices

Unsure if it is desired to pull these devices or not - Home Assistant already offers components for them so it seems silly to duplicate that work. Perhaps if someone wants to use the command line they might want this functionality? I've attached the json for these devices for future reference.

nest_json.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.