def handle_registration(self, stream, address):
        try:
            # receives the 21-byte registration info and proceeds.
            # Otherwise yield and keep waiting.
            message = yield stream.read_bytes(21)

            # unpacks the received bytes into phone number, IP addr.
            reg_data = struct.unpack('!I11scIc', message)
            phone = reg_data[1]

            logger.info('Registered device(%s)' % phone)

            # adds this new device into database.
            device = Device(18, phone, stream)
            session.add(device)
            session.commit()
            self.device_dict[device.portid] = device

        except Exception as e:
            logger.exception('Register device(%s) failed' % phone)
            logger.exception('In handle_registration %s' % e)
        else:
            logger.info('[Device list] %s' % self.device_dict.keys())
            device.colltype = 'R'
            self.handle_device(device)
    def handle_registration(self, stream, address):
        try:
            # receives the 21-byte registration info and proceeds.
            # Otherwise yield and keep waiting.
            message = yield stream.read_bytes(21)                  # 读取设备首次上报的信息(非阻塞化)

            # unpacks the received bytes into phone number, IP addr.
            reg_data = struct.unpack('!I11scIc',message)
            phone = reg_data[1]

            logger.info('Registered device(%s)' % phone)

            # adds this new device into database.
            device = Device(18, phone, stream)                     # 这3行用sqlalchemy将device信息存入数据库
            session.add(device)
            session.commit()
            self.device_dict[device.portid] = device               # 同时信息保存一份到device_dict

        except Exception as e:
            logger.exception('Register device(%s) failed' % phone) # 一旦注册这一步异常,则do nothing next
            logger.exception('In handle_registration %s' % e)
        else:
            logger.info('[Device list] %s' % self.device_dict.keys())
            device.colltype = 'R'
            self.handle_device(device)                             # 注册成功后的下一步操作
    def handle_device(self, device, chktime=None):
        action = device.colltype or 'R'
        cmd = None
        try:
            # get msg from rabbitmq.
            # process the msg.

            if action == 'R':
                timestamp = now()

                data = yield self.collect_data(device, 4)
                # Ensures we only store data in a interval of 1 minute.

                if not device.chktime or (timestamp.minute !=
                                          device.chktime.minute):
                    device.chktime = timestamp
                    logger.info("storing data")
                    #devdata = DeviceData(data)
                    #device.devdata.append(devdata)
                    #session.add(device)
                    #session.commit()

                logger.info('[Parsed data] %s' % data)
                delay = 60 - timestamp.second
                if delay > 55:
                    # This is only for keeping the connection alive.
                    # The data returned is not meant to be stored in database.
                    self.io_loop.call_later(55, self.handle_device, device)
                else:
                    self.io_loop.call_later(delay, self.handle_device, device)

            elif action == 'C':
                yield self.send_cmd(device, cmd)
                self.io_loop.add_callback(self.handle_device, device)

            elif action == 'H':
                chktime = chktime
                yield self.collect_data(device, 4, chktime=chktime)
                device.chktime = chktime
                # request history data from device right in the next iteration.
                #devdata = DeviceData(data)
                #device.devdata.append(devdata)
                #session.add(device)
                #session.commit()
                chktime += datetime.timedelta(0, 60, 0)
                self.io_loop.add_callback(self.handle_device, device, chktime)

        except Exception as e:
            logger.exception(str(e))
            raise e
    def handle_device(self, device, chktime=None):
        action = device.colltype or 'R'
        cmd = None
        try:
            # get msg from rabbitmq.
            # process the msg.

            if action == 'R':
                timestamp = now()

                data = yield self.collect_data(device, 4)
                # Ensures we only store data in a interval of 1 minute.

                if not device.chktime or (timestamp.minute != device.chktime.minute):
                    device.chktime = timestamp
                    logger.info("storing data")
                    #devdata = DeviceData(data)
                    #device.devdata.append(devdata)
                    #session.add(device)
                    #session.commit()

                logger.info('[Parsed data] %s' % data)
                delay = 60 - timestamp.second
                if delay > 55:
                    # This is only for keeping the connection alive.
                    # The data returned is not meant to be stored in database.
                    self.io_loop.call_later(55, self.handle_device, device)
                else:
                    self.io_loop.call_later(delay, self.handle_device, device)

            elif action == 'C':
                yield self.send_cmd(device, cmd)
                self.io_loop.add_callback(self.handle_device, device)

            elif action == 'H':
                chktime = chktime
                yield self.collect_data(device, 4, chktime=chktime)
                device.chktime = chktime
                # request history data from device right in the next iteration.
                #devdata = DeviceData(data)
                #device.devdata.append(devdata)
                #session.add(device)
                #session.commit()
                chktime += datetime.timedelta(0,60,0)
                self.io_loop.add_callback(self.handle_device, device, chktime)

        except Exception as e:
            logger.exception(str(e))
            raise e                       # 通过raise唤醒阻塞处,返回值给阻塞调用者,而不是用return
    def collect_data(self, device, data_type, interval=1, chktime=None):
        try:
            timestamp = now() if data_type == 4 and not chktime else chktime
            recv_frame = BitArray()
            request_frame = gen_collect_cmd_frame(device.devaddr, data_type,
                                                  interval, timestamp)

            # sends out the inqury command frame.
            yield device.stream.write(request_frame.bytes)

            # receives the first 4 leading bytes
            recv_bytes = yield device.stream.read_bytes(4)

            leading, head, remain_length = struct.unpack('!HBB', recv_bytes)
            recv_frame += hex(leading)
            recv_frame += hex(head)
            recv_frame += hex(remain_length)

            # receives the remaining bytes from device.
            remain_bytes = yield device.stream.read_bytes(remain_length)

            for byte in remain_bytes:
                recv_frame += BitArray(uint=ord(byte), length=8)

            # unpacks the binary data into a Python dict object
            frame_dict = unpack_frame(remain_bytes, DATA_LENGTHS[data_type])

            # parses those data bytes into JSON.
            data_json = parse_data(frame_dict['data'])

            logger.info('Received: %s' % recv_frame)

        except StreamClosedError:
            logger.exception('Device(%s) lost connection' % device.portid)
            self.device_dict.pop(device.portid)
        except Exception as e:
            logger.error('In collect_data %s' % str(e))
            self.device_dict.pop(device.portid)
            device.stream.close()
            device.online = False
        else:
            raise gen.Return(data_json)
    def collect_data(self, device, data_type, interval=1, chktime=None):
        try:
            timestamp = now() if data_type==4 and not chktime else chktime
            recv_frame = BitArray()
            request_frame = gen_collect_cmd_frame(device.devaddr, data_type,
                interval, timestamp)

            # sends out the inqury command frame.
            yield device.stream.write(request_frame.bytes)

            # receives the first 4 leading bytes
            recv_bytes = yield device.stream.read_bytes(4)

            leading, head, remain_length = struct.unpack('!HBB', recv_bytes)
            recv_frame += hex(leading)
            recv_frame += hex(head)
            recv_frame += hex(remain_length)

            # receives the remaining bytes from device.
            remain_bytes = yield device.stream.read_bytes(remain_length)

            for byte in remain_bytes:
                recv_frame += BitArray(uint=ord(byte), length=8)

            # unpacks the binary data into a Python dict object
            frame_dict = unpack_frame(remain_bytes, DATA_LENGTHS[data_type])

            # parses those data bytes into JSON.
            data_json = parse_data(frame_dict['data'])

            logger.info('Received: %s' % recv_frame)
            
        except StreamClosedError:
            logger.exception('Device(%s) lost connection' % device.portid)
            self.device_dict.pop(device.portid)
        except Exception as e:
            logger.error('In collect_data %s' % str(e))
            self.device_dict.pop(device.portid)
            device.stream.close()
            device.online = False
        else:
            raise gen.Return(data_json)
def main():
    puller = Puller()
    puller.listen(8777)
    logger.info('Starting Puller instance......')
    mainloop=ioloop.IOLoop.instance()
    mainloop.start()
 def handle_stream(self, stream, address):
     logger.info('New connection from %s' % str(address))
     self.handle_registration(stream, address)
Exemple #9
0
def main():
    puller = Puller()
    puller.listen(8777)
    logger.info('Starting Puller instance......')
    mainloop = ioloop.IOLoop.instance()
    mainloop.start()
 def handle_stream(self, stream, address):
     logger.info('New connection from %s' % str(address))
     self.handle_registration(stream, address)                  # 处理设备的首次连接,当注册