Ejemplo n.º 1
0
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.cfgs = {}
        self.accumulator = JsonDataAccumulator()

        self.conn = None
        self.session = None

        self.service = instance.serviceManager.get('main')
        # self.mongo = instance.datasourceManager.get('mongodb').conn
        # self.redis = instance.datasourceManager.get('redis').conn

        self.raw_file = None
        self.active = False  # 设备是否在线登录
        self.start_time = datetime.datetime.now()
        self.device_id = None
        self.redis = None
        self.device = None
        self.logger = None

        # self.packet_sequence = 0

        # self.device_iot_channel = None  # 发送到绿城家的通道
        self.iot_controller = None

        self.device_app_pub_channel = None
        self.command_controller = None
        self.queue = Queue()
        self.running = True
        self.peer_address = ''
        self.last_heartbeat = 0
        # self.msg_codec = MessageJsonStreamCodec()
        self.box = None
        self.device_type = ''
        self.channel_down = None
Ejemplo n.º 2
0
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.cfgs = {}
        self.accumulator = JsonDataAccumulator()

        self.conn = None
        self.session = None

        self.service = instance.serviceManager.get('main')
        self.mongo = instance.datasourceManager.get('mongodb').conn
        self.redis = instance.datasourceManager.get('redis').conn

        self.raw_file = None
        self.active = False  # 设备是否在线登录
        self.start_time = datetime.datetime.now()
        self.device_id = None
        self.redis = None
        self.device = None
        self.logger = None
        self.seq_gen = None  # RedisIdGenerator().init('')
        self.packet_sequence = 0

        self.device_app_pub_channel = None
        self.command_controller = None
        self.queue = Queue()
        self.running = True
        self.peer_address = ''
        self.last_heartbeat = 0
        # self.msg_codec = MessageJsonStreamCodec()
        self.box = None
        self.device_type = ''
        self.joined = False  # 是否已加入

        self.subscribed_ids = {}  # 已订阅设备编号
        self.app_id = str(time.time())
Ejemplo n.º 3
0
 def onConnected(self, conn, address):
     self.acc = JsonDataAccumulator()
     m = message.MessageAppSubscribe()
     m.authcode = authcode
     m.ids = ids
     conn.sendData(m.marshall())
     print '>> data sent: ', m.marshall()
Ejemplo n.º 4
0
class CallEventHandler(ConnectionEventHandler):
    """服务器被叫呼叫处理"""
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.conn = None
        self.accumulator = JsonDataAccumulator()

    def onConnected(self, conn, address):
        """连接成功,发送 call_keep 保活"""
        self.conn = conn
        print 'call connected ..'
        gevent.spawn(self.keepalive)

    def keepalive(self):
        """定时发送报活包"""
        while True:
            self.conn.sendData(message.MessageCallKeep().marshall())
            gevent.sleep(3)

    def onDisconnected(self, conn):
        print 'call disconnected ..'

    def onData(self, conn, data):
        print 'call onData ..'
        data_list = self.accumulator.enqueue(data)
        for data in data_list:
            msg = parseMessage(data)
            if isinstance(msg, message.MessageJoinAccept):
                pass
Ejemplo n.º 5
0
class ClientHandler(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.conn = None
        self.accumulator = JsonDataAccumulator()

    def onConnected(self,conn,address):
        print 'client connected ..'
        self.conn = conn
        # gevent.spawn(self.keepalive)

        # 连接成功,马上发送加入家庭
        msg = message.MessageJoinFamily()

        conn.sendData(msg.marshall())

    def keepalive(self):
        while True:
            self.conn.sendData(message.MessageCallKeep().marshall())
            gevent.sleep(3)

    def onDisconnected(self,conn):
        print 'client disconnected ..'

    def onData(self,conn,data):
        print '<< client onData ..'
        data_list = self.accumulator.enqueue(data)
        for data in data_list:
            msg = parseMessage(data)
            if isinstance(msg,message.MessageJoinAccept):
                # 加入成功马上发起呼叫
                gevent.spawn(self.call_out)

    def call_out(self):
        # 开始向外呼叫
        gevent.sleep(.5)

        msg = message.MessageCall()
        msg.src.id = '2-1-1-1'
        msg.src.type = message.CallPeerType.INNER_SCREEN
        msg.src.audio_stream_id = 5678

        msg.dest.ip = '127.0.0.1'
        msg.dest.port = PORT_CALL_PEER  #
        msg.dest.type = message.CallPeerType.OUTER_BOX
        msg.dest.video_stream_id = 5679

        print 'call out start..'
        self.conn.sendData(msg.marshall())

        gevent.spawn(self.call_keep)

    def call_keep(self):
        """呼叫保持"""
        gevent.sleep(3)
        self.conn.sendData(message.MessageCallKeep().marshall())
        gevent.spawn(self.call_keep)
Ejemplo n.º 6
0
class MyConnection(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.acc = None

    def onConnected(self, conn, address):
        self.acc = JsonDataAccumulator()
        m = message.MessageAppSubscribe()
        m.authcode = authcode
        m.ids = ids
        conn.sendData(m.marshall())
        print '>> data sent: ', m.marshall()

    def onData(self, conn, data):
        print '<< data in :', data
        messages = self.acc.enqueue(data)
        for m in messages:
            pass
Ejemplo n.º 7
0
class ClientHandler(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.conn = None
        self.accumulator = JsonDataAccumulator()
        self.status = ''

    def onConnected(self, conn, address):
        print 'innerbox Connected ..'
        self.conn = conn
        self.status = 'call_start'
        gevent.spawn(self.keepalive)
        self.conn.sendData(message.MessageCall().marshall())

    def keepalive(self):
        while self.status == 'call_start':
            self.conn.sendData(message.MessageCallKeep().marshall())
            gevent.sleep(3)

    def onDisconnected(self, conn):
        print 'client disconnected ..'
        self.status = 'call_end'

    def onData(self, conn, data):
        print 'client onData ..'
        data_list = self.accumulator.enqueue(data)
        for data in data_list:
            msg = parseMessage(data)
            print msg.name_
            if isinstance(msg, message.MessageJoinAccept):
                print 'Remote CallAccept'
            if isinstance(msg, message.MessageCallEnd):
                print 'Remote Call End'
                self.status = 'call_end'
            if isinstance(msg, message.MessageCallReject):
                print 'Remote Reject Call'
                self.status = 'call_end'
Ejemplo n.º 8
0
class SmartAdapter(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.cfgs = {}
        self.accumulator = JsonDataAccumulator()

        self.conn = None
        self.session = None

        self.service = instance.serviceManager.get('main')
        # self.mongo = instance.datasourceManager.get('mongodb').conn
        # self.redis = instance.datasourceManager.get('redis').conn

        self.raw_file = None
        self.active = False  # 设备是否在线登录
        self.start_time = datetime.datetime.now()
        self.device_id = None
        self.redis = None
        self.device = None
        self.logger = None

        # self.packet_sequence = 0

        # self.device_iot_channel = None  # 发送到绿城家的通道
        self.iot_controller = None

        self.device_app_pub_channel = None
        self.command_controller = None
        self.queue = Queue()
        self.running = True
        self.peer_address = ''
        self.last_heartbeat = 0
        # self.msg_codec = MessageJsonStreamCodec()
        self.box = None
        self.device_type = ''
        self.channel_down = None

    def init(self,**kwargs):
        self.cfgs.update(kwargs)
        # self.redis = instance.datasourceManager.get('redis').conn
        self.logger = instance.getLogger()

        # cls = import_class(self.cfgs.get('command_controller'))
        # self.command_controller = cls()

        self.broker = instance.messageBrokerManager.get('redis')

        gevent.spawn(self.messageProcessTask)

    def onConnected(self,conn,address):
        """连接上来"""
        self.logger.debug('device connected .  {}'.format(str(address)))
        self.conn = conn
        self.peer_address = address  # 连接上来的对方地址
        self.last_heartbeat = timestamp_current()

    def onDisconnected(self,conn):
        self.logger.debug('device  disconnected. {} {}'.format(self.device_type, self.device_id))
        self.active = False
        # self.raw_file.close()
        self.service.deviceOffline(self)
        self.running = False

        # 断开连接删除设备与接入服务器的映射
        # self.redis.delete(constants.DeviceServerRel.format(self.device_id))

        # if self.iot_controller:
        #     self.iot_controller.onDeviceDisconnected()
        if self.channel_down:
            self.channel_down.close()



    def onData(self,conn,data):
        self.logger.debug("<< Device Data Retrieve in . {} {}".format(self.device_id, self.device_type))
        self.logger.debug(data)
        json_text_list = self.accumulator.enqueue(data)

        # dump = self.hex_dump(bytes)
        # self.logger.debug("<< "+dump)
        # self.dump_hex_data(dump)

        for text in json_text_list:
            message = parseMessage(text)
            if message:
                self.queue.put([message, current_datetime_string()])

    def checkLogin(self,message):
        # from mantis.yinlian.dtu.token import device_token_check
        self.device_id = message.device_id
        return True

        # device = model.SmartDevice.get(id = message.device_id)
        # if not device :
        #     return False
        # secret = device.secret_key
        # data = device_token_check(message.token,secret)
        # if not data:
        #     return False
        # auth_time = data.get('auth_time',0)
        # self.device_id = data.get('id')
        # self.device_type = data.get('type')
        # TOKEN_VALID_TIME = self.service.getConfig().get('token_valid_time',300)
        # # 校验token是否已过期
        # if timestamp_current() - auth_time > TOKEN_VALID_TIME:
        #     instance.getLogger().error(u'过期无效token: ',message.token)
        #     return False
        #
        # return True

    def handleMessage(self,message):
        """ 处理来自设备上行的消息
        """
        # self.logger.debug( str( message.__class__ ))
        self.logger.debug('{} conn:{}'.format(str(message),str(self.conn)))
        # self.logger.debug(message.__class__.__name__+' device_type:{} device_id:{} message type:0x{:02x} '.format(self.device_type,self.device_id,message.Type.value))
        # self.logger.debug(
        #     message.__class__.__name__ + ' device_type:{} device_id:{} content: {} '.format(self.device_type,
        #                                                                                               self.device_id,
        #                                                                                               message.dict()))
        if isinstance(message,MessageHeartBeat):
            return self.handleHeartbeat(message)

        if 0 and  not self.active: # 设备未登陆
            if isinstance(message, MessageLogin): # 设备注册包
                if not self.checkLogin( message ):
                    self.logger.error('Login Info Check Failed.')
                    self.close()
                    return
                self.onActive() # 设备登陆注册
            else:
                self.logger.error('Device should Login first, socket connection dropped')
                self.close()
                return

        if not message.device_id:
            message.device_id = self.device_id
        # message.device_type = self.device_type

        # self.postMessageIoT(message)  # 将设备信息分发到 绿城+SDK --> iot

        # 发布到app接收通道
        device_id = message.device_id
        # name = constants.DeviceChannelPubTraverseUp.format(device_id=device_id)
        # 推入 本地 redis
        # self.broker.conn.publish(name, message.marshall(''))



        # if isinstance(message,MessageHeartBeat):
        #     self.handleHeartbeat(message)

        if isinstance(message,MessageDeviceStatus):
            self.handleDeviceStatus(message)

        # 推入平台消息总线
        if isinstance(message,MessageDeviceStatus):
            mx.put_message(message)

    def handleDeviceStatus(self,message):
        pass



    def handleHeartbeat(self,message):
        self.last_heartbeat = timestamp_current()
        if self.device:
            self.device.alive_time_s = datetime.datetime.now()
            self.device.alive_time = timestamp_current()
            self.device.save()


    def open(self):
        pass

    def setConnection(self,sock_conn):
        self.conn = sock_conn

    def close(self):
        self.running = False
        if self.conn:
            self.conn.close()


    def make_rawfile(self):
        fmt = '%Y%m%d_%H%M%S.%f'
        ts = time.time()
        name = time.strftime(fmt, time.localtime(ts)) + '.raw'
        name = os.path.join(instance.getDataPath(),name)
        self.raw_file = open(name,'w')


    def hex_dump(self,bytes):
        dump = ' '.join(map(lambda _:'%02x'%_, map(ord, bytes)))
        return dump


    def threadHeartbeat(self):
        """定时发送设备的心跳包"""
        sleep = self.cfgs.get('heartbeat', 10)
        while self.running:
            gevent.sleep( sleep )
            if not self.running:
                break
            self.traverseDown(MessageHeartBeat())

    def onTraverseMessage(self,data,ctx):
        """接收到平台服务发送的下行的消息,转发到下行的设备连接对端"""
        message = parseMessage(data)
        self.traverseDown(message)

    def subscribeTraverseDownMessage(self):
        """订阅下行控制命令"""
        broker = instance.messageBrokerManager.get('redis')
        name = constants.DeviceChannelPubTraverseDown.format(device_id = self.device_id)

        self.channel_down = broker.createPubsubChannel(name, self.onTraverseMessage)
        self.channel_down.open()

    def onActive(self):
        """设备在线登录, 订阅本设备下行的消息"""
        self.logger.debug('device onActive. {} {}'.format(self.device_type, self.device_id))
        self.active = True
        gevent.spawn(self.threadHeartbeat)  # 定时心跳发送

        # access_url = self.service.getConfig().get('access_api_url')     #暴露给外部调用的web接口,接收命令控制
        # self.redis.set( constants.DeviceAccessHttpAPI.format(self.device_id),access_url)
        #
        # device = model.SmartDevice.get(id = self.device_id)
        # if device:
        #     self.device = device
        # else:
        #     self.logger.error('device not register',self.device_id)
        #     self.close()
        #     return
        #
        # CHECK_ACTIVE = False
        # if CHECK_ACTIVE:
        #     if not device.active_time:  # 未激活
        #         self.logger.error('device not actived.',self.device_id)
        #         self.close()
        #         return
        #
        # device.alive_time = timestamp_current()
        # device.save()

        self.service.deviceOnline(self)
        self.subscribeTraverseDownMessage()

        # 设备上线,即刻发送设备状态查询
        self.traverseDown(MessageDeviceStatusQuery())

        # todo. 发送设备上线 事件 到平台总线


    def traverseDown(self,message):
        """转发设备下行消息"""
        self.conn.sendData(message.marshall())

        if isinstance(message, MessageDeviceValueSet):
            pass
            # log = model.LogDeviceValueSet()
            # log.device_id = self.device_id
            # log.sys_time = timestamp_current()
            # log.param_name = message.param_name
            # log.param_value = message.param_value
            # log.save()

    def messageProcessTask(self):
        """处理设备上报消息的工作队列"""
        while self.running:
            # 长久没有心跳包
            if timestamp_current() - self.last_heartbeat > 60*5:
                self.logger.warn('Heartbeat Lost. Close socket. {} {} '.format(self.device_id, self.device_type))
                self.close()
                break
            try:
                message,date = self.queue.get(block=True, timeout=1)
                try:
                    self.logger.debug('message pop from queue: {} {}  {} {}'.format(date,message.__class__.__name__,self.device_id,self.device_type))
                    self.handleMessage(message)
                except:
                    self.logger.warn(traceback.print_exc())
                    self.close()
                    break
            except:pass

        # todo. 此处发送设备 断开的事件 到平台总线
        self.logger.warn('messageTask() exiting.. {} {} '.format(self.device_id, self.device_type))
Ejemplo n.º 9
0
class AppAdapter(ConnectionEventHandler):
    """app接入流服务"""
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.cfgs = {}
        self.accumulator = JsonDataAccumulator()

        self.conn = None
        self.session = None

        self.service = instance.serviceManager.get('main')
        self.mongo = instance.datasourceManager.get('mongodb').conn
        self.redis = instance.datasourceManager.get('redis').conn

        self.raw_file = None
        self.active = False  # 设备是否在线登录
        self.start_time = datetime.datetime.now()
        self.device_id = None
        self.redis = None
        self.device = None
        self.logger = None
        self.seq_gen = None  # RedisIdGenerator().init('')
        self.packet_sequence = 0

        self.device_app_pub_channel = None
        self.command_controller = None
        self.queue = Queue()
        self.running = True
        self.peer_address = ''
        self.last_heartbeat = 0
        # self.msg_codec = MessageJsonStreamCodec()
        self.box = None
        self.device_type = ''
        self.joined = False  # 是否已加入

        self.subscribed_ids = {}  # 已订阅设备编号
        self.app_id = str(time.time())

    def init(self, **kwargs):
        self.cfgs.update(kwargs)
        self.redis = instance.datasourceManager.get('redis').conn
        self.logger = instance.getLogger()
        gevent.spawn(self.messageProcessTask)

        self.initBroker()

    def onDeviceTraverseUpMessage(self, message, ctx):
        """接收到投递过来的设备状态消息,转发到当前 tcp 通道"""
        from mantis.fanbei.smarthome.message import MessageSensorStatus, parseMessage
        message = parseMessage(message)

        if not isinstance(message, MessageSensorStatus):
            self.logger.error("Message From Redis is Not MessageSensorStatus.")
            return
        self.traverseDown(message)

    def initBroker(self):
        self.broker = instance.messageBrokerManager.get('redis')

    def onConnected(self, conn, address):
        """连接上来 , 等待app发送join请求,超时 10s 断开连接 """
        self.logger.debug('app connected .  {}'.format(str(address)))
        self.conn = conn
        self.peer_address = address  # 连接上来的对方地址
        self.last_heartbeat = timestamp_current()
        # gevent.spawn_later(self.checkLogin,10)
        gevent.spawn(self.checkLogin)

    def checkLogin(self):
        """检查是否已发起订阅"""
        gevent.sleep(100)
        if not self.subscribed_ids:
            print 'App Subscribe Timeout , destroy connection..'
            self.close()

    def onDisconnected(self, conn):
        self.logger.debug('App  disconnected. {} {}'.format(
            self.device_type, self.device_id))
        self.active = False
        # self.raw_file.close()

        for id, channel in self.subscribed_ids.items():
            # channel = self.subscribed_ids.get(id_)
            if channel:
                channel.close()  # 关闭订阅
                # del self.subscribed_ids[id_]

        self.service.appOffline(self)
        self.running = False
        self.subscribed_ids = {}

    def onData(self, conn, data):
        self.logger.debug("app data retrieve in . " + data)
        json_text_list = self.accumulator.enqueue(data)

        # dump = self.hex_dump(bytes)
        # self.logger.debug("<< "+dump)
        # self.dump_hex_data(dump)

        for text in json_text_list:
            message = parseMessage(text)
            if message:
                self.queue.put([message, current_datetime_string()])

    def handleMessage(self, message):
        """ 处理来自设备上行的消息
        """

        if isinstance(message, MessageAppHeartbeat):
            return self.handleHeartbeat(message)

        if isinstance(message, MessageAppSubscribe):
            self.handleSubscribe(message)

        if isinstance(message, MessageAppUnSubscribe):
            self.handleUnSubscribe(message)

    def subscribeDevice(self, device_id):
        channelname = constants.DeviceChannelPubTraverseUp.format(
            device_id=device_id)
        channel = self.broker.createPubsubChannel(
            channelname, self.onDeviceTraverseUpMessage)
        channel.open()
        return channel

    def getAutchDeviceIds(self, authcode):
        """从redis读取授权的设备编码, 多个设备编码以 , 分隔"""
        name = constants.AppRequestAuthCodeWidthIdsPrefix + authcode
        value = self.redis.get(name)
        ids = str(value).split(',')
        return ids

    def handleSubscribe(self, message):
        # return
        authed_ids = self.getAutchDeviceIds(message.authcode)

        for id_ in message.ids:
            if id_ not in authed_ids:
                continue

            if not self.subscribed_ids.has_key(id_):
                channel = self.subscribeDevice(id_)
                self.subscribed_ids[id_] = channel

    def handleUnSubscribe(self, message):
        for id_ in message.ids:
            channel = self.subscribed_ids.get(id_)
            if channel:
                channel.close()  # 关闭订阅
                del self.subscribed_ids[id_]

    def handleHeartbeat(self, message):
        self.last_heartbeat = timestamp_current()

    def open(self):
        pass

    def setConnection(self, sock_conn):
        self.conn = sock_conn

    def close(self):
        self.running = False
        if self.conn:
            self.conn.close()

    def make_rawfile(self):
        fmt = '%Y%m%d_%H%M%S.%f'
        ts = time.time()
        name = time.strftime(fmt, time.localtime(ts)) + '.raw'
        name = os.path.join(instance.getDataPath(), name)
        self.raw_file = open(name, 'w')

    def hex_dump(self, bytes):
        dump = ' '.join(map(lambda _: '%02x' % _, map(ord, bytes)))
        return dump

    def traverseDown(self, message):
        """转发设备下行消息"""
        if self.conn:
            self.conn.sendData(message.marshall())

    def messageProcessTask(self):
        """处理设备上报消息的工作队列"""
        while self.running:
            # 长久没有心跳包
            if timestamp_current() - self.last_heartbeat > 60 * 5:
                self.logger.warn('Heartbeat Lost. Close socket. {} {} '.format(
                    self.device_id, self.device_type))
                self.close()
                break
            try:
                message, date = self.queue.get(block=True, timeout=1)
                try:
                    self.logger.debug(
                        'message pop from queue: {} {}  {} {}'.format(
                            date, message.__class__.__name__, self.device_id,
                            self.device_type))

                    self.handleMessage(message)
                except:
                    self.logger.warn(traceback.print_exc())
                    self.close()
                    break
            except:
                pass

        self.logger.warn('messageTask() exiting.. {} {} '.format(
            self.device_id, self.device_type))
Ejemplo n.º 10
0
 def __init__(self):
     ConnectionEventHandler.__init__(self)
     self.conn = None
     self.accumulator = JsonDataAccumulator()
Ejemplo n.º 11
0
class SmartAdapter(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.cfgs = {}
        self.accumulator = JsonDataAccumulator()

        self.conn = None
        self.session = None

        self.service = instance.serviceManager.get('main')
        self.mongo = instance.datasourceManager.get('mongodb').conn
        self.redis = instance.datasourceManager.get('redis').conn

        self.raw_file = None
        self.active = False  # 设备是否在线登录
        self.start_time = datetime.datetime.now()
        self.device_id = None
        self.redis = None
        self.device = None
        self.logger = None
        self.seq_gen = None  # RedisIdGenerator().init('')
        self.packet_sequence = 0

        # self.device_iot_channel = None  # 发送到绿城家的通道
        self.iot_controller = None

        self.device_app_pub_channel = None
        self.command_controller = None
        self.queue = Queue()
        self.running = True
        self.peer_address = ''
        self.last_heartbeat = 0
        # self.msg_codec = MessageJsonStreamCodec()
        self.box = None
        self.device_type = ''
        self.channel_down = None

    def init(self, **kwargs):
        self.cfgs.update(kwargs)
        self.redis = instance.datasourceManager.get('redis').conn
        self.logger = instance.getLogger()
        # self.seq_gen = RedisIdGenerator().init(self.cfgs.get('sequence_key'))

        # cls = import_class(self.cfgs.get('command_controller'))
        # self.command_controller = cls()

        self.broker = instance.messageBrokerManager.get('redis')

        gevent.spawn(self.messageProcessTask)

    def onConnected(self, conn, address):
        """连接上来"""
        self.logger.debug('device connected .  {}'.format(str(address)))
        self.conn = conn
        self.peer_address = address  # 连接上来的对方地址
        self.last_heartbeat = timestamp_current()

    def onDisconnected(self, conn):
        self.logger.debug('device  disconnected. {} {}'.format(
            self.device_type, self.device_id))
        self.active = False
        # self.raw_file.close()
        self.service.deviceOffline(self)
        self.running = False

        # 断开连接删除设备与接入服务器的映射
        self.redis.delete(constants.DeviceServerRel.format(self.device_id))

        # if self.iot_controller:
        #     self.iot_controller.onDeviceDisconnected()
        if self.channel_down:
            self.channel_down.close()

    def onData(self, conn, data):
        self.logger.debug("<< Device Data Retrieve in . {} {}".format(
            self.device_id, self.device_type))
        self.logger.debug(data)
        json_text_list = self.accumulator.enqueue(data)

        # dump = self.hex_dump(bytes)
        # self.logger.debug("<< "+dump)
        # self.dump_hex_data(dump)

        for text in json_text_list:
            message = parseMessage(text)
            if message:
                self.queue.put([message, current_datetime_string()])

    def checkLogin(self, message):
        from mantis.fanbei.smarthome.token import device_token_check

        device = model.SmartDevice.get(id=message.device_id)
        if not device:
            return False
        secret = device.secret_key
        data = device_token_check(message.token, secret)
        if not data:
            return False
        auth_time = data.get('auth_time', 0)
        self.device_id = data.get('id')
        self.device_type = data.get('type')
        TOKEN_VALID_TIME = self.service.getConfig().get(
            'token_valid_time', 300)
        # 校验token是否已过期
        if timestamp_current() - auth_time > TOKEN_VALID_TIME:
            instance.getLogger().error(u'过期无效token: ', message.token)
            return False

        return True

    def handleMessage(self, message):
        """ 处理来自设备上行的消息
        """
        # self.logger.debug( str( message.__class__ ))
        self.logger.debug('{} conn:{}'.format(str(message), str(self.conn)))
        # self.logger.debug(message.__class__.__name__+' device_type:{} device_id:{} message type:0x{:02x} '.format(self.device_type,self.device_id,message.Type.value))
        # self.logger.debug(
        #     message.__class__.__name__ + ' device_type:{} device_id:{} content: {} '.format(self.device_type,
        #                                                                                               self.device_id,
        #                                                                                               message.dict()))
        if isinstance(message, MessageHeartBeat):
            return self.handleHeartbeat(message)

        if not self.active:  # 设备未登陆
            if isinstance(message, MessageLogin):  # 设备注册包
                if not self.checkLogin(message):
                    self.logger.error('Login Info Check Failed.')
                    self.close()
                    return
                self.onActive()  # 设备登陆注册
            else:
                self.logger.error(
                    'Device should Login first, socket connection dropped')
                self.close()
                return

        message.device_id = self.device_id
        # message.device_type = self.device_type

        # self.postMessageIoT(message)  # 将设备信息分发到 绿城+SDK --> iot

        # 发布到app接收通道
        device_id = message.device_id
        name = constants.DeviceChannelPubTraverseUp.format(device_id=device_id)
        self.broker.conn.publish(name, message.marshall(''))

        # if isinstance(message,MessageHeartBeat):
        #     self.handleHeartbeat(message)

        if isinstance(message, MessageDeviceStatus):
            self.handleDeviceStatus(message)

        if isinstance(message, MessageSensorStatus):
            self.handleSensorStatus(message)

        if isinstance(message, MessageDeviceLogInfo):
            self.handleDeviceLogInfo(message)

    def handleDeviceStatus(self, message=MessageDeviceStatus()):
        """ 注意: 包括 家庭模式 """
        import base64
        profile = message.params.get('profile', '')
        if profile:
            profile = base64.decodestring(profile)
            self.device.profile = profile
            self.device.save()
            return

        self.device.assign(message.values())
        self.device.alive_time = timestamp_current()
        self.device.save()

        # 写入 redis
        name = constants.DeviceStatusHash.format(self.device_id)
        data = hash_object(self.device)
        self.redis.hmset(name, data)

        # 写入日志
        log = model.LogDeviceStatus()
        log.device_id = self.device_id
        log.sys_time = timestamp_current()
        log.assign(message.params)
        # log.host_ver = message.host_ver
        # log.mcu_ver = message.mcu_ver
        # log.status_time = message.status_time
        # log.boot_time = message.boot_time
        log.save()

    def handleSensorStatus(self, message=MessageSensorStatus()):
        # 写入 redis 记录设备当前最新的状态值
        name = constants.SensorStatusHash.format(
            device_id=self.device_id,
            sensor_type=message.sensor_type,
            sensor_id=message.sensor_id)
        data = message.params
        self.redis.hmset(name, data)

        # 发布到华为iot
        # self.iot_controller.onMessageSensorStatus( message )

        sensor = model.Sensor.get(device_id=message.device_id,
                                  id=message.sensor_id,
                                  type=message.sensor_type)
        if not sensor:
            sensor = model.Sensor()
            sensor.id = message.sensor_id
            sensor.type = message.sensor_type
            sensor.device_id = message.device_id
        params = {}
        if sensor.params:  # 合并新老的状态参数值
            try:
                params = json.loads(sensor.params)
                params.update(params)
            except:
                pass

        params.update(message.params)
        jsondata = json.dumps(params)
        sensor.params = jsondata
        sensor.save()

        # 写入日志
        log = model.LogSensorStatus()
        log.device_id = self.device_id
        log.sys_time = timestamp_current()
        log.sensor_id = message.sensor_id
        log.sensor_type = message.sensor_type
        log.datetime = datetime.datetime.now()
        log.assign(message.params)
        # log.params = json.dumps( message.params )
        log.save()

    def handleDeviceLogInfo(self, message=MessageDeviceLogInfo()):
        log = model.LogDeviceLogInfo()
        log.device_id = self.device_id
        log.sys_time = timestamp_current()
        log.device_time = message.time
        log.content = message.content
        log.save()

    def handleHeartbeat(self, message):
        self.last_heartbeat = timestamp_current()

        # bytes = message.response()
        # self.conn.sendData(bytes)
        #
        # # 更新设备最新的状态和位置信息到Redis
        # data = message.dict()
        # self.update_device_in_cache(data)

    def postMessageIoT(self, message):
        # 设备登陆上线和状态需发送给绿城+ SDK
        return
        if not isinstance(message, (MessageSensorStatus, MessageLogin)):
            return

        m = None
        if isinstance(message, MessageSensorStatus):
            m = iot_message.MessageSensorStatus()
            m.device_id = message.device_id
            m.sensor_id = message.sensor_id
            m.sensor_type = message.sensor_type
            m.params = message.params
        if m:
            self.device_iot_channel.publish_or_produce(message.marshall(''))

        # # 写入日志数据库
        # dbname = 'ismart_device_log'
        # coll = self.mongo[dbname][self.device_id]
        # coll.insert_one(data)

    def open(self):
        pass

    def setConnection(self, sock_conn):
        self.conn = sock_conn

    def close(self):
        self.running = False
        if self.conn:
            self.conn.close()

    def make_rawfile(self):
        fmt = '%Y%m%d_%H%M%S.%f'
        ts = time.time()
        name = time.strftime(fmt, time.localtime(ts)) + '.raw'
        name = os.path.join(instance.getDataPath(), name)
        self.raw_file = open(name, 'w')

    def hex_dump(self, bytes):
        dump = ' '.join(map(lambda _: '%02x' % _, map(ord, bytes)))
        return dump

    def threadHeartbeat(self):
        """定时发送设备的心跳包"""
        sleep = self.cfgs.get('heartbeat', 10)
        while self.running:
            gevent.sleep(sleep)
            if not self.running:
                break
            self.traverseDown(MessageHeartBeat())

    def onTraverseMessage(self, data, ctx):
        """接收到平台服务发送的下行的消息,转发到下行的设备连接对端"""
        message = parseMessage(data)
        self.traverseDown(message)

    def subscribeTraverseDownMessage(self):
        """订阅下行控制命令"""
        broker = instance.messageBrokerManager.get('redis')
        name = constants.DeviceChannelPubTraverseDown.format(
            device_id=self.device_id)

        self.channel_down = broker.createPubsubChannel(name,
                                                       self.onTraverseMessage)
        self.channel_down.open()

    def onActive(self):
        """设备在线登录, 订阅本设备下行的消息"""
        self.logger.debug('device onActive. {} {}'.format(
            self.device_type, self.device_id))
        self.active = True
        gevent.spawn(self.threadHeartbeat)  # 定时心跳发送

        access_url = self.service.getConfig().get(
            'access_api_url')  #暴露给外部调用的web接口,接收命令控制
        self.redis.set(constants.DeviceAccessHttpAPI.format(self.device_id),
                       access_url)

        # 记录设备由哪个sever接入的
        # service_id = self.service.getConfig().get('id')
        # self.redis.hset(constants.DeviceServerRel,self.device_id,service_id)

        device = model.SmartDevice.get(id=self.device_id)
        if device:
            self.device = device
        else:
            self.logger.error('device not register', self.device_id)
            self.close()
            return

        CHECK_ACTIVE = False
        if CHECK_ACTIVE:
            if not device.active_time:  # 未激活
                self.logger.error('device not actived.', self.device_id)
                self.close()
                return

        device.alive_time = timestamp_current()
        device.save()

        self.service.deviceOnline(self)

        self.subscribeTraverseDownMessage()
        # 创建到华为iot的通道
        # self.iot_controller = iot.IotController(self)
        # self.iot_controller.onActive()

        # 设备上线,即刻发送设备状态查询
        self.traverseDown(MessageDeviceStatusQuery())

        # 要求设备返回所有状态 20190630
        msg_sensor_query = MessageSensorStatusQuery()
        msg_sensor_query.sensor_type = 0
        msg_sensor_query.sensor_id = 0
        self.traverseDown(msg_sensor_query)

        # 发送设备profile上报请求
        msg_upload_profile = MessageDeviceCommand()
        msg_upload_profile.command = 'upload_profile'
        self.traverseDown(msg_upload_profile)

    def traverseDown(self, message):
        """转发设备下行消息"""
        self.conn.sendData(message.marshall())

        if isinstance(message, MessageDeviceValueSet):
            log = model.LogDeviceValueSet()
            log.device_id = self.device_id
            log.sys_time = timestamp_current()
            log.param_name = message.param_name
            log.param_value = message.param_value
            log.save()

        if isinstance(message, MessageSensorValueSet):
            log = model.LogSensorValueSet()
            log.device_id = self.device_id
            log.sensor_id = message.sensor_id
            log.sensor_type = message.sensor_type
            log.sys_time = timestamp_current()
            log.param_name = message.param_name
            log.param_value = message.param_value
            log.save()

    def messageProcessTask(self):
        """处理设备上报消息的工作队列"""
        while self.running:
            # 长久没有心跳包
            if timestamp_current() - self.last_heartbeat > 60 * 5:
                self.logger.warn('Heartbeat Lost. Close socket. {} {} '.format(
                    self.device_id, self.device_type))
                self.close()
                break
            try:
                message, date = self.queue.get(block=True, timeout=1)
                try:
                    self.logger.debug(
                        'message pop from queue: {} {}  {} {}'.format(
                            date, message.__class__.__name__, self.device_id,
                            self.device_type))

                    self.handleMessage(message)
                except:
                    self.logger.warn(traceback.print_exc())
                    self.close()
                    break
            except:
                pass

        self.logger.warn('messageTask() exiting.. {} {} '.format(
            self.device_id, self.device_type))
Ejemplo n.º 12
0
class ClientHandler(ConnectionEventHandler):
    def __init__(self):
        ConnectionEventHandler.__init__(self)
        self.conn = None
        self.accumulator = JsonDataAccumulator()
        self.status = 'call_start'

    def onConnected(self, conn, address):
        print 'client connected ..'
        self.conn = conn
        # gevent.spawn(self.keepalive)

        # 连接成功,马上发送加入家庭
        msg = message.MessageJoinFamily()

        conn.sendData(msg.marshall())

    def keepalive(self):
        while True:
            self.conn.sendData(message.MessageCallKeep().marshall())
            gevent.sleep(3)

    def onDisconnected(self, conn):
        print 'client disconnected ..'

    def onData(self, conn, data):
        print '<< client onData ..'
        data_list = self.accumulator.enqueue(data)
        for data in data_list:
            msg = parseMessage(data)
            print msg.name_
            if isinstance(msg, message.MessageJoinAccept):
                # 加入成功马上发起呼叫
                print 'Box Join Accepted. Waiting for Call in ..'
                # gevent.spawn(self.call_out)
            if isinstance(msg, message.MessageCall):
                print 'Remote Call in..'
                print data
                gevent.spawn(self.pick_up)
                # gevent.spawn(self.reject)
                # gevent.spawn(self.call_keep)
            if isinstance(msg, message.MessageCallEnd):
                self.status = 'call_end'

    def reject(self):
        gevent.sleep(3)
        print 'Reject Call..'
        self.conn.sendData(message.MessageCallReject().marshall())

    def pick_up(self):
        """接听"""
        if sys.argv[-1] != 'accept':
            return

        gevent.sleep(random.randint(0, 5))
        # if random.randint(0,5) % 2 == 0: #随机接听
        if True:  #随机接听
            print "Pick up Call .."
            self.conn.sendData(message.MessageCallAccept().marshall())
            self.status = 'call_start'
            gevent.spawn(self.process_call_in)
            gevent.sleep(2)
            print 'OpenDoor ordering..'
            self.conn.sendData(message.MessageOpenDoor().marshall())

    def process_call_in(self):
        # 模拟呼叫持续过程
        gevent.sleep(5)
        print 'Hang Up ..'
        # 模拟挂断通话
        self.conn.sendData(message.MessageCallEnd().marshall())
        self.status = 'call_end'

    def call_keep(self):
        """呼叫保持"""
        gevent.sleep(3)
        if self.status == 'call_start':
            print 'send call_keep to peer..'
            self.conn.sendData(message.MessageCallKeep().marshall())
            gevent.spawn(self.call_keep)
        else:
            print 'stop call_keep send..'