def _decode(raw_value: bytes) -> Tuple[float, Quality]: raw_value, _ = raw_value if len(raw_value) != 8: raise ValueError('raw_value out of supported length') seconds = s_unpack('!I', raw_value[:4])[0] # TODO Fraction seems to be wrong fraction = s_unpack('!I', b'\x00' + raw_value[4:7])[0] quality = Quality(raw_value=raw_value[7:8]) return float(str(f'{seconds}.{fraction}')), quality
def _decode(raw_value: bytes) -> int: if len(raw_value) == 1: return s_unpack('!b', raw_value)[0] elif len(raw_value) == 2: return s_unpack('!h', raw_value)[0] elif len(raw_value) == 4: return s_unpack('!i', raw_value)[0] elif len(raw_value) == 8: return s_unpack('!q', raw_value)[0] raise ValueError('Signed integer out of supported range')
def _decode(raw_value: bytes) -> int: if len(raw_value) == 1: return s_unpack('!B', raw_value)[0] elif len(raw_value) == 2: return s_unpack('!H', raw_value)[0] # elif len(raw_value) == 3: # # NOTE regular MMS does not have 24 bits unsigned int # # NOTE 24 bits unsigned int seems to be used only for timestamp # return s_unpack('!I', b'\x00' + raw_value)[0] elif len(raw_value) == 4: return s_unpack('!I', raw_value)[0] raise ValueError('Unsigned integer out of supported range')
def unpack(self, bytearray): lower_offset = 0 upper_offset = 0 # unpack pressure upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.pressure = s_unpack("d", bytes)[0] # unpack temperature upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.temperature = s_unpack("d", bytes)[0]
def process_response(self): """ gevent读事件的监听回调处理,用于读取数据 """ try: now_data = self._recv(8192) if not now_data: # 如果读取的数据为空,那么socket已经断开了 self.close() return except: ex = sys.exc_info()[1] # 获取异常对象 error_no = ex.args[0] # 获取错误代码 sys.exc_clear() # 当前是在主协程中运行,这里直接清理掉异常信息 if error_no not in (EWOULDBLOCK, EAGAIN): self.close() # 一般情况下是一些reset关闭啥的 return # 根本就没有数据可以处理,还搞毛啊,直接返回 self._now_data += now_data # 将读取的数据保存起来 self._recv_ping_time = 0 # 重置心跳标志为 while 1: if self._status == 1 and len(self._now_data) >= 4: # 当前状态还需要读取数据的头部 body_len_data = self._now_data[:4] # 获取4个字节长度的头部 self._body_len, = s_unpack("i", body_len_data) # 计算数据body应该有的长度 self._now_data = self._now_data[4:] # 将4个字节的头部从数据中移除 if self._body_len == -1: # 这里如果数据包的长度为-1,那么就是心跳数据 continue # 这里直接略过 self._status = 2 # 更改状态标志 elif self._status == 2 and len(self._now_data) >= self._body_len: response_data = self._now_data[:self._body_len] # 这个就是客户端发送过来的数据 self._now_data = self._now_data[self._body_len:] # 将输入数据清除 self._status = 1 # 恢复状态标志为 rid, message = cp_loads(response_data) if rid in self._events: # 找到当前返回数据对应的event self._events[rid].set(message) # 找到对应挂起的事件,然后设置,唤醒挂起的协程 else: break
def unpack(self,bytearray): lower_offset = 0 upper_offset = 0 # unpack accx upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.accx = s_unpack("d",bytes)[0] # unpack accy upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.accy = s_unpack("d",bytes)[0] # unpack accz upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.accz = s_unpack("d",bytes)[0]
def unpack(self,bytearray): lower_offset = 0 upper_offset = 0 # unpack position upper_offset += self.position.getSize() bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.position.unpack(bytes) # unpack age upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.age = s_unpack("Q",bytes)[0] # unpack sats upper_offset += 2 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.sats = s_unpack("h",bytes)[0]
def unpack(self, bytearray): lower_offset = 0 upper_offset = 0 # unpack lat upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.lat = s_unpack("d", bytes)[0] # unpack lon upper_offset += 8 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.lon = s_unpack("d", bytes)[0] # unpack alt upper_offset += 4 bytes = bytearray[lower_offset:upper_offset] lower_offset = upper_offset self.alt = s_unpack("f", bytes)[0]
def unpack(self, octets): '''Return a 2-tuple (val, octets), the value unpacked from binary string `octets`, and the trailing octets not unpacked, respectively. If :attr:`sfmt` is None then this method MUST be overridden. Raise :class:`ValueError` or :class:`TypeError` if a value of this type cannot be unpacked from `octets`. ''' if self.sfmt is None: raise NotImplementedError() sfmt = '>' + self.sfmt return (s_unpack(sfmt, octets)[0], octets[s_size(sfmt):])
def _decode(self, raw_value: bytes) -> Tuple[bool, bool, bool, int]: if not isinstance(raw_value, bytes): raise_type('raw_value', bytes, type(raw_value)) if len(raw_value) != 1: raise ValueError('raw_value out of supported length') bits = s_unpack('!B', raw_value)[0] time_accuracy = bits & 0x1F if time_accuracy > 24 and time_accuracy != 0x1F: raise ValueError('bits out of supported range') leap_seconds_known = (bits & 0x80) == 0x80 clock_failure = (bits & 0x40) == 0x40 clock_not_synchronized = (bits & 0x20) == 0x20 return leap_seconds_known, clock_failure, clock_not_synchronized, time_accuracy
def unpack(self, fmt): """Unpack wrapper for automatic extraction of given format Arguments: fmt - Format of bytes to read (see struct.unpack)""" from struct import calcsize, unpack as s_unpack fmt_size = calcsize(fmt) data = self.read(fmt_size) if len(data) != fmt_size: exception = "Format mismatch: Tried to unpack {} bytes but got {}" raise IOError(exception.format(fmt_size, len(data))) ret = s_unpack(fmt, data) if len(ret) == 1: return ret[0] return ret
def process(self): """ 因为启动了当前socket的读监听,所以在有数据可以读取的时候,会调用这个方法来处理 这里要做的事情就是读取出来数据然后处理 注意:因为这个回调直接就是watcher的回调,是在loop协程上运行的,不能够阻塞loop协程,所以 数据包解析出来之后服务的调用都需要派发到别的协程中运行 注意:这里并没有不断的读取数据直到将数据全部读取完,因为默认水平触发,这样子可以降低一些recv系统调用的次数 """ try: now_data = self._recv(8192) # 这里直接从底层的socket读取数据 if not now_data: # 如果读取的数据为空,那么socket已经断开了 self.close() # 关闭当前的连接 return except: ex = sys.exc_info()[1] # 获取异常对象 error_no = ex.args[0] # 错误号码 sys.exc_clear() # 当前是在主协程中运行,这里直接清理掉异常信息 if error_no not in (EWOULDBLOCK, EAGAIN): # 这里判断一下是不是正常的异常情况 self.close() # 一般情况下是一些reset关闭啥的 return # 根本就没有数据可以处理,直接返回 self._now_data += now_data # 将刚刚收到的数据拼起来 self._recv_ping_time = 0 # 只要有数据来了就可以将心跳标志为设置为0了 while 1: if self._status == 1 and len(self._now_data) >= HEAD_LEN: # 当前为接收header的状态 body_len_data = self._now_data[0:HEAD_LEN] # 获取头部数据 self._body_len, = s_unpack("i", body_len_data) # 相应数据的body的长度 self._now_data = self._now_data[HEAD_LEN:] # 将头部数据移除 if self._body_len == -1: # 心跳包,长度直接为-1 continue # 心跳数据 self._status = 2 # 更改状态标志,接下来读取body elif self._status == 2 and len(self._now_data) >= self._body_len: # 读取body的数据 input_data = self._now_data[0:self._body_len] # 这个就是客户端发送过来的数据 self._now_data = self._now_data[self._body_len:] # 将输入数据清除 self._status = 1 # 恢复状态标志为,下次就再次读取头部 """ 注意:因为python本身并没有段作用域这种事说法,所以在构建异步执行的时候一定要非常小心 如果在异步执行的任务中直接引用外部闭包的变量,有可能会有一致性的问题,尤其是在循环内部, 外部的闭包变量可能已经更改,等到异步执行的时候,它所引用的变量也就更改了,从而导致 逻辑上的不正确 这里解决方案就是直接造再重新构建一层闭包,将外部变量重新包到新的闭包环境中去 """ run_task(self._generate_task(input_data)) # 将任务派发到协程池中运行 else: break # 数据还无法处理,那么跳出循环
def process_response(self): """ gevent读事件的监听回调处理,用于读取数据 """ try: now_data = self._recv(8192) if not now_data: # 如果读取的数据为空,那么socket已经断开了 self.close() return except: ex = sys.exc_info()[1] # 获取异常对象 error_no = ex.args[0] # 获取错误代码 sys.exc_clear() # 当前是在主协程中运行,这里直接清理掉异常信息 if error_no not in (EWOULDBLOCK, EAGAIN): self.close() # 一般情况下是一些reset关闭啥的 return # 根本就没有数据可以处理,还搞毛啊,直接返回 self._now_data += now_data # 将读取的数据保存起来 self._recv_ping_time = 0 # 重置心跳标志为 while 1: if self._status == 1 and len( self._now_data) >= 4: # 当前状态还需要读取数据的头部 body_len_data = self._now_data[:4] # 获取4个字节长度的头部 self._body_len, = s_unpack("i", body_len_data) # 计算数据body应该有的长度 self._now_data = self._now_data[4:] # 将4个字节的头部从数据中移除 if self._body_len == -1: # 这里如果数据包的长度为-1,那么就是心跳数据 continue # 这里直接略过 self._status = 2 # 更改状态标志 elif self._status == 2 and len(self._now_data) >= self._body_len: response_data = self._now_data[:self. _body_len] # 这个就是客户端发送过来的数据 self._now_data = self._now_data[self._body_len:] # 将输入数据清除 self._status = 1 # 恢复状态标志为 rid, message = cp_loads(response_data) if rid in self._events: # 找到当前返回数据对应的event self._events[rid].set(message) # 找到对应挂起的事件,然后设置,唤醒挂起的协程 else: break
def handle(self): try: self.update_status() while self.status not in (self.CONNECTION_END, self.CONNECTION_STOP): try: data_size = self.rfile.read(4) except timeout: self.update_status() print self.status else: break self.update_status() while self.status not in (self.CONNECTION_END, self.CONNECTION_STOP): if len(data_size) < 4: print 'Wrong input received: EOF while waiting for \ message length (4 bytes long)' self.update_status(self.CONNECTION_STOP) else: data_size = s_unpack('!I', data_size)[0] if data_size > 4096: print 'Wrong input received: message size exceeds \ 4096 bytes' self.update_status(self.CONNECTION_STOP) else: try: data = self.rfile.read(data_size) except timeout: print 'Wrong input received: timeout' self.update_status(self.CONNECTION_STOP) else: if len(data) < data_size: print 'Wrong input received: EOF while \ waiting message content (' + str(data_size) + '\nbytes long)' self.update_status(self.CONNECTION_STOP) else: try: data = m_unpack(data, use_list=False) except Exception as exception: print 'Wrong input received:', exception self.update_status(self.CONNECTION_STOP) else: self.handle_test(data) try: handler_suffix = data['type'] except TypeError: print "Wrong input received: invalid \ message's type" self.update_status( self.CONNECTION_STOP) except KeyError: print 'Wrong input received: no \ `type` field in message' self.update_status( self.CONNECTION_STOP) else: # We must ensure that `type` field # contains a string type object if not isinstance( handler_suffix, basestring): print 'Wrong input received: \ invalid message field `type`' self.update_status( self.CONNECTION_STOP) else: handler_name = 'handle_' + \ handler_suffix if self.status == \ self.CONNECTION_INIT and \ handler_suffix != 'init': print 'Wrong input received: \ invalid message field `type`; must be "init" during the\ninitialisation phase.' self.update_status( self.CONNECTION_STOP) else: try: handler = getattr( self, handler_name) except AttributeError: print 'Wrong input \ received: invalid message field `type`' self.update_status( self.CONNECTION_STOP) else: handler(data) while self.status not in ( self. CONNECTION_END, self. CONNECTION_STOP): try: data_size = self.\ rfile.\ read(4) except timeout: self.\ update_status() else: break self.update_status() while self.status == self.CONNECTION_END: sleep(1) except ThreadExit: self.update_status(self.CONNECTION_STOP)
def _decode(self, raw_value: bytes) -> float: if len(raw_value) != self._length: raise ValueError(f'{self._name} floating point out of supported length') if raw_value[0:1] != self._exponent: raise ValueError(f"{self._name} floating point's exponent out of supported range") return s_unpack(self._format, raw_value[1:self._length])[0]
def unpack(fmt, stream): if type(stream) == np.ndarray: stream0 = ''.join([chr(i) for i in stream]) else: stream0 = stream return s_unpack(fmt, stream0)
def getHeader(self, buff): uid = s_unpack("I", buff[:4])[0] return uid
def handle(self): try: self.update_status() while self.status not in (self.CONNECTION_END, self.CONNECTION_STOP): try: data_size = self.rfile.read(4) except timeout: self.update_status() print self.status else: break self.update_status() while self.status not in (self.CONNECTION_END, self.CONNECTION_STOP): if len(data_size) < 4: print 'Wrong input received: EOF while waiting for \ message length (4 bytes long)' self.update_status(self.CONNECTION_STOP) else: data_size = s_unpack('!I', data_size)[0] if data_size > 4096: print 'Wrong input received: message size exceeds \ 4096 bytes' self.update_status(self.CONNECTION_STOP) else: try: data = self.rfile.read(data_size) except timeout: print 'Wrong input received: timeout' self.update_status(self.CONNECTION_STOP) else: if len(data) < data_size: print 'Wrong input received: EOF while \ waiting message content (' + str(data_size) + '\nbytes long)' self.update_status(self.CONNECTION_STOP) else: try: data = m_unpack(data, use_list=False) except Exception as exception: print 'Wrong input received:', exception self.update_status(self.CONNECTION_STOP) else: self.handle_test(data) try: handler_suffix = data['type'] except TypeError: print "Wrong input received: invalid \ message's type" self.update_status(self. CONNECTION_STOP) except KeyError: print 'Wrong input received: no \ `type` field in message' self.update_status(self. CONNECTION_STOP) else: # We must ensure that `type` field # contains a string type object if not isinstance(handler_suffix, basestring): print 'Wrong input received: \ invalid message field `type`' self.update_status(self. CONNECTION_STOP) else: handler_name = 'handle_' + \ handler_suffix if self.status == \ self.CONNECTION_INIT and \ handler_suffix != 'init': print 'Wrong input received: \ invalid message field `type`; must be "init" during the\ninitialisation phase.' self.update_status(self. CONNECTION_STOP) else: try: handler = getattr(self, handler_name) except AttributeError: print 'Wrong input \ received: invalid message field `type`' self.update_status( self.CONNECTION_STOP) else: handler(data) while self.status not in ( self. CONNECTION_END, self. CONNECTION_STOP): try: data_size = self.\ rfile.\ read(4) except timeout: self.\ update_status() else: break self.update_status() while self.status == self.CONNECTION_END: sleep(1) except ThreadExit: self.update_status(self.CONNECTION_STOP)