开发指南

APP组成

本章介绍如何使用Lua5.3语言开发FreeIOE应用,在开始阅读本章前,请先熟悉Lua中模块的概念以及如何构建简单的Lua模块。
一个经典的APP会有如下的结构:
├── opcua_client ———— App目录
│——├── app.lua ————- App入口Lua文件
│——├── conf.lua ———— App自定义模块文件
│——└── luaclib ————- App自定义的C模块目录
│—————└── opcua.so — App自定义的OpcUA模块(C语言模块)

APP应用的入口是一个符合FreeIOE框架接口定义的特定Lua模块文件

连接设备

TCP 套接字

FreeIOE框架提供两种TCP Socket连接方式:

  1. SocketChannel

    Skynet 框架提供的TCP Socket通讯框架。有两种工作模式:

    • 同步模式
    • 异步模式(需要协议支持Session)
  2. app.socket

    FreeIOE 封装的简易TCP Socket模式。

  3. Skynet Socket模块

连接设备(串口)

FreeIOE 集成了librs232模块,支持用户访问串口设备。可选择:

  1. SerialChannel

    同SocketChannel模式的通讯框架

  2. app.serial

    FreeIOE 封装的建议串口模块

  3. rs232

    直接使用librs232模块

UDP 套接字

TODO:

创建设备模型(实例)

在开始真正采集设备数据之前,需要创建设备模型以及设备实例:

  1. --- 生成设备的序列号
  2. local dev_sn = "this_is_device_serial_number"
  3. local meta = self._api:default_meta()
  4. meta.name = "Modbus"
  5. meta.description = "Modbus Device"
  6. meta.series = "S5500"
  7. --- 生成设备模型对象
  8. local dev = self._api:add_device(dev_sn, meta, inputs, outputs, commands)
  9. --- 生成设备通讯口统计对象
  10. local stat = dev:stat('port')

设备描述

设备描述包含:元信息,输入项,输出项,指令集

元信息(meta)

设备元信息包含以下内容:

  1. name: 设备描述名称(云平台唯一名称, 如: Symtech S5500)
  2. description: 设备描述
  3. inst: 设备实例名称(用户可见名称如: 1# S5500电表
  4. series: 设备型号(如: v2)

输入项(input)

设备输入项,即从实际传感器设备采集到的数据项,如A相电压、有功总功率等等。

  1. local inputs = {}
  2. table.insert(inputs, {
  3. name='Va',
  4. desc='A相电压',
  5. })
  6. table.insert(inputs, {
  7. name='Mode',
  8. desc='工作模式',
  9. vt = 'int', -- 数据类型:整数数值。可以是: float/int/string,缺省为float浮点类型(double)
  10. })

输出项(output)

设备输出项,即可以用来调整传感器设备输出的数据项。如:当前输出电压,输出功率等等。

  1. local outputs = {}
  2. table.insert(outputs, {
  3. name='v_output',
  4. desc='输出电压',
  5. })

指令集(command)

设备支持的动作指令。如:开启,停止,暂停等等。

  1. local commands = {}
  2. table.insert(commands, {
  3. name='start',
  4. desc='启动设备(无需参数)',
  5. })

设定数据

当通过设备通讯协议收到设备数据项后,设定设备输入项:

  1. dev:set_input_prop('Va', "value", math.tointeger(v), now, 0)

响应输出

在api:set_handler的处理对象中增加下面的处理函数。当平台的设备输出请求到达网关后,此处理函数就会被调用。

  1. --- 处理设备输出项数值变更消息
  2. -- @param app 应用对象实体
  3. -- @param sn 目标设备序列号
  4. -- @param output 输出项名称
  5. -- @param prop 输出项属性(默认为value)
  6. -- @param value 输出数值
  7. on_output = function(app, sn, output, prop, value)
  8. -- You code here
  9. end,

响应指令

在api:set_handler的处理对象中增加下面的处理函数。当平台的设备指令请求到达网关后,此处理函数就会被调用。

  1. --- 处理设备指令消息
  2. -- @param app 应用对象实体
  3. -- @param sn 目标设备序列号
  4. -- @param command 指令名称
  5. -- @param param 参数(可以是数值,字符串,table)
  6. on_command = function(app, sn, command, param)
  7. -- You code here
  8. end,

紧急数据

紧急数据是一种需要FreeIOE尽快将之传输至平台的数据,设定方式为:

  1. dev:set_input_prop_emergency('Va', "value", math.tointeger(v), now, 0)

紧急数据将绕过一系列的上传检测/打包等操作,请谨慎使用。

设备事件

当设备/应用出现异常,或者任何其他需要通知用户的可读信息,通过设备的事件接口将信息上传至平台。

  1. local event = require 'app.event'
  2. local info = "/tmp disk is nearly full!!!"
  3. dev:fire_event(event.LEVEL_ERROR, event.EVENT_SYS, info, {used=10000000, free=0})

通讯报文

当从链路上接受到数据时,可以通过通讯报文接口进行输出。

  1. --- 设定通讯口数据回调
  2. client:set_io_cb(function(io, msg)
  3. --- 输出通讯报文
  4. dev:dump_comm(io, msg)
  5. --- 计算统计信息
  6. if io == 'IN' then
  7. stat:inc('bytes_in', string.len(msg))
  8. else
  9. stat:inc('bytes_out', string.len(msg))
  10. end
  11. end)

通讯统计

通讯统计信息,如接收包数,发送包数,接收字节数,发送字节数等等。

  • 统计类型
    • status
    • success_ratio
    • error_ratio
    • packets_in
    • packets_out
    • packets_error
    • bytes_in
    • bytes_out
    • bytes_error

代码示例,见通讯报文代码示例

应用日志

参考日志接口

  1. self._log:trace("read input registers done!")
  2. self._log:trace("Got err:", err, "more", "log content", here)

其他

设备序列号

如设备协议中并未提供设备的序列号读取方式、或者不想采用设备本身的序列号,则可以使用FreeIOE提供的序列号生成功能,生成序列号。参考:

  1. local dev_sn = self._sys:gen_sn('S5500_#1')

如需更为简单的序列号方式,则可以使用网关序列号 + 应用示例名 + 设备序号:

  1. local dev_sn = self._sys:id()..self._name..'#1'

云配置

云平台提供应用的云配置服务,可以存储应用配置、设备模板等文本信息。在应用中可以使用sys:conf_api来获取接口,从而从平台下载配置的内容。

  1. local api = self._sys:conf_api('TPL000000001')
  2. local ver = api:version()
  3. local str = api:data(ver)
  4. -- If template is cjson format
  5. local conf = cjson.decode(str)
  6. -- If template is csv
  7. local conf = ftcsv.parse(str)

社区

访问FreeIOE 应用开发

应用参考

FreeIOE 在Github上提供一些示例应用: 代码库