def emberLoop(self): DBG(self.m_cmd) poll = select.poll() self.m_proc = subprocess.Popen(self.m_cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid) stdout_fileno = self.m_proc.stdout.fileno() poll.register(stdout_fileno, select.POLLIN | select.POLLHUP) while self.m_fgRun: events = poll.poll(1000) # Processing events from zbember process. for event in events: (rfd, event) = event if event & select.POLLIN and rfd == stdout_fileno: line = self.m_proc.stdout.readline().strip() # if len(line) == 0 : # continue ; if line == self.m_sentMsg: self.m_sentMsg = None continue # self.m_sentMsg = None ; if self.processMessage(line): DBG(CliColor.GREEN + line + CliColor.NONE) else: DBG(CliColor.YELLOW + line + CliColor.NONE) # Processing events to request queries about zigbee node. # It is singleton therefore no needs a additional mutex. self.__flushQueryPool() self.m_proc.wait() DBG('End of emberLoop')
def run(self): # DBG('DBManager = %d' % ctypes.CDLL('libc.so.6').syscall(224)) ; DBG('Start of DBManager') while self.fgRun: self.m_eventQuery.wait(DBManager.DB_IDLE_SECOND) self.__flushQueryPool() if (time.time() - self.m_lastUpdateTime ) > DBManager.DB_UPDATE_INTERVAL_SECOND: self.__flushSensorPool() self.__flushSensorPool() DBG('End of DBManager')
def cliMain(self) : DBG('Start of cliMain') ; while self.m_fgRun : cmd = raw_input(Cli.PROMPT).strip().split() ; # DBG('CMD%s' % cmd) if cmd == [] : continue ; try : self.command[cmd[0]](None if len(cmd)==1 else cmd[1:]) ; except KeyError : ERR('Unknown Command, %s' % cmd) DBG('End of cliMain') ;
def _dumpContentTable(self, table): cur = self.queryScalar('PRAGMA TABLE_INFO(%s);' % table) if cur: schema = '' for row in cur.fetchall(): schema += '%s , ' % row[1] cur = self.queryScalar('SELECT * FROM %s ORDER BY 1;' % table) DBG('Schema : %s' % schema) idx = 0 for row in cur.fetchall(): rowData = '' idx += 1 for col in row: rowData += '%s , ' % col DBG('%6d : %s' % (idx, rowData))
def processMessage(self, msg): RegxPool = ( (self.rxOnMessage, r'T(.+):nodeId\[0x([0-9a-fA-F]+)\] RX len ([0-9a-fA-F]+), ep ([0-9a-fA-F]+), clus 0x([0-9a-fA-F]+) \((.+)\) mfgId ([0-9a-fA-F]+) FC ([0-9a-fA-F]+) seq ([0-9a-fA-F]+) cmd ([0-9a-fA-F]+) payload\[(.+)\]' ), # It brings up automatically by Device-Query-Service plugin for sending a simple descriptor request. # ( self.rxOnSimple, r'Device-Query-Service EP\[([0-9a-fA-F]+)\] : found for 0x([0-9a-fA-F]+)') , (self.rxOnIEEE, r'IEEE Address response: \(>\)([0-9a-fA-F]+) for 0x([0-9a-fA-F]+)' ), (self.rxOnNewJoin, r'emberAfTrustCenterJoinCallback@newNodeId<0x([0-9a-fA-F]+)> newNodeEui64<([0-9a-fA-F]+)> parentOfNewNode<0x([0-9a-fA-F]+)> EmberDeviceUpdate<(.*)> EmberJoinDecision<(.*)>' ), (self.rcOnJoinStart, r'Device-Query-Service added device to database: \(>\)([0-9a-fA-F]+), capabilities: 0x([0-9a-fA-F]+)' ), (self.rxOnCluster, r'Device-Query-Service (in|out) cluster 0x([0-9a-fA-F]+) for ep\[([0-9a-fA-F]+)\] of 0x([0-9a-fA-F]+) (.*)' ), (self.rxOnBasic, r'Device-Query-Service All endpoints discovered for 0x([0-9a-fA-F]+)' ), (self.rxOnCoInfo, r'node \[\(>\)([0-9a-fA-F]+)\] chan \[([0-9]+)\] pwr \[([0-9a-fA-F]+)\]' ), (self.rxOnInfo, r'EMBER_NETWORK_UP 0x0000'), ) # Remove prompt word if ZbEmber.PROMPT == msg[0:8]: msg = msg[8:] for func, rstr in RegxPool: mo = re.match(rstr, msg) if mo: DBG(mo.groups()) return func(mo)
def sendMsg(self, msg): with self.m_lockSend: try: self.sock.sendall(msg + IPC_TERMINATOR) except socket.error, e: DBG('Have Socket Errors : %s' % e) self.stop()
def queryUpsert(self, notifyList) : query = [] ; for protoSubtype, payload in notifyList : if protoSubtype == 'SENSOR' : field = payload.split('|') ; if field[1] in SensorDB.SubtypeTableMap : table = SensorDB.SubtypeTableMap[field[1]] ; if len(field) != 6 : ERR('Field length is 6 over, %s-%s.' % (protoSubtype, payload)) ; continue ; if table == 'sensor_node' : query.append("INSERT OR IGNORE INTO %s (eui) VALUES ('%s') ;" % (table, field[2])) ; query.append("UPDATE %s SET fuid='%s' WHERE eui='%s' ;" % (table, field[3], field[2])) ; query.append("UPDATE %s SET stamp='%s' WHERE eui='%s' ;" % (table, field[0], field[2])) ; query.append("UPDATE %s SET type='%s' WHERE eui='%s' ;" % (table, field[1], field[2])) ; if field[4] not in SensorDB.EmptyField : query.append("UPDATE %s SET value='%s' WHERE eui='%s' ;" % (table, field[4], field[2])) ; if field[5] not in SensorDB.EmptyField : query.append("UPDATE %s SET extra='%s' WHERE eui='%s' ;" % (table, field[5], field[2])) ; else : query.append("INSERT OR IGNORE INTO %s (eui, fuid) VALUES ('%s', '%s') ;" % (table, field[2], field[3])) ; query.append("UPDATE %s SET stamp='%s' WHERE eui='%s' AND fuid='%s' ;" % (table, field[0], field[2], field[3])) ; query.append("UPDATE %s SET type='%s' WHERE eui='%s' AND fuid='%s' ;" % (table, field[1], field[2], field[3])) ; if field[4] not in SensorDB.EmptyField : query.append("UPDATE %s SET value='%s' WHERE eui='%s' AND fuid='%s' ;" % (table, field[4], field[2], field[3])) ; if field[5] not in SensorDB.EmptyField : query.append("UPDATE %s SET extra='%s' WHERE eui='%s' AND fuid='%s' ;" % (table, field[5], field[2], field[3])) ; else : ERR('Unknown subtype, %s-%s.' % (protoSubtype, payload)) ; else : DBG('Not supported portoSubtype, %s-%s.' % (protoSubtype, payload)) ; self.queryUpdate(query) ; del query ;
def queryScalar(self, query): try: cur = self.m_con.cursor() cur.execute(query) return cur except sqlite3.Error, e: DBG('DB Error, %s: %s' % (e.args, query))
def _getModule(name, path): try: module = imp.load_source(name, path) except SyntaxError, err: ERR('Syntax Error : %s' % path) DBG(err) module = None
def dump(self, msg=''): if len(self.m_clusterArray) > 0: for cl in self.m_clusterArray: msgep = msg + ' ep[%d]' % self.getId() cl.dump(msgep) else: DBG(msg + ' ep[%d]' % self.getId())
def __receivedPacket(self, msg): ''' receivedPacket() is called by IPCClient thread. ''' field = msg[0:18].split('|') # print '@@', field if len(field) == 4: fieldId = field[0] fieldType = field[1] fieldSub = field[2] payload = msg[18:] if int(fieldId, 16) != 0: if fieldType == IPMeta.REPLY: # Caller of Request is only recevied Reply. with self.m_lockQuery: try: self.m_queryPool[fieldId][1] = payload self.m_queryPool[fieldId][0].set() except KeyError: # Maybe, it is not mine. pass elif fieldType == IPMeta.REQUEST: if hasattr(self.m_callback, '__call__'): self.m_callback(fieldId, fieldSub, payload) else: # Notify if hasattr(self.m_callback, '__call__'): self.m_callback(fieldId, fieldSub, payload) elif msg == IPMeta.IPC_QUIT: DBG('Quit a IPC Client') with self.m_lockQuery: for key in self.m_queryPool: self.m_queryPool[key][0].set()
def rxOnMsgReadAttribute(self, node, ep, cl, payload): if self.m_zbHandle.upsertAttribute( node, ep, cl, self.m_zbHandle.doReadPayload(payload)): DBG('Attribute Updated from Read Attribute') if node.getJoinState() == ZbJoinState.BASIC: if payload.find('00 40 ') == 0: self.m_zbHandle.doConfiguration(self, node) return True
def dump(self, msg=''): if len(self.m_attributeArray) > 0: for at in self.m_attributeArray: msgcl = msg + ' C[%s %s]' % (hex(self.getId()), str( self.m_dir)) at.dump(msgcl) else: DBG(msg + ' %s %s' % (hex(self.getId()), str(self.m_dir)))
def main(argv): if argv[0] == 'server': UIDDaemon(uidHost, uidPort) elif argv[0] == 'client': DBG( UIDClient(uidHost, uidPort).getUID('\n' if len(argv) == 1 else argv[1] + '\n'))
def dump(self, msg=''): msgnd = msg + ' %s %s %s Mfg[%04X] Join.%s C%X' % ( self.m_eui, hex(self.m_id), str(self.m_extra.activity), self. m_extra.mfgId, ZbJoinState.dump(self), self.m_extra.capability) if len(self.m_endpointArray) > 0: for ep in self.m_endpointArray: ep.dump(msgnd) else: DBG(msgnd)
def sendQueryRequest(self, subType, payload, timeout=0): assert ( len(subType) == IPMeta.SIZE_SUBTYPE), 'subType length is not 6.' event = threading.Event() try: fieldId = self.__getUID() except socket.error, e: DBG('Have Socket Errors : %s' % e) self.stop() return None
class IPCClient(threading.Thread): def __init__(self, host, port=None, cbfunc=None): threading.Thread.__init__(self) if isinstance(port, int): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect((host, port)) else: self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(host) self.fgAlive = True self.buffer = [] self.m_lockSend = threading.Lock() self.cbfunc = cbfunc self.start() def __doPollIn(self): rv = False tmp = self.sock.recv(1) if tmp != IPC_TERMINATOR: self.buffer.append(tmp) else: msg = ''.join(self.buffer).strip() self.buffer = [] if self.cbfunc: assert (hasattr(self.cbfunc, '__call__')) self.cbfunc(msg) if msg == IPC_QUIT: rv = True return rv def run(self): poll = select.poll() poll.register(self.sock, select.POLLIN | select.POLLHUP) pollc = 1 try: sockFd = self.sock.fileno() while self.fgAlive and pollc > 0: fgUnregister = False events = poll.poll(1000) for event in events: (rfd, event) = event if event & select.POLLIN: if rfd == sockFd: fgUnregister = self.__doPollIn() if fgUnregister or event & select.POLLHUP: poll.unregister(rfd) pollc -= 1 if pollc > 0: poll.unregister(sockFd) pollc -= 1 except select.error, e: DBG('Select Errors : %s' % e) except socket.error, e: DBG('Have Socket Errors : %s' % e)
def queryUpdate(self, query): try: cur = self.m_con.cursor() if isinstance(query, list): for q in query: cur.execute(q) else: cur.execute(query) self.m_con.commit() except sqlite3.Error, e: self.m_con.rollback() DBG('DB Error, %s: %s' % (e.args, query))
def rcOnJoinStart(self, mo): fgStart = False node = self.m_zbHandle.getNodeWithEUI(mo.group(1)) if node: DBG('Already Exist Node') if node.getJoinState() != ZbJoinState.DONE: fgStart = True else: fgStart = True if fgStart: self.sendMsg('plugin device-query-service start') return fgStart
def rxOnNewJoin(self, mo): rv = False node = self.m_zbHandle.getNodeWithEUI(mo.group(2)) if mo.group(4).find(' left') >= 0: DBG('Device left, but keeping device data.') if node: self.m_zbHandle.setActivity(node, False) elif mo.group(4).find(' rejoin') >= 0: # TODO : # It should be to read basic cluster attributes for firmware version and others ... # Or to write IAS Zone's CIB Address for Notification because some device could be forgot the coordinator's endpoint. But it is not mandotory. pass elif mo.group(4).find(' join') >= 0: rv = True if node is None: node = self.m_zbHandle.addNode(mo.group(2), mo.group(1)) else: # It could be changed nodeId, in case of joinning again after end-device leaved network by user. self.m_zbHandle.setJoinState(node, ZbJoinState.SIMPLE) self.m_zbHandle.updateNode(node, int(mo.group(1), 16)) else: DBG(CliColor.RED + 'Unknown State' + CliColor.NONE) return rv
def target(zbem, node): moduleName = '%s_%s' % ( node.getValue(1, ZCLCluster.ZCL_BASIC_CLUSTER_ID, ZCLAttribute.ZCL_MANUFACTURER_NAME_ATTRIBUTE_ID), node.getValue(1, ZCLCluster.ZCL_BASIC_CLUSTER_ID, ZCLAttribute.ZCL_MODEL_IDENTIFIER_ATTRIBUTE_ID)) configFile = 'config/%s.py' % moduleName DBG('Configuration : %s' % configFile) configFile = ZbConfig._doVerify(configFile) module = ZbConfig._getModule(moduleName, configFile) if module: if hasattr(module, 'doInit'): instInit = getattr(module, 'doInit') ZbConfig._doSendMessage(zbem, instInit(node)) if hasattr(module, 'doConfig'): instConfig = getattr(module, 'doConfig') ZbConfig._doSendMessage(zbem, instConfig(node), node) zbem.m_zbHandle.setJoinState(node, ZbJoinState.CONFIG) del module
class ZbConfig: DEFAUT_CONFIG = 'zigbee_common' @staticmethod def _doVerify(configFile): if os.path.exists(configFile): # TODO : checking config file - syntax and import .... return configFile DBG('File Not Exist : %s - Using a default config file.' % configFile) return 'config/%s.py' % ZbConfig.DEFAUT_CONFIG @staticmethod def _doSendMessage(zbem, msgs, node=None): if type(msgs) is list: coEUI = zbem.m_zbHandle.getSwapEUI() swapCoEUI = zbem.m_zbHandle.getEUI() # print msgs ; countReport = 0 for msg in msgs: msg = msg.replace('IASCIE', swapCoEUI) msg = msg.replace('COEUI', coEUI) zbem.sendMsg(msg) countReport += msg.count('send-me-a-report') time.sleep(0.1) if node: node.setRequestedCount(countReport) @staticmethod def _getModule(name, path): try: module = imp.load_source(name, path) except SyntaxError, err: ERR('Syntax Error : %s' % path) DBG(err) module = None except Exception, err: ERR('Exception Error : %s' % path) DBG(err) module = None
def run(self): poll = select.poll() poll.register(self.sock, select.POLLIN | select.POLLHUP) pollc = 1 try: sockFd = self.sock.fileno() while self.fgAlive and pollc > 0: fgUnregister = False events = poll.poll(1000) for event in events: (rfd, event) = event if event & select.POLLIN: if rfd == sockFd: fgUnregister = self.__doPollIn() if fgUnregister or event & select.POLLHUP: poll.unregister(rfd) pollc -= 1 if pollc > 0: poll.unregister(sockFd) pollc -= 1 except select.error, e: DBG('Select Errors : %s' % e)
# else : # self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) ; # self.sock.connect(host) ; # def getUID(self, msg=UID_TOKEN) : # try : # self.sock.sendall(msg) ; # uid = self.sock.recv(16) ; # finally : # self.sock.close() ; # return uid ; if __name__ == '__main__': import sys uidHost = '/tmp/picam/socket_uid' uidPort = None def main(argv): if argv[0] == 'server': UIDDaemon(uidHost, uidPort) elif argv[0] == 'client': DBG( UIDClient(uidHost, uidPort).getUID('\n' if len(argv) == 1 else argv[1] + '\n')) if len(sys.argv) == 1: DBG('usage : %s <server|client> [message]' % sys.argv[0]) raise SystemExit main(sys.argv[1:])
def run(self): try: asyncore.loop(map=_ipc_room) except asyncore.ExitNow, e: DBG(e)
def _sendMsg(param): zbem = param[0] msg = param[1] DBG(CliColor.BLUE + msg + CliColor.NONE) zbem.m_proc.stdin.write(msg + ENTER) zbem.m_sentMsg = ZbEmber.PROMPT + msg
def receivedZigbeeQuery(self, ipId, ipSType, ipPayload): DBG('[QUERY] %s %s %s' % (ipId, ipSType, ipPayload)) with self.m_lockDB: self.m_queryPool.append([ipId, ipPayload]) # It is just intended to awaken to send a terminator. self.sendMsg(' ')
def rxOnMsgIasZoneEnrollRequest(self, node, ep, cl, payload): self.m_zbHandle.setNodeExtraInfo(node, payload) attrList = self.m_zbHandle.doIasZoneEnrollRequest(payload) if self.m_zbHandle.upsertAttribute(node, ep, cl, attrList): DBG('Attribute Updated from Enroll Request') return True
def rxOnMsgZoneChangedNotification(self, node, ep, cl, payload): attrList = self.m_zbHandle.doZoneChangedNotification(payload) if self.m_zbHandle.upsertAttribute(node, ep, cl, attrList): DBG('Attribute Updated from Zone Changed Notification') return True
def rxOnMsgReportAttribute(self, node, ep, cl, payload): attrList = self.m_zbHandle.doReportPayload(payload) if self.m_zbHandle.upsertAttribute(node, ep, cl, attrList): DBG('Attribute Updated from Report') return True