驰诚对接的接口开发

master
Terry 4 days ago
parent 4812cc8407
commit 696de12073

@ -0,0 +1,76 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.openapi.controller;
import cc.iotkit.common.api.Request;
import cc.iotkit.openapi.dto.bo.chicheng.ChichengThingBo;
import cc.iotkit.openapi.dto.bo.chicheng.DeviceStatusBo;
import cc.iotkit.openapi.dto.bo.chicheng.HomeBo;
import cc.iotkit.openapi.dto.bo.chicheng.IndustryBo;
import cc.iotkit.openapi.service.ChichengService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import cn.dev33.satoken.annotation.SaIgnore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = {"openapi-驰诚数据接入"})
@Slf4j
@RestController
@RequestMapping("/openapi/chicheng")
public class ChichengController {
@Autowired
private ChichengService chichengService;
@ApiOperation("接收驰诚家报和独立探头上报数据")
@PostMapping("/v1/receiveHome")
public boolean receiveHomeData(@RequestBody @Validated Request<HomeBo> data){
return chichengService.receiveData1(data.getData());
}
@ApiOperation("接收驰诚工业控制器上报数据")
@PostMapping("/v1/receiveIndsutry")
public boolean receiveIndustryData(@RequestBody @Validated Request<IndustryBo> data){
return chichengService.receiveData2(data.getData());
}
@ApiOperation("设备上下线")
@PostMapping("/v1/modifyDeviceState")
public boolean modifyDeviceState(@RequestBody @Validated Request<DeviceStatusBo> data){
return chichengService.modifyDeviceStatus(data.getData());
}
@ApiOperation("接收驰诚设备上报数据(设备心跳/数据上报/通讯模块心跳)")
@PostMapping("/v1/receiveThing")
public boolean receiveThingData(@RequestBody @Validated Request<ChichengThingBo> data){
return chichengService.receiveThingData(data.getData());
}
}

@ -0,0 +1,37 @@
package cc.iotkit.openapi.dto.bo.chicheng;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "ChichengThingBo", description = "驰诚设备上报请求")
@Data
public class ChichengThingBo {
@ApiModelProperty(value = "请求ID")
private Long id;
@ApiModelProperty(value = "版本号")
private String version;
@ApiModelProperty(value = "产品Key")
private String productKey;
@ApiModelProperty(value = "设备名称(IMEI号)", required = true)
private String deviceName;
@ApiModelProperty(value = "时间戳")
private Long time;
@ApiModelProperty(value = "参数", required = true)
private Params params;
@ApiModelProperty(value = "方法名")
private String method;
@Data
public static class Params {
@ApiModelProperty(value = "上报数据(JSON字符串)", required = true)
private String upd_data;
}
}

@ -0,0 +1,121 @@
package cc.iotkit.openapi.dto.bo.chicheng;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "ChichengUpdDataBo", description = "upd_data解析后的数据结构")
@Data
public class ChichengUpdDataBo {
@ApiModelProperty(value = "消息类型: heartbeat(设备心跳), event_change/event_alarm/event_error(设备数据上报), power_on(通讯模块心跳)")
private String msg_type;
@ApiModelProperty(value = "错误值")
private String error_val;
@ApiModelProperty(value = "通道数量")
private Integer ch_cnt;
@ApiModelProperty(value = "错误数量")
private Integer erro_cnt;
@ApiModelProperty(value = "低报数量")
private Integer alarm_low_cnt;
@ApiModelProperty(value = "高报数量")
private Integer alarm_high_cnt;
@ApiModelProperty(value = "离线数量")
private Integer offline_cnt;
@ApiModelProperty(value = "故障状态")
private Integer fault_state;
@ApiModelProperty(value = "BSP状态")
private Integer bsp_state;
@ApiModelProperty(value = "信号质量")
private Integer csq;
@ApiModelProperty(value = "浓度值数组")
private Integer[] rtd_val;
@ApiModelProperty(value = "ADC值数组")
private Integer[] adc_val;
@ApiModelProperty(value = "状态数组(0正常/1低报/2高报/3故障/4离线/5超量程)")
private Integer[] status_val;
@ApiModelProperty(value = "无线模块信息(通讯模块心跳特有)")
private Wireless wireless;
@ApiModelProperty(value = "主机信息(通讯模块心跳特有)")
private Host host;
@Data
public static class Wireless {
@ApiModelProperty(value = "模块型号")
private String model;
@ApiModelProperty(value = "模块子型号")
private String module_model;
@ApiModelProperty(value = "IMEI号")
private String IMEI;
@ApiModelProperty(value = "ICCID号")
private String ICCID;
@ApiModelProperty(value = "软件版本")
private String sw_ver;
@ApiModelProperty(value = "硬件版本")
private String hw_ver;
@ApiModelProperty(value = "通道数量")
private Integer ch_cnt;
@ApiModelProperty(value = "心跳间隔(秒)")
private Integer heartbeat_inv;
@ApiModelProperty(value = "上报点数")
private Integer up_pcnt;
@ApiModelProperty(value = "上报间隔(秒)")
private Integer up_pcnt_inv;
@ApiModelProperty(value = "信号质量")
private Integer csq;
}
@Data
public static class Host {
@ApiModelProperty(value = "主机型号")
private Integer model;
@ApiModelProperty(value = "设备ID")
private String dev_id;
@ApiModelProperty(value = "芯片ID")
private String chip_id;
@ApiModelProperty(value = "生产日期")
private String mfd_day;
@ApiModelProperty(value = "软件版本")
private Integer sw_ver;
@ApiModelProperty(value = "硬件版本")
private Integer hw_ver;
@ApiModelProperty(value = "运行时长")
private Integer duration;
@ApiModelProperty(value = "数字通道数量")
private Integer d_ch_cnt;
@ApiModelProperty(value = "模拟通道数量")
private Integer a_ch_cnt;
}
}

@ -0,0 +1,21 @@
package cc.iotkit.openapi.dto.bo.chicheng;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "ChichengDataBo", description = "设备上下线")
@Data
public class DeviceStatusBo {
@ApiModelProperty(value = "消息类型: data(数据上报)、alarm(报警上报)、heartbeat(心跳)", required = true)
private String msgtype;
@ApiModelProperty(value = "时间戳", required = true)
private String timestamp;
@ApiModelProperty(value = "设备IMEI号", required = true)
private String imei;
@ApiModelProperty(value = "设备名称", required = true)
private String devicename;
@ApiModelProperty(value = "设备类型", required = true)
private String devicetype;
}

@ -0,0 +1,49 @@
package cc.iotkit.openapi.dto.bo.chicheng;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel(value = "ChichengDataBo", description = "驰诚数据上报请求(家报、独立探头)")
@Data
public class HomeBo {
@ApiModelProperty(value = "消息类型: data(数据上报)、alarm(报警上报)、heartbeat(心跳)", required = true)
private String msgtype;
@ApiModelProperty(value = "软件版本号")
private String software_version;
@ApiModelProperty(value = "信噪比,取值范围: -32768-32767")
private String sinr;
@ApiModelProperty(value = "参考信号接收功率,取值范围: -32768-32767")
private String rsrp;
@ApiModelProperty(value = "时间戳")
private Long timestamp;
@ApiModelProperty(value = "设备IMEI号", required = true)
private String imei;
@ApiModelProperty(value = "ICCID号")
private String iccid;
@ApiModelProperty(value = "设备名称", required = true)
private String devicename;
@ApiModelProperty(value = "数据列表")
private List<DataItem> data;
@ApiModel(value = "DataItem", description = "监测数据项")
@Data
public static class DataItem {
@ApiModelProperty(value = "监测类型/气体类型", required = true)
private String type;
@ApiModelProperty(value = "状态0正常、1低报、2高报、3故障、4离线", required = true)
private String status;
}
}

@ -0,0 +1,53 @@
package cc.iotkit.openapi.dto.bo.chicheng;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel(value = "ChichengDataBo", description = "驰诚数据上报请求(工业控制器)")
@Data
public class IndustryBo {
@ApiModelProperty(value = "消息类型: data(数据上报)、alarm(报警上报)、heartbeat(心跳)", required = true)
private String msgtype;
@ApiModelProperty(value = "软件版本号")
private String software_version;
@ApiModelProperty(value = "信噪比,取值范围: -32768-32767")
private String sinr;
@ApiModelProperty(value = "参考信号接收功率,取值范围: -32768-32767")
private String rsrp;
@ApiModelProperty(value = "时间戳")
private Long timestamp;
@ApiModelProperty(value = "设备IMEI号", required = true)
private String imei;
@ApiModelProperty(value = "ICCID号")
private String iccid;
@ApiModelProperty(value = "设备名称", required = true)
private String devicename;
@ApiModelProperty(value = "数据列表")
private List<IndustryBo.DataItem> data;
@ApiModel(value = "DataItem", description = "监测数据项")
@Data
public static class DataItem{
@ApiModelProperty(value = "探头通道号", required = true)
private String deviceCode;
@ApiModelProperty(value = "监测类型/气体类型", required = true)
private String type;
@ApiModelProperty(value = "数值", required = true)
private String value;
@ApiModelProperty(value = "单位", required = true)
private String unit;
@ApiModelProperty(value = "状态0正常、1低报、2高报、3故障、4离线", required = true)
private String status;
}
}

@ -0,0 +1,44 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.openapi.service;
import cc.iotkit.openapi.dto.bo.chicheng.ChichengThingBo;
import cc.iotkit.openapi.dto.bo.chicheng.DeviceStatusBo;
import cc.iotkit.openapi.dto.bo.chicheng.HomeBo;
import cc.iotkit.openapi.dto.bo.chicheng.IndustryBo;
/**
*
*/
public interface ChichengService {
/**
* &
* */
boolean receiveData1(HomeBo data);
boolean receiveData2(IndustryBo data);
boolean modifyDeviceStatus(DeviceStatusBo data);
boolean receiveThingData(ChichengThingBo data);
}

@ -0,0 +1,296 @@
/*
*
* * | Licensed OPENIITA
* * +----------------------------------------------------------------------
* * | Author: xw2sy@163.com
* * +----------------------------------------------------------------------
*
* Copyright [2024] [OPENIITA]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package cc.iotkit.openapi.service.impl;
import cc.iotkit.common.enums.ErrCode;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.thing.ThingModelMessage;
import cc.iotkit.data.manager.IDeviceInfoData;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.openapi.dto.bo.chicheng.ChichengThingBo;
import cc.iotkit.openapi.dto.bo.chicheng.ChichengUpdDataBo;
import cc.iotkit.openapi.dto.bo.chicheng.DeviceStatusBo;
import cc.iotkit.openapi.dto.bo.chicheng.HomeBo;
import cc.iotkit.openapi.dto.bo.chicheng.IndustryBo;
import cc.iotkit.openapi.service.ChichengService;
import cc.iotkit.temporal.IThingModelMessageData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Slf4j
@Service
public class ChichengServiceImpl implements ChichengService {
@Autowired
private IThingModelMessageData thingModelMessageData;
@Autowired
@Qualifier("deviceInfoDataCache")
private IDeviceInfoData deviceInfoData;
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean receiveData1(HomeBo data) {
String requestId=UUID.randomUUID().toString();
log.info("接收到驰诚的数据mstype={},imei={},deviceName={},data={}",data.getMsgtype(),data.getImei(),data.getMsgtype(),data.getData());
Long time=data.getTimestamp()!=null?data.getTimestamp():System.currentTimeMillis();
switch (data.getMsgtype()){
case "heartbeat":
case "data":
case "alarm":
handleReceiveData(data,time);
break;
default:
log.warn("接收驰诚的数据中出现了未知类i型数据msgtype={},data={}",data.getMsgtype(),data.getData());
break;
}
return true;
}
@Override
public boolean receiveData2(IndustryBo data) {
String requestId=UUID.randomUUID().toString();
log.info("接收到驰诚的数据mstype={},imei={},deviceName={},data={}",data.getMsgtype(),data.getImei(),data.getMsgtype(),data.getData());
Long time=data.getTimestamp()!=null?data.getTimestamp():System.currentTimeMillis();
handleReceiveData(data,time);
return true;
}
@Override
public boolean modifyDeviceStatus(DeviceStatusBo data) {
DeviceInfo device=deviceInfoData.findByDeviceName(data.getDevicename());
if (device == null) {
throw new BizException(ErrCode.DEVICE_NOT_FOUND);
}
if(!data.getMsgtype().equals("online") && !data.getMsgtype().equals("offline")){
throw new BizException(ErrCode.PARAMS_EXCEPTION);
}
device.setState(new DeviceInfo.State(data.getMsgtype().equals("online"),device.getState().getOnlineTime(), device.getState().getOfflineTime()));
deviceInfoData.save(device);
return false;
}
@Override
public boolean receiveThingData(ChichengThingBo data) {
if (data == null || data.getParams() == null || data.getParams().getUpd_data() == null) {
throw new BizException(ErrCode.PARAMS_EXCEPTION);
}
try {
ChichengUpdDataBo updData = objectMapper.readValue(data.getParams().getUpd_data(), ChichengUpdDataBo.class);
Long time = data.getTime() != null ? data.getTime() : System.currentTimeMillis();
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", data.getId());
dataMap.put("version", data.getVersion());
dataMap.put("productKey", data.getProductKey());
dataMap.put("deviceName", data.getDeviceName());
dataMap.put("time", data.getTime());
dataMap.put("method", data.getMethod());
dataMap.put("raw_upd_data", data.getParams().getUpd_data());
dataMap.put("msg_type", updData.getMsg_type());
dataMap.put("error_val", updData.getError_val());
dataMap.put("ch_cnt", updData.getCh_cnt());
dataMap.put("erro_cnt", updData.getErro_cnt());
dataMap.put("alarm_low_cnt", updData.getAlarm_low_cnt());
dataMap.put("alarm_high_cnt", updData.getAlarm_high_cnt());
dataMap.put("offline_cnt", updData.getOffline_cnt());
dataMap.put("fault_state", updData.getFault_state());
dataMap.put("bsp_state", updData.getBsp_state());
dataMap.put("csq", updData.getCsq());
dataMap.put("rtd_val", updData.getRtd_val());
dataMap.put("adc_val", updData.getAdc_val());
dataMap.put("status_val", updData.getStatus_val());
if (updData.getWireless() != null) {
dataMap.put("wireless", updData.getWireless());
}
if (updData.getHost() != null) {
dataMap.put("host", updData.getHost());
}
dataMap.put("channel_status", buildChannelStatus(updData));
ThingModelMessage message = ThingModelMessage.builder()
.mid(UUID.randomUUID().toString())
.deviceId(data.getDeviceName())
.deviceName(data.getDeviceName())
.type(ThingModelMessage.TYPE_PROPERTY)
.identifier(ThingModelMessage.ID_PROPERTY_REPORT)
.code(0)
.data(dataMap)
.time(time)
.occurred(time)
.build();
thingModelMessageData.add(message);
log.info("接收到驰诚设备上报数据msg_type={}, deviceName={}, ch_cnt={}",
updData.getMsg_type(), data.getDeviceName(), updData.getCh_cnt());
} catch (Exception e) {
log.error("解析驰诚设备上报数据失败:{}", e.getMessage(), e);
throw new BizException(ErrCode.PARAMS_EXCEPTION);
}
return true;
}
private List<Map<String, Object>> buildChannelStatus(ChichengUpdDataBo updData) {
List<Map<String, Object>> channelStatus = new ArrayList<>();
Integer[] rtdVal = updData.getRtd_val();
Integer[] statusVal = updData.getStatus_val();
int channelCount = updData.getCh_cnt() != null ? updData.getCh_cnt() : 0;
for (int i = 0; i < channelCount; i++) {
Map<String, Object> channel = new HashMap<>();
channel.put("channel", i + 1);
Integer rtd = rtdVal != null && i < rtdVal.length ? rtdVal[i] : null;
channel.put("rtd_val", rtd);
if (rtd != null) {
if (rtd == 65535) {
channel.put("rtd_desc", "离线");
} else if (rtd == -1) {
channel.put("rtd_desc", "无效");
} else {
channel.put("rtd_desc", "有效");
}
}
Integer status = statusVal != null && i < statusVal.length ? statusVal[i] : null;
channel.put("status_val", status);
channel.put("status_desc", parseStatusDesc(status));
channelStatus.add(channel);
}
return channelStatus;
}
private String parseStatusDesc(Integer status) {
if (status == null) {
return "未知";
}
switch (status) {
case 0:
return "正常";
case 1:
return "低报";
case 2:
return "高报";
case 3:
return "故障";
case 4:
return "离线";
case 5:
return "超量程";
default:
return "未知(" + status + ")";
}
}
/**
*
* */
private void handleReceiveData(IndustryBo data,Long time){
Map<String,Object> data_map=new HashMap<>();
data_map.put("msgtype",data.getMsgtype());
data_map.put("software_version",data.getSoftware_version());
data_map.put("sinr",data.getSinr());
data_map.put("rsrp",data.getRsrp());
data_map.put("timestamp",data.getTimestamp());
data_map.put("imei",data.getImei());
data_map.put("iccid",data.getIccid());
data_map.put("devicename",data.getDevicename());
data_map.put("data",data.getData());
ThingModelMessage message= ThingModelMessage.builder()
.mid(UUID.randomUUID().toString())
.deviceId(data.getImei())
.deviceName(data.getDevicename())
.type(ThingModelMessage.TYPE_PROPERTY)
.identifier(ThingModelMessage.ID_PROPERTY_REPORT)
.code(0)
.data(data_map)
.time(time)
.occurred(time)
.build();
thingModelMessageData.add(message);
}
/**
*
* */
private void handleReceiveData(HomeBo data,Long time){
Map<String,Object> data_map=new HashMap<>();
data_map.put("msgtype",data.getMsgtype());
data_map.put("software_version",data.getSoftware_version());
data_map.put("sinr",data.getSinr());
data_map.put("rsrp",data.getRsrp());
data_map.put("timestamp",data.getTimestamp());
data_map.put("imei",data.getImei());
data_map.put("iccid",data.getIccid());
data_map.put("devicename",data.getDevicename());
data_map.put("data",data.getData());
ThingModelMessage message= ThingModelMessage.builder()
.mid(UUID.randomUUID().toString())
.deviceId(data.getImei())
.deviceName(data.getDevicename())
.type(ThingModelMessage.TYPE_PROPERTY)
.identifier(ThingModelMessage.ID_PROPERTY_REPORT)
.code(0)
.data(data_map)
.time(time)
.occurred(time)
.build();
thingModelMessageData.add(message);
}
}
Loading…
Cancel
Save