# -----------------------------------------------------------------------------
UDP_RECEIVE_PORT = 5005 # port used for incoming UDP data
UDP_RECEIVE_BUFFER_SIZE = 4096 # max buffer size of an incoming UDP packet
-SYSTEM_MASTER_ADDRESS = ("192.168.2.108", 12345) # ip address and portof the system master node
+SYSTEM_MASTER_ADDRESS = ("192.168.1.198", 12345) # ip address and portof the system master node
+#SYSTEM_MASTER_ADDRESS = ("192.168.2.108", 22222) # ip address and portof the system master node
+#SYSTEM_MASTER_ADDRESS2 = ("192.168.2.108", 11111)
+#SYSTEM_MASTER_ADDRESS3 = ("192.168.2.108", 11222)
# time for messages to wait for a response before the system clears away that
# sequence identifier
sendSoceket = socket(AF_INET, SOCK_DGRAM)
receiveSoceket = socket(AF_INET, SOCK_DGRAM)
+
# zigbee address authority list
zigbeeAddressAuthorityDict = dict()
zigbeeConnection.send('at', command="SL")
# sleep for a bit to give the radio time to respond before we check again
- time.sleep(2)
+ #time.sleep(2)
+ time.sleep(0.5)
def addressUpdateWorkerMethod():
''' Method to keep refreshing the short addresses of the known zigbee devices'''
)
zigbeeConnectionMutex.release()
- time.sleep(8)
+ #time.sleep(8)
+ time.sleep(1)
# -------------
zigbeeUnregisteredAddresses.append(parsedData['device_address_long'])
zigbeeUnregisteredAddressesMutex.release()
+
+
#made by changwoo
def processUdpEnrollmentResponse(parsedData, addr):
pass
+#made by Jiawei
+def processUdpZclLockOrUnlockDoorReqMessage(parsedData, addr):
+
+ global zigbeeLongShortAddr
+ global zigbeeLongShortAddrMutex
+ global zigeeBindRequestMutex
+ global zigeeBindRequest
+ global zigbeeConnectionMutex
+ global zigbeeConnection
+ shortAddr = None
+
+ # get the short address for this device long address if possible
+ zigbeeLongShortAddrMutex.acquire()
+ if(zigbeeLongShortAddr.has_key(parsedData['device_address_long'])):
+ shortAddr = zigbeeLongShortAddr[parsedData['device_address_long']]
+ zigbeeLongShortAddrMutex.release()
+
+
+ # if there is a short address than we can send the message
+ # if there is not one then we cannot since we need both the short and
+ # the long address
+ if(shortAddr != None):
+
+ # get a request number
+ seqNumber = createSequenceNumberForClient(addr, parsedData['packet_id'])
+
+ # send back failure
+ if(seqNumber == -1):
+
+ # send an error message, could not get a sequence number to use at this time
+ sendUdpSuccessFail(addr, 'lock_or_unlock_door_request', parsedData['packet_id'], False, 'out_of_space')
+ return
+
+ # get the info for sending
+ destLongAddr = hexStringToZigbeeHexString(parsedData['device_address_long'])
+ destShortAddr = hexStringToZigbeeHexString(shortAddr)
+ dstEndpoint = hexStringToZigbeeHexString(parsedData['device_endpoint'])
+ clusterId = hexStringToZigbeeHexString(parsedData['cluster_id'])
+ profileId = hexStringToZigbeeHexString(parsedData['profile_id'])
+ value = hexStringToZigbeeHexString(parsedData['value'])
+
+ # create and send binding command
+ zigbeeConnectionMutex.acquire()
+
+ zigbeeConnection.send('tx_explicit',
+ frame_id='\x40',
+ dest_addr_long=destLongAddr,
+ dest_addr=destShortAddr,
+ src_endpoint='\x01',
+ dest_endpoint=dstEndpoint,
+ cluster=clusterId,
+ profile=profileId,
+ data='\x01'+chr(seqNumber)+value
+ )
+ time.sleep(1)
+ if value == '\x01':
+ print '> The door lock is unlocked'
+ elif value == '\x00':
+ print '> The door lock is locked'
+ else:
+ print '> Unknown door lock value: ' + str(value)
+
+ zigbeeConnectionMutex.release()
+
+
+ else:
+ # send a fail response
+ sendUdpSuccessFail(addr, 'lock_or_unlock_door_request', parsedData['packet_id'], False, 'short_address_unknown')
+
+
+#made by Jiawei
+def processUdpZclReadDoorStatusReqMessage(parsedData, addr):
+
+ global zigbeeLongShortAddr
+ global zigbeeLongShortAddrMutex
+ global zigeeBindRequestMutex
+ global zigeeBindRequest
+ global zigbeeConnectionMutex
+ global zigbeeConnection
+ shortAddr = None
+
+ # get the short address for this device long address if possible
+ zigbeeLongShortAddrMutex.acquire()
+ if(zigbeeLongShortAddr.has_key(parsedData['device_address_long'])):
+ shortAddr = zigbeeLongShortAddr[parsedData['device_address_long']]
+ zigbeeLongShortAddrMutex.release()
+
+
+ # if there is a short address than we can send the message
+ # if there is not one then we cannot since we need both the short and
+ # the long address
+ if(shortAddr != None):
+
+ # get a request number
+ seqNumber = createSequenceNumberForClient(addr, parsedData['packet_id'])
+
+ # send back failure
+ if(seqNumber == -1):
+
+ # send an error message, could not get a sequence number to use at this time
+ sendUdpSuccessFail(addr, 'read_door_status_request', parsedData['packet_id'], False, 'out_of_space')
+ return
+
+ # get the info for sending
+ destLongAddr = hexStringToZigbeeHexString(parsedData['device_address_long'])
+ destShortAddr = hexStringToZigbeeHexString(shortAddr)
+ dstEndpoint = hexStringToZigbeeHexString(parsedData['device_endpoint'])
+ clusterId = hexStringToZigbeeHexString(parsedData['cluster_id'])
+ profileId = hexStringToZigbeeHexString(parsedData['profile_id'])
+ # framecontrol = hexStringToZigbeeHexString(parsedData['framecontrol'])
+ # commandframe = hexStringToZigbeeHexString(parsedData['commandframe'])
+ # attribute_id = hexStringToZigbeeHexString(parsedData['attribute_id'])
+
+ # create and send binding command
+ zigbeeConnectionMutex.acquire()
+
+ zigbeeConnection.send('tx_explicit',
+ frame_id='\x40',
+ dest_addr_long=destLongAddr,
+ dest_addr=destShortAddr,
+ src_endpoint='\x01',
+ dest_endpoint=dstEndpoint,
+ cluster=clusterId,
+ profile=profileId,
+ data='\x10' + chr(seqNumber) + '\x00' + '\x00\x00'
+ )
+ time.sleep(1)
+
+ zigbeeConnectionMutex.release()
+ print "send read door status"
+
+ else:
+ # send a fail response
+ sendUdpSuccessFail(addr, 'read_door_status_request', parsedData['packet_id'], False, 'short_address_unknown')
+
# made by changwoo
def processUdpBroadcastingRouteRecordReqMessage(parsedData, addr):
sendUdpSuccessFail(addr, 'zcl_configure_reporting', parsedData['packet_id'], False, 'short_address_unknown')
pass
-
def processUdpPolicySet(parsedData, addr):
''' Method handle a policy set message
# do nothing if wrong source
#if addr == SYSTEM_MASTER_ADDRESS or addr == SYSTEM_MASTER_ADDRESS2 or addr == SYSTEM_MASTER_ADDRESS3 :
- #if addr == SYSTEM_MASTER_ADDRESS :
- if addr[0] == SYSTEM_MASTER_ADDRESS[0]:
+ if addr == SYSTEM_MASTER_ADDRESS :
key = (parsedData['ip_address'], int(parsedData['port']))
if (zigbeeAddressAuthorityDict.has_key(key)):
zigbeeAddressAuthorityDict[key].append(parsedData['device_address_long'])
global deviceAnnouncementSingleton
global seqNumberForNotification
+ #made by Jiawei
+ #doorlock response
+ if (parsedData['cluster'] == '\x01\x01' and parsedData['profile'] == '\x01\x04'):
+ zclSeqNumber = parsedData['rf_data'][1]
+ tup = None
+ zigbeeSeqNumberToClientMutex.acquire()
+ if(zigbeeSeqNumberToClient.has_key(ord(zclSeqNumber))):
+ tup = zigbeeSeqNumberToClient[ord(zclSeqNumber)]
+ del zigbeeSeqNumberToClient[ord(zclSeqNumber)]
+ zigbeeSeqNumberToClientMutex.release()
+
+ rfdata = parsedData['rf_data']
+ framecontrol = rfdata[0]
+ command = rfdata[2]
+
+ if tup != None:
+ packetId = tup[2]
+
+ if framecontrol == '\x19':
+ if(command == '\x00'):
+ print ''
+ print "( 0x0101 ) Door Lock: Lock Door Response"
+ print time.strftime("%H:%M:%S", time.localtime())
+ value = rfdata[3]
+ if(value == '\x00'):
+ print "Door locked successfully"
+ else:
+ print "An error occurred in door locking"
+ elif(command == '\x01'):
+ print ''
+ print "( 0x0101 ) Door Lock: Unlock Door Response"
+ print time.strftime("%H:%M:%S", time.localtime())
+ value = rfdata[3]
+ if(value == '\x00'):
+ print "Door unlocked successfully"
+ else:
+ print "An error occurred in door unlocking"
+ return
+ elif framecontrol == '\x18':
+ if(command == '\x01'):
+ attributeId = (ord(rfdata[3]) * 256) + ord(rfdata[4])
+ if attributeId == 0x0000:
+ value = rfdata[7]
+ print "Door status: "
+ if value == '\x00':
+ print "Not fully locked"
+ elif value == '\x01':
+ print "Locked"
+ elif value == '\x02':
+ print "Unlocked"
+ else:
+ print "Unknown value: " + zigbeeHexStringToHexString(value)
+
+ message = "type : zcl_read_attributes_response \n"
+ message += "packet_id: " + packetId + "\n"
+ message += "cluster_id: " + zigbeeHexStringToHexString(parsedData['cluster']) + "\n"
+ message += "profile_id: " + zigbeeHexStringToHexString(parsedData['profile']) + "\n"
+ message += "attributes: "
+
+ attrIdStr = "%0.4x" % attributeId
+ attrIdStr = changeEndian(attrIdStr)
+ message += attrIdStr
+ message += ", "
+
+ zclPayload = parsedData['rf_data'][3:]
+ zclPayload = zclPayload[3:]
+ attributeType = zclPayload[0]
+ message += "%0.2x" % ord(attributeType)
+ message += ", "
+
+ message += "success"
+ message += ", "
+
+ message += "%0.2x" % ord(value)
+ message += ";"
+
+ message += ";"
+
+ message = message[0:len(message) - 1]
+ message += "\n"
+
+ # no one to send the response to so just move on
+ if(tup == None):
+ # cant really do anything here
+ return
+ sendSoceket.sendto(message,tup[0])
+ elif command == '\x07':
+ status = rfdata[3]
+ print ''
+ print "( 0x0101 ) Door Lock: Configure reporting response"
+ print 'rfdata : ' + zigbeeHexStringToHexString(rfdata)
+ if status == '\x00':
+ print "Configure report successfully"
+ message = "type : zcl_configure_reporting_response \n"
+ message += "packet_id: " + packetId + "\n"
+ message += "cluster_id: " + zigbeeHexStringToHexString(parsedData['cluster']) + "\n"
+ message += "profile_id: " + zigbeeHexStringToHexString(parsedData['profile']) + "\n"
+ message += "attributes: "
+ message += "all_success \n";
+
+ # no one to send the response to so just move on
+ if(tup == None):
+ # cant really do anything here
+ return
+ sendSoceket.sendto(message,tup[0])
+ else:
+ print "Configure report unsuccessfully, status =", zigbeeHexStringToHexString(status)
+ elif(command == '\x0A'):
+ print "New update"
+ attributeId = (ord(rfdata[3]) * 256) + ord(rfdata[4])
+ if attributeId == 0x0000:
+ value = rfdata[6]
+ if value == '\x00':
+ print "Not fully locked"
+ elif value == '\x01':
+ print "Locked"
+ elif value == '\x02':
+ print "Unlocked"
+ else:
+ print "Unknown value: " + zigbeeHexStringToHexString(value)
+
+ message = "type : zcl_read_attributes_response \n"
+ message += "packet_id: " + ("%0.2x" % ord(zclSeqNumber)) + "\n"
+ message += "cluster_id: " + zigbeeHexStringToHexString(parsedData['cluster']) + "\n"
+ message += "profile_id: " + zigbeeHexStringToHexString(parsedData['profile']) + "\n"
+ message += "attributes: "
+
+ attrIdStr = "%0.4x" % attributeId
+ attrIdStr = changeEndian(attrIdStr)
+ message += attrIdStr
+ message += ", "
+
+ zclPayload = parsedData['rf_data'][3:]
+ zclPayload = zclPayload[3:]
+ attributeType = zclPayload[0]
+ message += "%0.2x" % ord(attributeType)
+ message += ", "
+
+ message += "success"
+ message += ", "
+
+ message += "%0.2x" % ord(value)
+ message += ";"
+
+ message += ";"
+
+ message = message[0:len(message) - 1]
+ message += "\n"
+
+ # get callback clients to respond to
+ callbackIndex = (zigbeeHexStringToHexString(parsedData['source_addr_long']), zigbeeHexStringToHexString(parsedData['cluster']))
+ retAddr = None
+ zibeeHACallbackMutex.acquire()
+ if(zibeeHACallback.has_key(callbackIndex)):
+ retAddr = zibeeHACallback[callbackIndex]
+ zibeeHACallbackMutex.release()
+
+ # no one to respond to so do nothing here
+ if(retAddr == None):
+ return
+ for ra in retAddr:
+ sendSoceket.sendto(message,ra)
+ return
+
# if this is a ZDO message/response
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
#print parsedData
#print "=================================================================="
+
+
def handleNewUdpPacket(data, addr):
''' Method to parse and handle an incoming UDP packet.
processUdpBroadcastingRouteRecordReqMessage(parsedData, addr)
elif(parsedData["type"] == "zcl_change_switch_request"): #made by changwoo
processUdpZclChangeSwitchReqMessage(parsedData, addr)
+ elif(parsedData["type"] == "zcl_lock_or_unlock_door_request"): #made by Jiawei
+ processUdpZclLockOrUnlockDoorReqMessage(parsedData, addr)
+ elif(parsedData["type"] == "zcl_read_door_status_request"): #made by Jiawei
+ processUdpZclReadDoorStatusReqMessage(parsedData, addr)
else:
- print "unknown Packet: " + parsedData["type"]
+ #print "unknown Packet: " + parsedData["type"]
pass
except:
# if we ever get here then something went wrong and so just ignore this
# setup incoming UDP socket and bind it to self and specified UDP port
# sending socket does not need to be bound to anything
#receiveSoceket.bind(('192.168.2.227', UDP_RECEIVE_PORT))
- receiveSoceket.bind(('192.168.2.192', UDP_RECEIVE_PORT))
+ receiveSoceket.bind(('192.168.1.192', UDP_RECEIVE_PORT))
# create the thread that does short address lookups
addressUpdateWorkerThread = threading.Thread(target=addressUpdateWorkerMethod)