Skip to content

Commit

Permalink
Update to issue jamesleesaunders#55 (not fully fixed), and some docum…
Browse files Browse the repository at this point in the history
…ent / readability changes
  • Loading branch information
jrjefferies committed Oct 30, 2017
1 parent 4b35172 commit de11ebb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 46 deletions.
83 changes: 44 additions & 39 deletions pyalertme/zbnode.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@

# Filename: zbnode.py
# Description: This contains all the values code (and static data structures) act as a zigbee node
# and to communicate with Alertme nodes

from pyalertme.node import Node
import time
import threading
Expand All @@ -7,65 +12,65 @@


# ZigBee Addressing
BROADCAST_LONG = b'\x00\x00\x00\x00\x00\x00\xff\xff'
BROADCAST_SHORT = b'\xff\xfd'
BROADCAST_LONG = b'\x00\x00\x00\x00\x00\x00\xff\xff'
BROADCAST_SHORT = b'\xff\xfe'

# ZigBee Profile IDs
PROFILE_ID_ZDP = b'\x00\x00' # ZigBee Device Profile
PROFILE_ID_HA = b'\x01\x04' # HA Device Profile
PROFILE_ID_LL = b'\xc0\x5e' # Light Link Profile
PROFILE_ID_ZDP = b'\x00\x00' # ZigBee Device Profile
PROFILE_ID_HA = b'\x01\x04' # HA Device Profile
PROFILE_ID_LL = b'\xc0\x5e' # Light Link Profile
PROFILE_ID_ALERTME = b'\xc2\x16' # AlertMe Private Profile

# ZigBee Endpoints
ENDPOINT_ZDO = b'\x00' # ZigBee Device Objects Endpoint
ENDPOINT_ZDO = b'\x00' # ZigBee Device Objects Endpoint
ENDPOINT_ALERTME = b'\x02' # AlertMe / Iris Endpoint

# ZDP Status
ZDP_STATUS_OK = b'\x00'
ZDP_STATUS_INVALID = b'\x80'
ZDP_STATUS_OK = b'\x00'
ZDP_STATUS_INVALID = b'\x80'
ZDP_STATUS_NOT_FOUND = b'\x81'

# ZDO Clusters
# See:
# http://ftp1.digi.com/support/images/APP_NOTE_XBee_ZigBee_Device_Profile.pdf
# http://www.cel.com/pdf/misc/zic09_zdp_api.pdf
CLUSTER_ID_ZDO_NWK_ADDR_REQ = b'\x00\x00' # Network (16-bit) Address Request
CLUSTER_ID_ZDO_NWK_ADDR_RSP = b'\x80\x00' # Network (16-bit) Address Response
CLUSTER_ID_ZDO_SIMPLE_DESC_REQ = b'\x00\x04' # Simple Descriptor Request
CLUSTER_ID_ZDO_ACTIVE_EP_REQ = b'\x00\x05' # Active Endpoints Request
CLUSTER_ID_ZDO_ACTIVE_EP_RSP = b'\x80\x05' # Active Endpoints Response
CLUSTER_ID_ZDO_MATCH_DESC_REQ = b'\x00\x06' # Match Descriptor Request
CLUSTER_ID_ZDO_MATCH_DESC_RSP = b'\x80\x06' # Match Descriptor Response
CLUSTER_ID_ZDO_END_DEVICE_ANNCE = b'\x00\x13' # End Device Announce
CLUSTER_ID_ZDO_MGMT_RTG_REQ = b'\x00\x32' # Management Routing Request
CLUSTER_ID_ZDO_MGMT_RTG_RSP = b'\x80\x32' # Management Routing Response
CLUSTER_ID_ZDO_NWK_ADDR_REQ = b'\x00\x00' # Network (16-bit) Address Request
CLUSTER_ID_ZDO_NWK_ADDR_RSP = b'\x80\x00' # Network (16-bit) Address Response
CLUSTER_ID_ZDO_SIMPLE_DESC_REQ = b'\x00\x04' # Simple Descriptor Request
CLUSTER_ID_ZDO_ACTIVE_EP_REQ = b'\x00\x05' # Active Endpoints Request
CLUSTER_ID_ZDO_ACTIVE_EP_RSP = b'\x80\x05' # Active Endpoints Response
CLUSTER_ID_ZDO_MATCH_DESC_REQ = b'\x00\x06' # Match Descriptor Request
CLUSTER_ID_ZDO_MATCH_DESC_RSP = b'\x80\x06' # Match Descriptor Response
CLUSTER_ID_ZDO_END_DEVICE_ANNCE = b'\x00\x13' # End Device Announce
CLUSTER_ID_ZDO_MGMT_RTG_REQ = b'\x00\x32' # Management Routing Request
CLUSTER_ID_ZDO_MGMT_RTG_RSP = b'\x80\x32' # Management Routing Response
CLUSTER_ID_ZDO_MGMT_PERMIT_JOIN_REQ = b'\x00\x36' # Permit Join Request Request
CLUSTER_ID_ZDO_MGMT_NETWORK_UPDATE = b'\x80\x38' # Management Network Update
CLUSTER_ID_ZDO_MGMT_NETWORK_UPDATE = b'\x80\x38' # Management Network Update

# AlertMe Clusters
# See:
# http://www.desert-home.com/2015/06/hacking-into-iris-door-sensor-part-4.html
CLUSTER_ID_AM_SWITCH = b'\x00\xee' # SmartPlug Switch Cluster
CLUSTER_ID_AM_POWER = b'\x00\xef' # Power Information
CLUSTER_ID_AM_STATUS = b'\x00\xf0' # Device Status
CLUSTER_ID_AM_TAMPER = b'\x00\xf2' # Device Tamper Cluster
CLUSTER_ID_AM_BUTTON = b'\x00\xf3' # Keyfob / Button
CLUSTER_ID_AM_SWITCH = b'\x00\xee' # SmartPlug Switch Cluster
CLUSTER_ID_AM_POWER = b'\x00\xef' # Power Information
CLUSTER_ID_AM_STATUS = b'\x00\xf0' # Device Status
CLUSTER_ID_AM_TAMPER = b'\x00\xf2' # Device Tamper Cluster
CLUSTER_ID_AM_BUTTON = b'\x00\xf3' # Keyfob / Button
CLUSTER_ID_AM_DISCOVERY = b'\x00\xf6' # Device Discovery
CLUSTER_ID_AM_SECURITY = b'\x05\x00' # Security
CLUSTER_ID_AM_SECURITY = b'\x05\x00' # Security

# AlertMe Cluster Commands
CLUSTER_CMD_AM_SECURITY = b'\x00' # Security Event (Sensors)
CLUSTER_CMD_AM_STATE_REQ = b'\x01' # State Request (SmartPlug)
CLUSTER_CMD_AM_STATE_CHANGE = b'\x02' # Change State (SmartPlug)
CLUSTER_CMD_AM_STATE_RESP = b'\x80' # Switch Status Update
CLUSTER_CMD_AM_PWR_DEMAND = b'\x81' # Power Demand Update
CLUSTER_CMD_AM_SECURITY = b'\x00' # Security Event (Sensors)
CLUSTER_CMD_AM_STATE_REQ = b'\x01' # State Request (SmartPlug)
CLUSTER_CMD_AM_STATE_CHANGE = b'\x02' # Change State (SmartPlug)
CLUSTER_CMD_AM_STATE_RESP = b'\x80' # Switch Status Update
CLUSTER_CMD_AM_PWR_DEMAND = b'\x81' # Power Demand Update
CLUSTER_CMD_AM_PWR_CONSUMPTION = b'\x82' # Power Consumption & Uptime Update
CLUSTER_CMD_AM_PWR_UNKNOWN = b'\x86' # Unknown British Gas Power Meter Update
CLUSTER_CMD_AM_MODE_REQ = b'\xfa' # Mode Change Request
CLUSTER_CMD_AM_STATUS = b'\xfb' # Status Update
CLUSTER_CMD_AM_VERSION_REQ = b'\xfc' # Version Information Request
CLUSTER_CMD_AM_RSSI = b'\xfd' # RSSI Range Test Update
CLUSTER_CMD_AM_VERSION_RESP = b'\xfe' # Version Information Response
CLUSTER_CMD_AM_PWR_UNKNOWN = b'\x86' # Unknown British Gas Power Meter Update
CLUSTER_CMD_AM_MODE_REQ = b'\xfa' # Mode Change Request
CLUSTER_CMD_AM_STATUS = b'\xfb' # Status Update
CLUSTER_CMD_AM_VERSION_REQ = b'\xfc' # Version Information Request
CLUSTER_CMD_AM_RSSI = b'\xfd' # RSSI Range Test Update
CLUSTER_CMD_AM_VERSION_RESP = b'\xfe' # Version Information Response

# At the moment I am not sure what/if the following dictionary will be used?
# It is here to describe the relationship between Cluster ID and Cmd.
Expand Down Expand Up @@ -461,9 +466,6 @@ def receive_message(self, message):
source_addr_long = message['source_addr_long']
source_addr_short = message['source_addr']

# Update any attributes which may need updating
self.process_message(source_addr_long, source_addr_short, ret['attributes'])

# Send any replies which may need sending
for reply in ret['replies']:
message_id = reply['message_id']
Expand All @@ -475,6 +477,9 @@ def receive_message(self, message):
self.send_message(reply, source_addr_long, source_addr_short)
time.sleep(0.5)

# Update any attributes which may need updating
self.process_message(source_addr_long, source_addr_short, ret['attributes'])

def parse_message(self, message):
"""
Parse ZigBee message. Work out any attribute changes and reply messages.
Expand Down
8 changes: 4 additions & 4 deletions scripts/console-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
sys.path.insert(0, '../')
from commander import *
import serial
from pyalertme import *
from pyalertme.zbhub import *
import logging
import pprint

Expand All @@ -23,7 +23,7 @@ class TestCmd(Command):
- nodes list
* nodes <device_id> rename string
- nodes <device_id> state [0/1]
* nodes <device_id> mode ?
* nodes <device_id> mode [normal|range|locked|silent]
* nodes <device_id> attributes ?
* nodes <device_id> type
* nodes <device_id> detail
Expand Down Expand Up @@ -82,8 +82,8 @@ def do_nodes(self, *args):
return hub_obj.get_node_attribute_history(node_id, attrib_name, 338083200, 1537228800)

if args[1] == "type":
message = hub_obj.generate_type_request_message()
hub_obj.send_message(message, *hub_obj.device_id_to_addrs(node_id))
device_obj = hub_obj.device_obj_from_id(node_id)
hub_obj.send_type_request(device_obj)
return 'Type Request Sent'

if args[1] == "detail":
Expand Down
10 changes: 7 additions & 3 deletions scripts/hub-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import time
import sys
sys.path.insert(0, '../')
from pyalertme import *
from pyalertme.zbhub import *
import pprint

pp = pprint.PrettyPrinter(indent=4)
Expand All @@ -36,9 +36,10 @@
logger.addHandler(fh)

# Serial Configuration
XBEE_PORT = '/dev/tty.usbserial-DN018OI6'
# XBEE_PORT = '/dev/tty.usbserial-DN018OI6'
# XBEE_PORT = '/dev/cu.usbserial-DN02ZXKE'
# XBEE_PORT = '/dev/tty.usbserial-A1014P7W'
XBEE_PORT = '/dev/ttyUSB0'
XBEE_BAUD = 9600
ser = serial.Serial(XBEE_PORT, XBEE_BAUD)

Expand Down Expand Up @@ -66,6 +67,7 @@
device_obj = hub_obj.devices[node_id]
messages = hub_obj.list_messages()
pp.pprint(messages)
pp.pprint(" exit: to exit this device")
message_id = raw_input("Select Message:")

if message_id in messages.keys():
Expand All @@ -82,8 +84,10 @@
addresses = device_obj.addr_tuple
hub_obj.send_message(message, *addresses)

else:
elif message_id == "exit":
break
elif node_id == "discovery":
hub_obj.discovery()

except KeyboardInterrupt:
print("Keyboard Interrupt")
Expand Down

0 comments on commit de11ebb

Please sign in to comment.