该篇blog将讲述如何通过Edgex的SDK接口来创建device service,分为两部分,第一部分是configuration.toml与profile.yml的配置参数讲解,第二部分是有关SDK接口的实现。
首先到github上下载device-sdk-go,进入example目录下,接下来将主要对这个示例进行分析讲解。
configuration.toml主要是用来配置device service的地址和端口号,注册到EdgeX服务中以及设备的预定义。
进入cmd/device-simple/res/目录下,打开configuration.toml,如果你的EdgeX部署在服务器上,则需要将[Service]中的Host修改成服务器的ip地址,[Registry], [Clients], [Device], [Logging]等可以不需要修改。
找到[[DeviceList]]该部分是用来预定义设备的
Name是你创建的Device的名字
Profile是用来创建Device的配置文件,即profile.yml中name的值
[[DeviceList.AutoEvents]]是用来自动发送Command请求的,对应profile.yml是调用get命令,对应SDK接口是调用HandleReadCommand函数
Frequency 是发送请求的频率
Resource 是发送请求对应的数据类型,与proflie.yml中的deviceResources对应。
Profile.yml是用来定义Device的数据类型以及EdgeX如何通过core-Command来对device发送命令,先讲解deviceResources,deviceCommands与coreCommands的关系,deviceResources中的值是定义Device上传到deviceService中数据的类型,coreComands定义了核心服务core-command能对设备进行的操作,包括读(get)和写(put)。deviceCommands是联系coreCommands与deviceResources的桥梁,他定义了coreCommands操作设备时对哪些数值类型进行操作。
如图所示:
第一行name对应configuration.toml中DeviceList中的Name,是这个Profile的“名字”
deviceResources中name: “SwitchButton”代表这个设备的一个数据类型的名称
下面的 properties定义了SwitchButton的基本数值类型
corecommands 定义了core-command对设备操作的两种方法,一个是读(get),一个是写(put)
get中 expectedValues表示希望读取到的值的类型,与deviceResources中name目录下的名称一致
put中parameterNames表示传入的参数的值的类型,也与deviceResources中name目录下名称一致
deviceCommands连接deviceResources与coreCommands
name与 coreCommands中name一致
在coreCommands中定义了get则需要get, 定义了put则需要定义set。
deviceResource与deviceResources中name一致。
通过Configuration.toml的预定义Device和Simple.yaml文件就可以生成一个Device并且注册到core-metadata中去,当然也可以自己通过Simple.yaml手动注册一个Device
创建一个设备服务主要是要实现ProtocolDriver中给出的接口,在这个实例中进入到driver目录,主要是实现Initialize、HandleReadCommands、HandleWriteCommands三个函数。
Initialize(lc logger.LoggingClient, asyncCh chan<- *dsModels.AsyncValues, deviceCh chan<- []dsModels.DiscoveredDevice) error
lc应该是日志系统,asynCh是一个通道,我们通过将我们想上传的值赋予给asynCh就可以上传至coredata,deviceCh没有使用过,应该是用来自动发现设备的。
在Initialize函数中要定实现创建的设备服务的服务器,比如像mqtt服务器、http服务器等等,这些服务能监听某个Broker或者某个URL,当真实物理设备向这个Borker或者URL发送数据时,该服务就能取得数据,包装成asynCh,发送至coredata。具体如何实现服务设备,这个example中没有讲到,在device-rest-go和device-mqtt-go中有实现服务设备,我下篇博客也会讲如何具体实现。
func (s *SimpleDriver) HandleReadCommands(deviceName string, protocols map[string]contract.ProtocolProperties, reqs []dsModels.CommandRequest) (res []*dsModels.CommandValue, err error)
该函数的作用是在用户通过core-command发送get命令时调用,行为是像物理设备发送一次读命令请求。
deviceName:发送get命令时的物理设备的名称
protocals:不清楚有什么作用
reqs:命令的详细内容,可以通过该参数获取请求的数值类型等等
返回值res:将命令需要返回的值封装到res中,会自动包装成asyncCh发送到coredata中去
首先判断reqs的长度,即需要读取的deviceResources中变量的个数,
然后创建变量now,作为时间戳,之后通过调用reqs[0].DeviceResourceName来获得数据类型,进入到if之后通过dsModels.*Value(reqs[0].DeviceResourceName, now, value)来创建一个dsModels.CommandValue类型的变量,其中now是之前创建的时间戳,value是要上传到coredata的值,赋值给res,就可以通过res上传到coredata完成数据上传。
func (s *SimpleDriver) HandleWriteCommands(deviceName string, protocols map[string]contract.ProtocolProperties, reqs []dsModels.CommandRequest,
params []*dsModels.CommandValue) error {
用法基本与HandleRandomCommends一致,通过post上传的参数放到了params里面,其他就不多说了。