Skip to main content

dcom python package

Project description

dcompy

欢迎前往社区交流:海萤物联网社区

简介

RPC:Remote Procedure Call,远程过程调用。使用RPC可以让一台计算机的程序程调用另一台计算机的上的程序。

RPC通过把网络通讯抽象为远程的过程调用,调用远程的过程就像调用本地的子程序一样方便,从而屏蔽了通讯复杂性,使开发人员可以无需关注网络编程的细节,将更多的时间和精力放在业务逻辑本身的实现上,提高工作效率。

DCOM:Device Communication Protocol(DCOM),设备间通信协议。DCOM是针对物联网使用场景开发的RPC框架,主要有如下特点:

  • 协议开销极小仅4字节。物联网很多场景都是几十字节的短帧,RPC协议本身的开销如果过大会导致在这些场景无法应用
  • 可以跨语言通信。DCOM协议在设计上与语言无关,无论C,Golang,Python等都可以使用DCOM
  • 可以跨通信介质通信。DCOM协议可以工作在以太网,串口,wifi,小无线等一切通信介质之上

在海萤物联网中,节点间使用DCOM来通信。本文介绍Python语言开发的DCOM包的使用方法。

开源

安装

pip install dcompy

基础概念

查看文档 海萤物联网教程:Go SDK 基础概念章节。

API

def load(param: LoadParam)
	"""模块载入"""

def register(protocol: int, rid: int, callback):
    """
    注册DCOM服务回调函数
    :param protocol: 协议号
    :param rid: 服务号
    :param callback: 回调函数.格式: func(pipe: int, src_ia: int, req: bytearray) (bytearray, int)
    :return: 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
    """

def receive(protocol: int, pipe: int, src_ia: int, data: bytearray):
    """
    接收数据.应用模块接收到数据后需调用本函数,本函数接收帧的格式为DCOM协议数据
    """

def register(protocol: int, rid: int, callback):
    """
    注册DCOM服务回调函数
    :param protocol: 协议号
    :param rid: 服务号
    :param callback: 回调函数.格式: func(pipe: int, src_ia: int, req: bytearray) (bytearray, int)
    :return: 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
    """

def call(protocol: int, pipe: int, dst_ia: int, rid: int, timeout: int, req: bytearray) -> (bytearray, int):
    """
    RPC同步调用
    :param protocol: 协议号
    :param pipe: 通信管道
    :param dst_ia: 目标ia地址
    :param rid: 服务号
    :param timeout: 超时时间,单位:ms.为0表示不需要应答
    :param req: 请求数据.无数据可填bytearray()或者None
    :return: 返回值是应答字节流和错误码.错误码非SYSTEM_OK表示调用失败
    """
  • 数据结构
class LoadParam:
    """
    载入参数
    """

    def __init__(self):
        # 块传输帧重试间隔.单位:ms
        self.block_retry_interval = 0
        # 块传输帧重试最大次数
        self.block_retry_max_num = 0

        # API接口
        # 是否允许发送.函数原型:func(pipe: int) bool
        self.is_allow_send = None  # type: Callable[[int], bool]
        # 发送的是DCOM协议数据.函数原型:func(protocol: int, pipe: int, dst_ia: int, bytes: bytearray)
        self.send = None  # type: Callable[[int, int, int, bytearray], None]
  • 系统错误码
# 系统错误码
# 正确值
SYSTEM_OK = 0
# 接收超时
SYSTEM_ERROR_RX_TIMEOUT = 0x10
# 发送超时
SYSTEM_ERROR_TX_TIMEOUT = 0x11
# 内存不足
SYSTEM_ERROR_NOT_ENOUGH_MEMORY = 0x12
# 没有对应的资源ID
SYSTEM_ERROR_INVALID_RID = 0x13
# 块传输校验错误
SYSTEM_ERROR_WRONG_BLOCK_CHECK = 0x14
# 块传输偏移地址错误
SYSTEM_ERROR_WRONG_BLOCK_OFFSET = 0x15
# 参数错误
SYSTEM_ERROR_PARAM_INVALID = 0x16

load:模块载入

在使用DCOM前必须要初始化。DCOM支持重传,所以在初始化时需输入重传间隔以及重传最大次数。

DCOM与通信介质无关,不同介质可定义不同的管道号。应用程序需要在是否允许发送函数(is_allow_send),以及发送函数(send)中编写不同管道的操作。

  • 示例:某节点有两个管道
if __name__ == '__main__':
	param = dcompy.LoadParam()
    param.block_retry_max_num = 5
    param.block_retry_interval = 1000
    param.is_allow_send = is_allow_send
    param.send = send
    dcompy.load(param)


def is_allow_send(pipe: int) -> bool:
    if pipe == 1:
    	return is_pipe1_allow_send()
    else:
    	return is_pipe2_allow_send()


def send(protocol: int, pipe: int, dst_ia: int, data: bytearray):
    if pipe == 1:
    	pipe1_send(data)
    else:
    	pipe2_send(data)

protocol,dst_ia等字段根据需求处理。

receive 接收数据

应用程序接收到数据需要调用receive函数,将数据发送给DCOM。

  • 示例:某节点有两个管道都可接收
def pipe1_receive(data: bytearray):
	dcom.receive(0, 1, 0x2140000000000101, data)

def pipe2_receive(data: bytearray):
	dcom.Receive(0, 2, 0x2140000000000101, data)

协议号protocol示例中填写的是0,应用时根据实际场景填写。

register:服务注册

节点可以通过注册服务开放自身的能力。

  • 示例:假设节点2140::101是智能插座,提供控制和读取开关状态两个服务:
dcom.register(0, 1, control_service)
dcom.register(0, 2, get_state_service)

// control_service控制开关服务
// 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
def control_service(pipe: int, src_ia: int, req: bytearray) -> (bytearray, int):
	if req[0] == 0:
		off()
	else:
		on()
	return None, dcom.SystemOK

// get_state_service 读取开关状态服务
// 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
def get_state_service(pipe: int, src_ia: int, req: bytearray) -> (bytearray, int):
	return bytearray([state()]), dcom.SystemOK

call:同步调用

def call(protocol: int, pipe: int, dst_ia: int, rid: int, timeout: int, req: bytearray) -> (bytearray, int):
    """
    RPC同步调用
    :param protocol: 协议号
    :param pipe: 通信管道
    :param dst_ia: 目标ia地址
    :param rid: 服务号
    :param timeout: 超时时间,单位:ms.为0表示不需要应答
    :param req: 请求数据.无数据可填bytearray()或者None
    :return: 返回值是应答字节流和错误码.错误码非SYSTEM_OK表示调用失败
    """

同步调用会在获取到结果之前阻塞。节点可以通过同步调用,调用目标节点的函数或者服务。timeout字段是超时时间,单位是毫秒。如果目标节点超时未回复,则会调用失败。如果超时时间填0,则表示不需要目标节点回复。

  • 示例:2141::102节点控制智能插座2141::101开关状态为开
resp, errCode = dcom.call(0, 1, 0x2140000000000101, 3000, bytearray([1]))
  • 示例:2141::102节点读取智能插座2141::101开关状态
resp, errCode = dcom.call(0, 2, 0x2140000000000101, 3000, None)
if errCode == dcom.SystemOK:
	print("开关状态:", resp[0])

请求和应答数据格式

DCOM通信双方发送的数据流都是二进制,请求(req)和应答(resp)的数据类型都是[]uint8。

二进制不利于应用处理,所以会将二进制转换为其他数据类型来处理。常用的有以下三种:

  • 结构体
  • json
  • 字符串

在物联网中,硬件节点的资源有限,且大部分都是使用C语言编写代码。所以建议使用C语言结构体来通信。结构体约定使用1字节对齐,小端模式。

海萤物联网提供sbc库用来进行C语言结构体和二进制流的转换,详情可以查看文档:海萤物联网教程:sbc:基于python的C语言格式结构体和二进制转换库

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dcompy-1.6.tar.gz (16.5 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page