之前介绍过通过snack3快速对接物模型,不知道大家还有没有影响。记得还留了一个作业给大家想想,就是这么兼容多型号、多版本,这次就来跟大家分享下这么集成多型号。
上次是利用snack3 + 物模型json文件,快速对接。这次要支持多型号,那肯定首先物模型json文件调整时少不了的。
[{"profile": {"device_category": "温度检测器","device_unit": "WD-470AA1-01-0114","version": "1.0"},"properties": [{"dataType": {"specs": {"1": "成功"},"type": "enum"},"identifier": "ack_state","name": "指令下发状态"},{"dataType": {"specs": {"unit": "V"},"type": "double"},"identifier": "battery_voltage","name": "电池电压"},{"dataType": {"specs": {},"type": "string"},"identifier": "date","name": "数据上报时间"},{"dataType": {"specs": {"unit": "℃"},"type": "double"},"name": "温度","identifier": "temperature"}],"services": [{"inputs": [{"dataType": {"specs": {"unit": "/"},"type": "int"},"identifier": "year","name": "年"},{"dataType": {"specs": {"unit": "/"},"type": "int"},"name": "月","identifier": "month"},{"dataType": {"specs": {"unit": "/"},"type": "int"},"name": "日","identifier": "day"},{"dataType": {"specs": {"unit": "/"},"type": "int"},"name": "时","identifier": "hour"},{"dataType": {"specs": {"unit": "/"},"type": "int"},"name": "分","identifier": "minute"},{"dataType": {"specs": {"unit": "/"},"type": "int"},"name": "秒","identifier": "second"}],"identifier": "setTime","name": "时间同步设置","dataType": {"specs": {}}},{"inputs": [{"dataType": {"specs": {"unit": "s","min": "60","max": "86340"},"type": "int"},"identifier": "heart_beat","name": "心跳时间"}],"identifier": "heartbeat","name": "心跳周期设置","dataType": {"specs": {}}}]},{"profile": {"device_category": "温度检测器","device_unit": "WD-470AA1-01-0241","version": "1.0"},"properties": [{"dataType": {"specs": {},"type": "string"},"name": "设备ID","identifier": "device_id"},{"dataType": {"specs": {"0": "未校准","1": "已校准"},"type": "bool"},"name": "温度校准状态","identifier": "temp_calibration_state"},{"dataType": {"specs": {"0": "低于10%","1": "10%~20%","2": "20%~30%","3": "30%~50%","4": "50%以上"},"type": "enum"},"name": "电量等级","identifier": "battery_level"},{"dataType": {"specs": {"unit": "min","min": "1","max": "1440"},"type": "int"},"name": "心跳周期","identifier": "heartbeat_time"},{"identifier": "temperature","name": "温度","dataType": {"type": "double","specs": {"unit": "℃","unit_name": "摄氏度","min": "-20","max": "60"}}}],"services": [{"name": "设置心跳周期","identifier": "set_heartbeat_time","inputs": [{"dataType": {"specs": {"unit": "min","min": "1","max": "1440"},"type": "int","default": 60},"name": "心跳周期","identifier": "heartbeat_time"}],"isPooling": 0,"ackTimeout": null,"ackType": 0,"dataType": {"specs": {}}},{"name": "校准温度","identifier": "calibrate_temperature","inputs": [{"dataType": {"specs": {"min": "-2","max": "2"},"type": "double","default": 1},"name": "系数","identifier": "k"},{"dataType": {"specs": {"min": "-10","max": "10","unit": "℃"},"type": "double","default": 0},"name": "偏移量","identifier": "b"}],"isPooling": 0,"ackTimeout": null,"ackType": 0,"dataType": {"specs": {}}}]}
]
这里实际就是将json文件格式调整问json集合数组,一个元素时一个型号,例如这里就是个型号:WD-470AA1-01-0114、WD-470AA1-01-0241
原下行指令转换(核心):
/*** 读取物模型并返回下行服务** @param deviceTypeNo 设备类型编码* @param servicesId 下行标识* @return*/public static cn.hutool.json.JSONObject getDownCommand(String deviceTypeNo, String servicesId) {cn.hutool.json.JSONObject json = new cn.hutool.json.JSONObject();//设备类型编码获取物模型String thingsJsonUrl = "/things/" + deviceTypeNo + ".json";try {String thingsJsonStr = ResourcesUtil.getResourceAsString(thingsJsonUrl);ONode jsonONode = ONode.loadStr(thingsJsonStr);ONode commandONode = jsonONode.select("$.services[?(identifier == '" + servicesId + "')]");if (!commandONode.isNull()) {commandONode = commandONode.get(0);json = JSONUtil.parseObj(ONode.serialize(commandONode));}return json;} catch (Exception e) {log.error("读取linkos物模型,获取下行service服务异常,原因:", e.getMessage());}return null;}
现扩展下行转换(核心):
/*** 获取转化后的下行指令** @param deviceTypeNo 设备类型编码* @param servicesId 服务id* @param unitCode 型号编码* @return 下行指令*/public static cn.hutool.json.JSONObject getDownCommand(String deviceTypeNo, String servicesId, String unitCode) {//这里根据型号编码是否空判定是否走多型号物模型if (StringUtils.isBlank(unitCode)) {return getDownCommand(deviceTypeNo, servicesId);}cn.hutool.json.JSONObject json = new cn.hutool.json.JSONObject();//设备类型编码获取物模型String thingsJsonUrl = "/things/" + deviceTypeNo + ".json";try {String thingsJsonStr = ResourcesUtil.getResourceAsString(thingsJsonUrl);ONode jsonONode = ONode.loadStr(thingsJsonStr);ONode commandONode = jsonONode.select("$.[?(@.profile.device_unit == '" + unitCode + "')]").get(0).select("$.services[?(identifier == '" + servicesId + "')]");if (!commandONode.isNull()) {commandONode = commandONode.get(0);json = JSONUtil.parseObj(ONode.serialize(commandONode));}return json;} catch (Exception e) {log.error("读取linkos物模型,获取下行service服务异常,原因:", e.getMessage());}return null;}
实际上就是根据型号编码判定是否走多型号支持。
这里snack3功不可没,就是这:
ONode commandONode = jsonONode.select(“.[?(@.profile.deviceunit==′"+unitCode+"′)]").get(0).select(".[?(@.profile.device_unit == '" + unitCode + "')]").get(0).select(".[?(@.profile.deviceunit==′"+unitCode+"′)]").get(0).select(".services[?(identifier == '” + servicesId + “')]”);这一行连续过滤轻轻松松找到对应的物模型下行指令信息。
业务模块有设置设备的厂家、品牌、型号信息:

那么业务系统只需要在定义型号时,设置为跟物模型文件里的型号一致就ok。