5 Star 20 Fork 20

IOTOS / IOTOSDK-Python

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 18.67 KB
一键复制 编辑 原始数据 按行查看 历史
robbin 提交于 2023-07-28 16:09 . update

IOTOS物联中台 vs 常见物联网平台

  • 侧重面向集成项目、存量设备子系统接入 vs 面向消费端智能硬件、增量设备接入
  • 降低接口协议驱动的开发门槛 vs 新产品的创建和连接管理
  • 强调工具化,驱动由项目实施人员来配置交付项目 vs 实现硬件设备出厂直接接入IoT平台

历史版本说明

4.0.1.220928_release 升级驱动类的setValue()方法,在端侧支持数据点上报自动创建机制

4.0.1.220501_release

驱动命名规则:

  • 初步拟订驱动命名规则,以dr_开头为普通接口协议层驱动,以drl_开头为通信连接层驱动。
  • 两类型驱动可以通过同一个网关下组合,不同设备间的本地发布订阅来使用

驱动类(用于开发编写驱动包)

#!coding:utf8
import json
import sys
sys.path.append("..")
from driver import *

class TemplateDriver(IOTOSDriverI):
   '''
   驱动派生类模板,直接编写设备子系统接入相关的接口协议转换代码

   1.属性:
   	1.1	String sysId 
   		设备实例全局标识

       1.2	Json sysAttrs
   		设备实例配置属性
       
   	1.3	Json data2attrs
   		数据点与属性配置键值对
       
   	1.4	Json data2subs
   		数据点与被订阅设备列表键值对
   	
   	1.5	Json name2dataId
   		数据点名称与对应标识键值对
   
   2.方法
   	2.1 String getSysId()
   		获取设备标识(参见1.1)

   	2.2 Json getSysAttrs()
   		获取设备配置(参见1.2)
   	
   	2.3 Json getData2attrs()
   		获取数据点配置(参见1.3)
   	
   	2.4 Json getData2subs()
   		获取数据被订阅信息(参见1.4)
   	
   	2.5 String id(String name)
   		数据点名称转标识(参见1.5),将名称标识(方便阅读和修改的)换成ID标识(保证唯一性,方便驱动代码复用)
   		注意,支持"[数据点名称]"或"[设备名称].[数据点名]",暂不支持"全名称"("[网关名称].[设备名称].[数据点名称]")
   	
   	2.6	String name(String id)
   		数据点标识转名称,将标识ID转成名称
   		注意,支持"[数据点标识]"或"[设备标识].[数据点标识]",暂不支持"全ID标识"("[网关标识].[设备标识].[数据点标识]")
   	
   	2.7 None setPauseCollect(Bool enable=True)
   		传入True或False,设置3.3中Collecting()是否停止采集循环遍历,默认不启动。调用并传入False将启动采集循环(线程),
   		按顺序自动从数据点表第一个到最后一个进行遍历传入,详见3.3。
   	
   	2.8 None setCollectingOneCircle(Bool enable=True)
   		在2.7设置启用采集循环前提下,传入True或False,设置3.3中采集循环是周期循环遍历,还是初始化遍历完数据点表一次就退出(默认)
   	
   	2.9 String pointId(String dataId)
   		根据当前设备下数据点由ID标识,获取带网关、设备的"全ID标识"("[网关标识].[设备标识].[数据点标识]")
   		@param 
   			dataId: String	数据点ID标识,如"0b2e"
       	@return String	全ID标识,如'9003f858c85011ecbb02525400ffc252.e2c4f6fe.0b2e'
   	
   	2.10 String(Json) setValue(String name=None,id=None, Bool/String/Int/Float value, Timestamp timestamp=time.time(), Bool auto_created=False)
   		上报当前设备下单个数据点的值。注意name、id保证有任一传入即可,不要都传入。
   		@param
   			 name: String	数据点名称
   			   id: String	数据点ID标识
   			value: Bool/String/Int/Float	数据点上报值
   		@return String	Json字符串:{"code": 0, "msg":"", "data":""},返回格式及错误码详见README.md
   	
   	2.11 String(Json) setValues(Json data_values)
   		批量上报数据点值。
   		@param
   			data_values: Json 多个数据点与值组成的json数组,比如[{"id": "数据点ID", "value": "数据点value"}, {"id": "数据点ID", "value": "数据点value"}]
   		@return String 多个返回结构Json数组字符串,比如[{"code": 0, "msg":"", "data":""},{"code": 0, "msg":"", "data":""}],返回格式及错误码详见README.md
   	
   	2.12 Bool/String/Int/Float valueTyped(String dataId,String strValue)
   		将字符串类型的值按照点表类型转换成实际类型
   		@param
   			  dataId: String	数据点ID标识
   			strValue: String	数据点值对应的字符串
   		@return Bool/String/Int/Float	根据数据点的实际类型将字符串数值转换成实际类型
   	
   	2.13 Bool/String/Int/Float value(String name,String param='',String source='memory')
   		获取数据点的当前值,包含从采集引擎缓存、平台数据库、以及设备当下最新这三种方式
   		@param
   			  name: String	数据点名称
   			 param: String	查询条件,
   			source: String	有'memory'、'device'、'platfrom'三个来源参数,简写m/M,d/D,p/P,分别是上次采集到引擎的数据、设备当前数据、上报到平台的数据三类
   		@return Bool/String/Int/Float	按照实际类型返回数据点当前值

   	2.14 String(Json) subscribers(self, dataId)
   		订阅了当前设备指定监测点的外部设备ID标识列表
   		@param
   			dataId: String	数据点ID标识
   		@return String	返回Json数组字符串,比如["d8540013","36cb7dd8","82591776"]
   	
   	2.15 String(Json) online(Bool state)
   	    上报平台设备上下线状态
   		@param
   			state: Bool	上线(True)/下线(False)
   		@return String	参见详见README.md,通用数据返回结构

   	2.16 Object driver(String sysId)
   	    根据设备oid(不带“网关UUID.”)获取到该设备对应的驱动对象实例,注意,仅限于当前驱动实例对应设备相同网关节点下的其他设备
   		@param
   			sysId: String 设备/系统oid即全局标识,比如"d8540013"
   		@return Object 返回驱动类的对象类型,基类为IOTOSDriverI

   '''
   '''
   3.服务(引擎回调,需用户重写实现的驱动代码)
   	3.1 通信初始化:Bool InitComm(Json attrs)
   	3.2 通信连接状态回调(非必要,结合jcomm.py):None connectEvent(Bool state): 
   	3.3 循环采集:Dict/Array Collecting(String dataId): 
   	3.4 平台下发广播:String(Json) Event_customBroadcast(String fromUuid,String type,String data): 
   	3.5 平台下发查询:String(Json) Event_getData(String dataId, string condition): 
   	3.6 平台下发控制:String(Json) Event_setData(String dataId, Bool/String/Int/Float value): 
   	3.7 订阅数据上报:String(Json) Event_syncPubMsg(String point, Bool/String/Int/Float value): 
   '''

   #3.1 通信初始化
   def InitComm(self,attrs):
   	'''
   	需要用户实现的设备通信初始化。
   	Parameter
   	  attrs: dict 点表json加载并补全(参见parent指向)后,当前设备下包括数据的部分,示例如下:
   	  	{
   			"id": 11,
   			"device_oid": "d8540013",
   			"gateway_uuid": null,
   			"gateway_id": 8,
   			"uid": 28,
   			"config": {
   				"driver": "python/dr_pingshanshuiwu.ZSWDriver"
   			},
   			"name": "水位尺",
   			"type": "",
   			"description": "河道水文监测站-水位尺",
   			"timestamp": 1650774553.0,
   			"on": false,
   			"tpl_id": 9,
   			"data": {
   				"20bf": {
   					"id": 877,
   					"name": "msgId",
   					"description": "流水号(累加)",
   					"config": {},
   					"defaultvalue": "",
   					"readwrite": "1",
   					"timestamp": 1651338138724,
   					"valuetype": "STRING",
   					"maxvalue": "999",
   					"minvalue": "0",
   					"sensibility": "0.1",
   					"refreshcycle": "0",
   					"unit": null,
   					"tpl_id": 9,
   					"regexp": "english",
   					"value": null,
   					"data_date": null,
   					"data_oid": "20bf"
   				},
   			}
   		}
   	Return
   	  bool: True/False
   	'''
   	'''
   	
   	TODO
   	#self.setPauseCollect(True)
       #self.setCollectingOneCircle(False)
   	#self.online(True)
   	#self.setValue(u'demo_device.热水供水泵控制', True)
   	
   	''''
   	return True

   #3.3 循环采集
   def Collecting(self, dataId):
   	'''
   	对点表自动遍历的采集循环,可开启或关闭(对于主动上报,不存在遍历采集的情况)
   	Parameter
   	  dataId: string 当前数据点全局标识id,示例如"0b2e"
   	Return
   	  tuple: () 元组类型返回,多个不同类型数据的顺序组合,比如modbus批量采集数据后多个值的返回。
   		[*]应该支持多类型返回,常规数值类型,或元组都可以,目前直接返回dataId,报错;返回(dataId)报错;返回[dataId]才可以!
   	'''
   	'''

   	TODO
   	
   	''''
   	return ()

   #3.4 平台下发广播
   def Event_customBroadcast(self, fromUuid, type, data):
   	'''
   	高级用途,广播事件回调,其他操作访问,详略
   	'''
   	'''

   	TODO 
   	
   	'''
   	return json.dumps({'code':0, 'msg':'', 'data':''})

   #3.5 平台下发查询
   def Event_getData(self, dataId, condition):
   	'''
   	查询事件回调,数据点查询访问
   	Parameter
   		dataId: string 当前数据点全局标识id,示例如"0b2e"
   		condition: string 结合驱动支持下发的自定义查询条件
   	Return
   	  	string: 查询结果转成string类型返回
   	'''
   	'''

   	TODO 
   	
   	'''
   	return json.dumps({'code':0, 'msg':'', 'data':''})

   #3.6 平台下发控制
   def Event_setData(self, dataId, value):
   	'''
   	控制事件回调,数据点控制访问
   	Parameter
   		dataId: string 当前数据点全局标识id,示例如"0b2e"
   		value: 下发设备控制或写入的值,由数据点自身属性来决定类型,通常为Bool或String
   	Return
   	  	string: 执行结果转成string类型返回
   	'''
   	'''

   	TODO 
   	
   	'''
   	return json.dumps({'code':0, 'msg':'', 'data':''})

   #3.7 订阅数据上报
   def Event_syncPubMsg(self, point, value):
   	'''
   	数据订阅的事件回调。通常是同一个网关下不同设备上报的数据(兼容高级用途跨网关远程数据点订阅,略),常见订阅规则如下,
   	在当下驱动对应的设备实例驱动根配置中,param.sub以数组形式订阅同一个网关下其他一个或多个设备上报到平台的数据,以
   	[设备全局标识].[数据点全局标识],其中数据点全局标识可以指定也可以用*代替,表明指定设备所有setValue上报的数据都会
   	被订阅过来,在这里做数据处理,通过业务逻辑加工(常见是报文协议解析)后再做上报。
   	{
   		"driver": "python/dr_xxx.xxxDriver",
   		"param": {
   			"sub": [
   					"1bcd6b35.*"
   				],
   		}
   	}
   	230705,对于上述配置,新增下发支持支持,比如A订阅了B,在A的设备配置中sub字段配置有B的设备ID(可以是“设备oid.*”————全部数据点,
 		也可以是“设备oid.数据点oid”————指定一个或多个数据点),那么在A中数据点下发控制,会将下发参数自动派发到B设备驱动的Event_setData中,
   	不过注意,参数dataId不再是数据点oid,而是带有设备oid的形式,比如"4b6193fc.8838"。此时可以通过self.driver("4b6193fc")可以获得设备的驱动对象。
   	Parameter
   		point: string 当前数据点全ID(网关标识.设备标识.数据点标识),示例如"9003f858c85011ecbb02525400ffc252.e2c4f6fe.0b2e",id难以辨别可通过self.name()转换
   		value: 上报对应的值,由数据点自身属性来决定类型,通常为Bool/String/Int/Float
   	Return
   	  	string: string类型返回。注意同网关下不同设备的订阅为异步,可以默认返回或不返。兼容高级用途跨网关远程数据点订阅,返回值解释略
   	'''
   	'''

   	TODO 

   	'''
   	return json.dumps({'code':0, 'msg':'', 'data':''})

通用返回格式

{
    "code": 0,      //0表示调用成功;非0则标识异常,具体见"错误码定义"

    "msg" :"ok",	//code为0时,为描述信息;非0则对应错误码定义中的英文内容
    
    "data":null,	//code为0时,由具体业务接口返回数据而定,接口无返回则data为null,有返回则data为数据的字符串格式;
                    //code不为0时,通常存放程序捕获的异常信息字符串
}

驱动根配置

参考配置格式如下:

{
  "parentid": null,
  "driver": "python/drl_tcp.TCPDriver",
  "param": {
    "port": 3883,
    "sub": []   //本地设备间的数据发布和订阅
  },
  "datahub": "", //连同下面display,设置组态页面连接
  "display": "", //同上
  "bind": {}
}

配置字段说明

  • driver:关键项,用于指定驱动文件,以python驱动包为例,dr_xxx为文件名比如dr_mqtt(去掉.py后缀),后面xxx为驱动类名称比如MqttDriver,整体就是dr_mqtt.MqttDriver。其中如果驱动包类名称为"Driver时"可以省去类名称配置;如果是python驱动,也可以省去前缀"python/"。因此,上述示例的配置"driver": "python/drl_tcp.TCPDriver",在相关条件下,可以简化为"driver": "drl_tcp"。此外,为了兼容,当驱动类 名称为"Driver"时,驱动根配置的类名称可以不带,也可以配置任意名称,均可以。

  • param:设备通信连接自定义配置,由具体驱动提供配置字段及说明

关于param.sub,本地设备间的数据发布和订阅:

同一个网关下,多个设备实例比如A、B、C。其中A在正常从设备到平台数据点setValue上报过程中,设备B和C也需要该数据,那么可以在设备B、C的设备驱动配置中param.sub中订阅A的数据。

指定“[设备ID].[数据点ID]”(其中数据点ID可以用*号代替,表明订阅全部A中的数据!),那么对应A中被订阅的数据点上报时就会通过B、C的Event_syncPubMsg()事件函数传递过来!

常规IoT平台的方式:创建产品、设备(选择传输协议、消息协议),创建网关、网络组件。目前版本暂不支持这种方式配置(后续版本会提供)。

相对应地提供本地设备间数据的发布与订阅功能,一方面可实现常规传输协议与接口或报文协议组合,另一方面能实现本地联动调度以及算法服务类的虚拟设备接入,专用于数据处理。

上面本地发布订阅做到监听获取上行数据,那么订阅方的驱动怎么复用下行通道呢:setValue([设备名].[数据点名],val)即可!没有特殊机制!

数据点配置说明

  • 配置字段以modbus驱动为例说明
{
    "disabled": false,  //是否过滤
    "proxy": {
        "index": "",	//批量采集返回的第几个数据
        "pointer": null //是否指向其他数据点
    },
    "position": [],
    "equation": null,
    "class": null,
    "parentId": null,
  	"constant":"(当设定了此属性时,设定值将被当成固定值,在采集循环时上报。param的任何配置将不起作用)",
    "param": {
        "regad": 32,				//寄存器地址
        "funid": 3,					//功能号
        "equation": "round(x,1)",	//数值转换
        "devid": 1,					//设备地址
        "format": ">24f"			//连续采集数量以及数据类型、内存字节序
    }
}

注意1:format内存字节解析规则参考:http://www.3scard.com/index.php?m=blog&f=view&id=78

  • 关于公式equation字段配置说明 如下所示,param字段内的equation字段可以配置数值转换公式,其中x代表当前数据点在转换前的值,经过常见的加减乘除以及数学函数形成的计算后,表达式的值作为当前数据点实际上报的值。

表达式支持用python math模块支持的所有函数,参见python-math。注意,表达式中函数不需要math.开头,比如math.sqrt(),直接用sqrt()即可!

{ "param": { "equation": "round(x,1)" } }

此外,支持虚拟数据点,如下所以,当前数据点的值由vars中指定的其他数据点,经过equation表达式计算后生成。其中vars中key为表达式中的变量,value为其他数据点的全局标识或名称,数量可以任意多个(目前限定在同一个网关、同一个设备下)。

注意,当vars中任意一个数据点值更新,都会触发当前数据点值得更新和上报。其中,某个数据点值更新上报时,如果vars中其他数据点的值没有上报过,那么当前数据点的值不会更新,只有当依赖的所有数据点都有上报值后,才会触发当前数据点值进行更新和上报。

{ "param": { "vars":{ "x":"ac32", "y":"水箱水位", "z":"电缆温度", "m":"环境温度" }, "equation": "sqrt(x+y+z+m)" } }

错误码定义

数值范围对应错误源

   0~99:   通信路由返回
100~499:	数据后台返回
500~999:	采集引擎返回

错误码详细参照表

错误码 Enum定义(data) 中文描述 错误信息返回(msg)
0 Sucess 没有错误(返回成功) Success
101 Unknown 未知失败 Unknow error(当内部调用第三方库返回错误时,将库的反馈错误信息原样返回)
2 SelfOffline 自己掉线 self offline!
3 ObjectOffline 网络错误 Network error
504 NetError 没有错误(返回成功) Success
105 ArgError 参数错误 Argument error
105 ArgError 参数错误 Argument error
6 NoWebSer 没有WEB服务接入 No webserver online!
107 AccountNotRegister 用户名或密码错误,或登录失效 Account invalid
108 IONodeNotExist 接入网关不存在 Object not exists
109 DeviceNotExist 设备不存在 Device not exits
110 DataNotExist 数据点不存在 Data not exists
111 PointNotExist 点不存在 Point not exists
112 ObjectNotAuth 对象没有授权,目前指没有订阅相关接入网关 Object has no authority
513 FileNotExist 文件不存在 File not exists
514 TableNotValid 点表格式不正确 Table format invalid
515 PropertyNotValid 属性非法操作 Property access invalid
516 TypeNotValid 监测点类型不匹配 Point type mismatching
517 RuleNotRecognized 监测点条件规则未识别 Table format not
recognized
518 ThreadNotDestoryed 采集线程创建失败,存在未释放的 Inner resource not released
519 Timeout 接口请求超时 Timeout
521 DataNameInvalid 数据点名称不正确 DataName not exist
522 TypeNotSupport 参数类型不正确 type not support
1000 Reserved 以内的系统保留,大于的为用户服务自定义码 user customed

#230726 初步增加数据库业务接口驱动dr_influxdb_api.py(注意,改驱动依赖了dr_influxdb目录封装的包),默认 连接物联中台历史数据时序数据库。当北向接口难以满足业务数据,并且版本原因APIJSON也无法完全满足需求时, 可以通过驱动来编写数据库操作用以扩展业务接口。 相对于直接扩展北向接口而言,避免了需要改动平台代码。驱动编写与平台完全解耦,便于灵活扩展功能和服务。 此外,驱动是能与平台服务器运行在一起被云网关使用,因此对外不存在数据库暴露等安全性问题。

Python
1
https://gitee.com/aiotos/IOTOSDK-Python.git
git@gitee.com:aiotos/IOTOSDK-Python.git
aiotos
IOTOSDK-Python
IOTOSDK-Python
master

搜索帮助