feat:添加海为设备相关接口

This commit is contained in:
listom 2024-08-12 18:08:24 +08:00
parent d4722842ff
commit e0389a15da
35 changed files with 1847 additions and 55 deletions

View File

@ -0,0 +1,161 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://w.hanzhenyun.com:3306/wumei2.4?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: wumei2.4
password: rtB8EhbRRYSGyxHw
# 从库数据源
slave:
enabled: false # 从数据源开关/默认关闭
url:
username:
password:
# TDengine数据库
tdengine-server:
enabled: false # 默认不启用TDenginetrue=启用false=不启用
driverClassName: com.taosdata.jdbc.TSDBDriver
url: jdbc:TAOS://fastbee:6030/fastbee_log?timezone=UTC-8&charset=utf-8
username: root
password: taosdata
dbName: fastbee_log
initialSize: 5 # 初始连接数
minIdle: 10 # 最小连接池数量
maxActive: 20 # 最大连接池数量
maxWait: 60000 # 配置获取连接等待超时的时间
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
validationQuery: SELECT 1 FROM DUAL # 配置检测连接是否有效
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: fastbee
login-password: fastbee
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# redis 配置
redis:
host: localhost # 地址
port: 6379 # 端口默认为6379
# database: 1 # 数据库索引
# password: fastbee # 密码
timeout: 10s # 连接超时时间
lettuce:
pool:
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
max-active: 8 # 连接池的最大数据库连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# mqtt 配置
mqtt:
username: fastbee # 账号
password: fastbee # 密码
host-url: tcp://localhost:1883 # mqtt连接tcp地址
client-id: ${random.int} # 客户端Id不能相同采用随机数 ${random.value}
default-topic: test # 默认主题
timeout: 30 # 超时时间
keepalive: 30 # 保持连接
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
# redisson 配置
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 4
# Netty线程池数量
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${fastbee.name}
# 最小空闲连接数
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
# sip 配置
sip:
enabled: false # 是否启用视频监控SIPtrue为启用
## 本地调试时绑定网卡局域网IP设备在同一局域网设备接入IP填写绑定IP
## 部署服务端时默认绑定容器IP设备接入IP填写服务器公网IP
ip: 127.0.0.1
port: 5061 # SIP端口(保持默认)
domain: 3402000000 # 由省级、市级、区级、基层编号组成
id: 34020000002000000001 # 同上,另外增加编号,(可保持默认)
password: 12345678 # 监控设备接入的密码
# 日志配置
logging:
level:
com.fastbee: debug
com.yomahub: debug
org.dromara: warn
org.springframework: warn
# Swagger配置
swagger:
enabled: true # 是否开启swagger
pathMapping: /dev-api # 请求前缀
liteflow:
#FlowExecutor的execute2Future的线程数默认为64
main-executor-works: 64
#FlowExecutor的execute2Future的自定义线程池Builder
main-executor-class: com.fastbee.ruleEngine.config.MainExecutorBuilder
#并行节点的线程池Builder
thread-executor-class: com.fastbee.ruleEngine.config.WhenExecutorBuilder
rule-source-ext-data-map:
# 应用名称,规则链和脚本组件名称需要一致,不要修改
applicationName: fastbee
#是否开启SQL日志
sqlLogEnabled: true
# 规则多时,启用快速加载模式
fast-load: false
#是否开启SQL数据轮询自动刷新机制 默认不开启
pollingEnabled: false
pollingIntervalSeconds: 60
pollingStartSeconds: 60
#以下是chain表的配置
chainTableName: iot_scene
chainApplicationNameField: application_name
chainNameField: chain_name
elDataField: el_data
chainEnableField: enable
#以下是script表的配置
scriptTableName: iot_script
scriptApplicationNameField: application_name
scriptIdField: script_id
scriptNameField: script_name
scriptDataField: script_data
scriptTypeField: script_type
scriptLanguageField: script_language
scriptEnableField: enable

View File

@ -157,3 +157,16 @@ forest: # Forest配置 版本为1.5.36
log-response-content: true # 打开/关闭Forest响应内容日志默认为 false log-response-content: true # 打开/关闭Forest响应内容日志默认为 false
async-mode: platform # [自v1.5.27版本起可用] 异步模式(默认为 platform async-mode: platform # [自v1.5.27版本起可用] 异步模式(默认为 platform
#http请求参数
http: # 最大连接数
maxTotal: 100
# 并发数
defaultMaxPerRoute: 20
# 创建连接的最长时间
connectTimeout: 1000
# 从连接池中获取到连接的最长时间
connectionRequestTimeout: 500
# 数据传输的最长时间
socketTimeout: 10000
# 提交请求前测试连接是否可用
staleConnectionCheckEnabled: true

View File

@ -22,6 +22,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{ {
public static String YYYY = "yyyy"; public static String YYYY = "yyyy";
public static String YYYYMM = "yyyyMM";
public static String YYYY_MM = "yyyy-MM"; public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd"; public static String YYYY_MM_DD = "yyyy-MM-dd";

View File

@ -0,0 +1,54 @@
package com.fastbee.iot.cache;
/**
* 缓存的iot的key 常量
*/
public class DeviceCacheConstants {
/**
* 设备告警推送 redis key连续多次报警时只触发一次
*/
private static final String DEVICE_ALARM_PUSH_KEY = "device_alarm_push:";
/**
* 设备告警 redis key只要触发告警就修改缓存
*/
private static final String DEVICE_ALARM_KEY = "device_alarm:";
/**
* 设备信息 redis key
*/
private static final String DEVICE_LOG_KEY = "device_log:";
/**
* 设备信息 redis key
*/
private static final String DEVICE_INFO_KEY = "device_info:";
/**
* 插入数据库间隔
*/
private static final String DEVICE_INSERT_DB = "device_insert:";
public static String getDeviceAlarmPushKey(String deviceId, String triggerName, String operator, String value) {
return DEVICE_ALARM_PUSH_KEY + deviceId + ":" + triggerName + ":" + operator + ":" + value;
}
public static String getDeviceAlarmKey(String deviceId) {
return DEVICE_ALARM_KEY + deviceId;
}
public static String getDeviceLogKey(String deviceId) {
return DEVICE_LOG_KEY + deviceId;
}
public static String getDeviceInfoKey(Long deviceId) {
return DEVICE_INFO_KEY + deviceId;
}
public static String getDeviceInsertDb(Long deviceId) {
return DEVICE_INSERT_DB + deviceId;
}
}

View File

@ -252,6 +252,7 @@ public class TSLCacheImpl implements ITSLCache {
.setName_en_US(thingsModel.getModelName_en_US()) .setName_en_US(thingsModel.getModelName_en_US())
.setOrder(thingsModel.getModelOrder()) .setOrder(thingsModel.getModelOrder())
.setModelId(thingsModel.getModelId()) .setModelId(thingsModel.getModelId())
.setModelId(thingsModel.getModelId())
.setConfig(thingsModel.getModbusConfig()); .setConfig(thingsModel.getModbusConfig());
return JSONObject.toJSONString(dto); return JSONObject.toJSONString(dto);
})); }));

View File

@ -44,6 +44,8 @@ public class ThingsModel extends BaseEntity
@ApiModelProperty("英文物模型名称") @ApiModelProperty("英文物模型名称")
private String modelName_en_US; private String modelName_en_US;
private String group;
/** 产品ID */ /** 产品ID */
@ApiModelProperty("产品ID") @ApiModelProperty("产品ID")
private Long productId; private Long productId;

View File

@ -0,0 +1,43 @@
package com.fastbee.iot.enums;
public enum ProductTypeEnum {
SOLAR_DEVICE(138, "太阳能供电设备"),
FLOW_METER_DEVICE(139, "流量计设备"),
DOOR_LOCK_DEVICE(140, "门锁控制设备"),
WENSHIDU_SHEBEI(4, "温湿度");
private String name;
private Integer type;
ProductTypeEnum(Integer type, String name) {
this.type = type;
this.name = name;
}
public static ProductTypeEnum getName(Integer type) {
for (ProductTypeEnum scoreEnum : ProductTypeEnum.values()) {
if (scoreEnum.type.equals(type)) {
return scoreEnum;
}
}
return null;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,49 @@
package com.fastbee.iot.enums;
import com.fastbee.common.core.domain.CommonResult;
public enum WaterFertilizerHttpEnum {
_08012101("08012101", "参数不足"),
_08010001("08010001", "设备不存在或云服务器不存在"),
_08010002("08010002", "设备不存在或云服务器不存在"),
_08012102("08012102", "私钥不正确"),
_08012103("08012103", "解密失败"),
_08012104("08012104", "超时过期"),
_08010003("08010003", "操作失败"),
_08012105("08012105", "操作失败"),
_08012106("08012106", "与设备通信失败");
private String name;
private String type;
WaterFertilizerHttpEnum(String type, String name) {
this.type = type;
this.name = name;
}
public static WaterFertilizerHttpEnum getWaterFertilizerHttpEnum(String type) {
for (WaterFertilizerHttpEnum scoreEnum : WaterFertilizerHttpEnum.values()) {
if (scoreEnum.type.equals(type)) {
return scoreEnum;
}
}
return null;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,61 @@
package com.fastbee.iot.haiwei.controller;
import com.fastbee.common.core.domain.CommonResult;
import com.fastbee.common.utils.json.JsonUtils;
import com.fastbee.iot.haiwei.service.HaiWeiService;
import com.fastbee.iot.model.haiwei.CmdHaiWeiVo;
import com.fastbee.iot.model.haiwei.HaiWeiDeviceInfoVo;
import com.fastbee.iot.model.haiwei.HaiWeiVo;
import com.fastbee.iot.model.haiwei.dto.CmdHaiWeiDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Validated
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/haiwei/device")
@Api(tags = "海为设备")
@Slf4j
public class HaiWeiController {
@Resource
HaiWeiService haiWeiService;
/**
* 获取所有水肥设备
*/
@GetMapping("/devices")
@ApiOperation("获取所有海为设备")
public CommonResult<List<HaiWeiVo>> getHaiWeiDevices() {
return haiWeiService.getHaiWeiDevices();
}
/**
* 获取农作物产量统计
*/
@GetMapping("/cache/{deviceId}")
@ApiOperation("获取海为设备缓存信息")
public CommonResult<HaiWeiDeviceInfoVo> getCache(@PathVariable("deviceId") Long deviceId) {
return haiWeiService.getCache(deviceId);
}
/**
* 向grm设备下发指令
*/
@ApiOperation("向海为设备下发指令")
@PostMapping("/cmd")
public CommonResult<CmdHaiWeiVo> cmdDevices(@RequestBody CmdHaiWeiDto cmdHaiWeiDto) {
log.info("向海为设备下发指令:{}", JsonUtils.toJsonString(cmdHaiWeiDto));
return haiWeiService.cmdDevices(cmdHaiWeiDto);
}
}

View File

@ -0,0 +1,18 @@
package com.fastbee.iot.haiwei.service;
import com.fastbee.common.core.domain.CommonResult;
import com.fastbee.iot.model.haiwei.CmdHaiWeiVo;
import com.fastbee.iot.model.haiwei.HaiWeiDeviceInfoVo;
import com.fastbee.iot.model.haiwei.HaiWeiVo;
import com.fastbee.iot.model.haiwei.dto.CmdHaiWeiDto;
import java.util.List;
public interface HaiWeiService {
CommonResult<List<HaiWeiVo>> getHaiWeiDevices();
CommonResult<HaiWeiDeviceInfoVo> getCache(Long deviceId);
CommonResult<CmdHaiWeiVo> cmdDevices(CmdHaiWeiDto cmdGrmDeviceDto);
}

View File

@ -0,0 +1,161 @@
package com.fastbee.iot.haiwei.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.fastbee.common.core.domain.CommonResult;
import com.fastbee.common.core.redis.RedisCache;
import com.fastbee.common.utils.json.JsonUtils;
import com.fastbee.iot.cache.DeviceCacheConstants;
import com.fastbee.iot.cache.ITSLCache;
import com.fastbee.iot.domain.Device;
import com.fastbee.iot.enums.WaterFertilizerHttpEnum;
import com.fastbee.iot.haiwei.service.HaiWeiService;
import com.fastbee.iot.httpclient.HttpAPIController;
import com.fastbee.iot.httpclient.HttpResultDTO;
import com.fastbee.iot.mapper.DeviceMapper;
import com.fastbee.iot.model.ThingsModels.PropertyDto;
import com.fastbee.iot.model.haiwei.CmdHaiWeiVo;
import com.fastbee.iot.model.haiwei.CmdTagVo;
import com.fastbee.iot.model.haiwei.HaiWeiDeviceInfoVo;
import com.fastbee.iot.model.haiwei.HaiWeiVo;
import com.fastbee.iot.model.haiwei.bo.CmdHaiWeiBo;
import com.fastbee.iot.model.haiwei.dto.CmdHaiWeiDto;
import com.fastbee.iot.service.IDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.fastbee.iot.enums.ProductTypeEnum.*;
@Service
@Slf4j
public class HaiWeiServiceImpl implements HaiWeiService {
@Resource
private IDeviceService iDeviceService;
@Resource
private RedisCache redisCache;
@Resource
DeviceMapper deviceMapper;
@Resource
private ITSLCache itslCache;
@Override
public CommonResult<List<HaiWeiVo>> getHaiWeiDevices() {
Device device = new Device();
device.setProductId(Long.valueOf(SOLAR_DEVICE.getType()));
List<Device> devices = iDeviceService.selectDeviceList(device);
device.setProductId(Long.valueOf(FLOW_METER_DEVICE.getType()));
List<Device> devices1 = iDeviceService.selectDeviceList(device);
device.setProductId(Long.valueOf(DOOR_LOCK_DEVICE.getType()));
List<Device> devices2 = iDeviceService.selectDeviceList(device);
devices.addAll(devices1);
devices.addAll(devices2);
List<HaiWeiVo> deviceVos = new ArrayList<>();
for (Device device1 : devices) {
HaiWeiVo haiWeiVo = new HaiWeiVo();
BeanUtil.copyProperties(device1, haiWeiVo);
deviceVos.add(haiWeiVo);
}
return CommonResult.success(deviceVos);
}
@Override
public CommonResult<HaiWeiDeviceInfoVo> getCache(Long deviceId) {
HaiWeiDeviceInfoVo haiWeiDeviceInfoVo =
redisCache.getCacheObject(DeviceCacheConstants.getDeviceLogKey(deviceId.toString()));
if (haiWeiDeviceInfoVo != null) {
if (null != haiWeiDeviceInfoVo.getReceiveTime()) {
//5分钟未更新设备信息任务设备离线
if (System.currentTimeMillis() - haiWeiDeviceInfoVo.getReceiveTime().getTime() >= 1000 * 60 * 5) {
haiWeiDeviceInfoVo.setOnline(false);
}
} else {
haiWeiDeviceInfoVo.setOnline(false);
}
}
return CommonResult.success(haiWeiDeviceInfoVo);
}
@Override
public CommonResult<CmdHaiWeiVo> cmdDevices(CmdHaiWeiDto cmdHaiWeiDto) {
String url = "https://cloud.haiwell.com/api/project/machine/datagroup/setTagsValue";
Device deviceEntity = deviceMapper.selectDeviceByDeviceId(cmdHaiWeiDto.getDeviceId());
CmdHaiWeiVo cmdWaterFertilizerVo = new CmdHaiWeiVo();
cmdWaterFertilizerVo.setDeviceId(cmdHaiWeiDto.getDeviceId());
List<CmdTagVo> cmdTagVos = new ArrayList<>();
Map<String, String> devParams = getDevParams(deviceEntity);
CmdHaiWeiBo cmdWaterFertilizerBo = new CmdHaiWeiBo();
cmdWaterFertilizerBo.setAccount(devParams.get("account"));
cmdWaterFertilizerBo.setMachineCode(devParams.get("machineCode"));
cmdWaterFertilizerBo.setPrivateKey(devParams.get("privateKey"));
cmdWaterFertilizerBo.setWebapiKey(devParams.get("webapiKey"));
//获取该产品下功能模型
com.alibaba.fastjson2.JSONObject thingsModelObject =
com.alibaba.fastjson2.JSONObject.parseObject(itslCache.getCacheThingsModelByProductId(deviceEntity.getProductId()));
com.alibaba.fastjson2.JSONArray thingsList = thingsModelObject.getJSONArray("properties");
List<PropertyDto> properties = thingsList.toList(PropertyDto.class);
Map<String, List<PropertyDto>> stringListMap = properties.stream().collect(Collectors.groupingBy(PropertyDto::getId));
Map<String, String> tags = new HashMap<>();
String group = null;
List<PropertyDto> propertyDtos = stringListMap.get(cmdHaiWeiDto.getNameEn());
if (StringUtils.isEmpty(group)) {
group = propertyDtos.get(0).getGroup();
String[] split = cmdHaiWeiDto.getValue().split("\\.");
tags.put(cmdHaiWeiDto.getNameEn(), split[0]);
cmdWaterFertilizerBo.setGroupTag(group);
cmdWaterFertilizerBo.setTags(tags);
HttpResultDTO duhttpResultDTO = HttpAPIController.doPostWithJsonParamAndHeaders(url,
JsonUtils.toJsonString(cmdWaterFertilizerBo), new HashMap<>());
group = null;
tags.clear();
if (null != duhttpResultDTO && duhttpResultDTO.getCode() == 200) {
Object object = JSON.parse(duhttpResultDTO.getBody());
//请求报错
if (JsonUtils.toJsonString((Map<String, String>) object).contains("error")) {
Object map = ((Map<String, String>) object).get("error");
Object map1 = ((Map<String, String>) map).get("code");
WaterFertilizerHttpEnum waterFertilizerHttpEnum = WaterFertilizerHttpEnum.getWaterFertilizerHttpEnum((String) map1);
return CommonResult.error(500,waterFertilizerHttpEnum.getName());
} else {
Object map = ((Map<String, String>) object).get("result");
Object map1 = ((Map<String, String>) map).get("data");
Map<String, Integer> a = (Map<String, Integer>) map1;
for (String s : a.keySet()) {
CmdTagVo cmdTagVo = new CmdTagVo();
cmdTagVo.setNameEn(s);
Integer s1 = (Integer) a.get(s);
cmdTagVo.setResult(s1.toString());
cmdTagVos.add(cmdTagVo);
}
}
} else {
return CommonResult.error(500,"Http请求异常");
}
}
cmdWaterFertilizerVo.setCmdTagVos(cmdTagVos);
return CommonResult.success(cmdWaterFertilizerVo);
}
public Map<String, String> getDevParams(Device device) {
Map<String, String> devData = new HashMap<>();
devData.put("machineCode", device.getSerialNumber());
String remark = device.getRemark();
String[] split = remark.split(",");
for (String s : split) {
String[] split1 = s.split("_");
devData.put(split1[0], split1[1]);
}
return devData;
}
}

View File

@ -0,0 +1,445 @@
package com.fastbee.iot.httpclient;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fastbee.common.utils.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class HttpAPIController {
private static CloseableHttpClient httpClient;
/**
* 信任SSL证书
*/
static {
try {
SSLContext sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL)
.loadTrustMaterial((x, y) -> true).build();
/**
* 连接超时connectionTimeout-->指的是连接一个url的连接等待时间
* 读取数据超时SocketTimeout-->指的是连接上一个url获取response的返回等待时间
*/
RequestConfig config = RequestConfig.custom().setConnectTimeout(500000).setSocketTimeout(500000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext)
.setSSLHostnameVerifier((x, y) -> true).build();
} catch (Exception e) {
e.printStackTrace();
}
}
@Autowired
private RequestConfig config;
/**
* @description GET---不含参
* @param url
* @return com.mark.dc2.DTO.HttpResultDTO
* @author Mario
* @date 2019/7/23 9:02
*/
/*public HttpResultDTO doGet(String url) throws Exception {
// 声明 http get 请求
HttpGet httpGet = new HttpGet(url);
// 装载配置信息
httpGet.setConfig(config);
// 允许重定向
httpGet.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,true);
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpGet);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}*/
/**
* @description GET---含请求头
* @param url
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @author Mario
* @date 2019/7/23 9:04
*/
/* public HttpResultDTO doGetWithHeaders(String url, Map<String,Object> headers) throws Exception {
// 声明 http get 请求
HttpGet httpGet = new HttpGet(url);
// 装载配置信息
httpGet.setConfig(config);
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpGet.addHeader(key,value);
}
}
// 允许重定向
httpGet.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,true);
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpGet);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}*/
/**
* @description GET---含Map请求参数
* @param url
* @param mapParams
* @return com.mark.dc2.DTO.HttpResultDTO
* @author Mario
* @date 2019/7/23 9:06
*/
/*public HttpResultDTO doGetWithParams(String url, Map<String, Object> mapParams) throws Exception {
// 包装URL
URIBuilder uriBuilder = new URIBuilder(url);
if (mapParams != null) {
// 遍历map,拼接请求参数
for (Map.Entry<String, Object> entry : mapParams.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 调用不带参数的get请求
return this.doGet(uriBuilder.build().toString());
}*/
/**
* @param url
* @param jsonParam
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description POST---含参(请求路径JSON参数串请求头)
* @author Mario
* @date 2019/7/23 9:20
*/
public static HttpResultDTO doPostWithJsonParamAndHeaders(String url, String jsonParam, Map<String, Object> headers) {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpPost.addHeader(key, value);
}
}
// 设置以Json数据方式发送
StringEntity stringEntity = new StringEntity(jsonParam, "utf-8");
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
// 发起请求
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* @description POST--不含参
* @param url
* @return com.mark.dc2.DTO.HttpResultDTO
* @author Mario
* @date 2019/7/23 9:14
*/
/*public HttpResultDTO doPost(String url) throws Exception {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 加入配置信息
httpPost.setConfig(config);
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpPost);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}*/
/**
* @description POST---含参
* @param url
* @param params
* @return com.mark.dc2.DTO.HttpResultDTO
* @author Mario
* @date 2019/7/23 9:16
*/
/*public HttpResultDTO doPostWithParams(String url, Map<String, Object> params) throws Exception {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 加入配置信息
httpPost.setConfig(config);
// 判断map是否为空不为空则进行遍历封装from表单对象
if (params != null) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
// 构造from表单对象
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");
// 把表单放到post里
httpPost.setEntity(urlEncodedFormEntity);
}
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpPost);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}*/
/**
* @param url
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description POST---含请求头
* @author Mario
* @date 2019/7/23 9:17
*/
/*public HttpResultDTO doPostWithHeaders(String url, Map<String, Object> headers) throws Exception {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 加入配置信息
httpPost.setConfig(config);
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpPost.addHeader(key,value);
}
}
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpPost);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}*/
public static HttpResultDTO doGetWithJsonParamAndHeaders(String url, String jsonParam, Map<String, Object> headers) throws Exception {
// 声明httpPost请求
HttpClient httpClient = HttpClientBuilder.create().build();
// Get请求
URIBuilder uriBuilder = new URIBuilder(url);
if (StringUtils.isNotEmpty(jsonParam)) {
List<NameValuePair> nameValuePairList = json2NameValuePairList(JSON.parseObject(jsonParam));
uriBuilder.setParameters(nameValuePairList);
}
HttpGet httpGet = new HttpGet(uriBuilder.build());
// 设置Header
httpGet.setHeader("Content-Type", "application/json");
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpGet.addHeader(key, value);
}
HttpResponse response1 = httpClient.execute(httpGet);
return new HttpResultDTO(response1.getStatusLine().getStatusCode(), EntityUtils.toString(
response1.getEntity(), "UTF-8"));
}
private static List<NameValuePair> json2NameValuePairList(JSONObject params) {
if (params != null && !params.isEmpty()) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (entry.getValue() != null) {
String value = String.valueOf(entry.getValue());
list.add(new BasicNameValuePair(entry.getKey(), value));
}
}
return list;
}
return null;
}
/**
* @param url
* @param jsonParam
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description PUT---含参(请求路径JSON参数串请求头)
* @author Mario
* @date 2019/7/23 9:32
*/
public static HttpResultDTO doPutWithJsonAndHeaders(String url, String jsonParam, Map<String, String> headers) throws Exception {
// 声明httpPut请求
HttpPut httpPut = new HttpPut(url);
//设置header
httpPut.setHeader("Content-type", "application/json");
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpPut.setHeader(entry.getKey(), entry.getValue());
}
}
//组织请求参数
if (StringUtils.isNotEmpty(jsonParam)) {
StringEntity stringEntity = new StringEntity(jsonParam, "utf-8");
httpPut.setEntity(stringEntity);
}
// 发起请求
CloseableHttpResponse response = httpClient.execute(httpPut);
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}
/**
* @param url
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description DELETE---含参(请求路径请求头)
* @author Mario
* @date 2019/7/23 9:37
*/
public static HttpResultDTO doDeleteWithHeaders(String url, Map<String, String> headers) throws Exception {
// 声明httpDelete请求
HttpDelete httpDelete = new HttpDelete(url);
//设置header
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpDelete.setHeader(entry.getKey(), entry.getValue());
}
}
// 发起请求
CloseableHttpResponse response = httpClient.execute(httpDelete);
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}
/**
* @param url
* @param mapParams
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description GET---含Map请求参数且含请求头
* @author Mario
* @date 2019/7/23 9:08
*/
public HttpResultDTO doGetWithParamsAndHeaders(String url, Map<String, Object> mapParams,
Map<String, Object> headers) throws Exception {
// 包装请求行
if (mapParams != null) {
// 包装URL
URIBuilder uriBuilder = new URIBuilder(url);
// 遍历map,拼接请求参数
for (Map.Entry<String, Object> entry : mapParams.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
// 新的请求行
url = uriBuilder.build().toString();
}
// 声明 http get 请求
HttpGet httpGet = new HttpGet(url);
// 装载配置信息
httpGet.setConfig(config);
// 允许重定向
httpGet.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpGet.addHeader(key, value);
}
}
// 发起请求
CloseableHttpResponse response = this.httpClient.execute(httpGet);
// 返回响应代码与内容
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
}
/**
* @param url
* @param mapParams
* @param headers
* @return com.mark.dc2.DTO.HttpResultDTO
* @description POST---含参(请求路径Map参数请求头)
* @author Mario
* @date 2019/7/23 9:22
*/
public HttpResultDTO doPostWithParamsAndHeaders(String url, Map<String, Object> mapParams, Map<String, Object> headers) {
// 声明httpPost请求
HttpPost httpPost = new HttpPost(url);
// 加入配置信息
httpPost.setConfig(config);
// 判断map是否为空不为空则进行遍历封装from表单对象
if (mapParams != null) {
List<NameValuePair> list = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> entry : mapParams.entrySet()) {
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
// 构造from表单对象
UrlEncodedFormEntity urlEncodedFormEntity = null;
try {
urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// 把表单放到post里
httpPost.setEntity(urlEncodedFormEntity);
}
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key).toString();
httpPost.addHeader(key, value);
}
}
// 发起请求
CloseableHttpResponse response = null;
try {
response = this.httpClient.execute(httpPost);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
return new HttpResultDTO(response.getStatusLine().getStatusCode(), EntityUtils.toString(
response.getEntity(), "UTF-8"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,103 @@
package com.fastbee.iot.httpclient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpClientConfig {
@Value("${http.maxTotal}")
private Integer maxTotal;
@Value("${http.defaultMaxPerRoute}")
private Integer defaultMaxPerRoute;
@Value("${http.connectTimeout}")
private Integer connectTimeout;
@Value("${http.connectionRequestTimeout}")
private Integer connectionRequestTimeout;
@Value("${http.socketTimeout}")
private Integer socketTimeout;
@Value("${http.staleConnectionCheckEnabled}")
private boolean staleConnectionCheckEnabled;
/**
* 首先实例化一个连接池管理器设置最大连接数并发连接数
*
* @return
*/
@Bean(name = "httpClientConnectionManager")
public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
//最大连接数
httpClientConnectionManager.setMaxTotal(maxTotal);
//并发数
httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return httpClientConnectionManager;
}
/**
* 实例化连接池设置连接池管理器
* 这里需要以参数形式注入上面实例化的连接池管理器
*
* @param httpClientConnectionManager
* @return
*/
@Bean(name = "httpClientBuilder")
public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
//HttpClientBuilder中的构造方法被protected修饰所以这里不能直接使用new来实例化一个HttpClientBuilder可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionManager(httpClientConnectionManager);
return httpClientBuilder;
}
/**
* 注入连接池用于获取httpClient
*
* @param httpClientBuilder
* @return
*/
@Bean
public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
return httpClientBuilder.build();
}
/**
* Builder是RequestConfig的一个内部类
* 通过RequestConfig的custom方法来获取到一个Builder对象
* 设置builder的连接信息
* 这里还可以设置proxycookieSpec等属性有需要的话可以在此设置
*
* @return
*/
@Bean(name = "builder")
public RequestConfig.Builder getBuilder() {
RequestConfig.Builder builder = RequestConfig.custom();
return builder.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout)
.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
}
/**
* 使用builder构建一个RequestConfig对象
*
* @param builder
* @return
*/
@Bean
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
return builder.build();
}
}

View File

@ -0,0 +1,15 @@
package com.fastbee.iot.httpclient;
import lombok.Data;
import lombok.NonNull;
@Data
public class HttpResultDTO {
// 响应码
@NonNull
private Integer code;
// 响应体
@NonNull
private String body;
}

View File

@ -0,0 +1,41 @@
package com.fastbee.iot.httpclient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class IdleConnectionEvictor extends Thread {
@Autowired
private HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionEvictor() {
super();
super.start();
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
// 关闭失效的连接
connMgr.closeExpiredConnections();
}
}
} catch (InterruptedException ex) {
// 结束
}
}
//关闭清理无效连接的线程
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}

View File

@ -67,6 +67,13 @@ public interface DeviceLogMapper
*/ */
public int saveBatch(@Param("list") List<DeviceLog> list); public int saveBatch(@Param("list") List<DeviceLog> list);
/**
* 创建数据库表
*
* @param tableName 表名称
*/
int createTable(@Param("tableName") String tableName, @Param("id") Long id);
/** /**
* 修改设备日志 * 修改设备日志
* *

View File

@ -0,0 +1,22 @@
package com.fastbee.iot.mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public interface TableMapper {
/**
* 查询collectstatusPmon
*
* @param tableName 表名
* @return collectstatusPmon
*/
public void createTable(String tableName);
public String getTableByName(String tableName);
List<String> getTableNameList(String[] tableNames);
}

View File

@ -17,6 +17,7 @@ import java.util.List;
@Accessors(chain = true) @Accessors(chain = true)
public class PropertyDto public class PropertyDto
{ {
/** 物模型唯一标识符 */ /** 物模型唯一标识符 */
private String id; private String id;
/** 物模型名称 */ /** 物模型名称 */
@ -67,4 +68,8 @@ public class PropertyDto
private String parseType; private String parseType;
private ModbusConfig config; private ModbusConfig config;
private String group;
private Long modelId;
} }

View File

@ -99,6 +99,9 @@ public class ThingsModelValueItem {
private Long modelId; private Long modelId;
private String group;
/** /**
* 上报时间 * 上报时间

View File

@ -1,50 +0,0 @@
package com.fastbee.iot.model.ThingsModels;
import java.util.ArrayList;
import java.util.List;
/**
* 产品分类的Id和名称输出
*
* @author kerwincui
* @date 2021-12-16
*/
public class ThingsModelsDto
{
public ThingsModelsDto(){
properties=new ArrayList<>();
functions=new ArrayList<>();
events=new ArrayList<>();
}
/** 属性 */
private List<PropertyDto> properties;
/** 功能 */
private List<FunctionDto> functions;
/** 事件 */
private List<EventDto> events;
public List<PropertyDto> getProperties() {
return properties;
}
public void setProperties(List<PropertyDto> properties) {
this.properties = properties;
}
public List<FunctionDto> getFunctions() {
return functions;
}
public void setFunctions(List<FunctionDto> functions) {
this.functions = functions;
}
public List<EventDto> getEvents() {
return events;
}
public void setEvents(List<EventDto> events) {
this.events = events;
}
}

View File

@ -0,0 +1,22 @@
package com.fastbee.iot.model.haiwei;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 向grm设备下发指令
*/
@Data
@ApiModel(description = "向水肥设备下发指令")
public class CmdHaiWeiVo {
@ApiModelProperty(value = "设备id")
private Long deviceId;
@ApiModelProperty("属性")
private List<CmdTagVo> cmdTagVos;
}

View File

@ -0,0 +1,19 @@
package com.fastbee.iot.model.haiwei;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 向grm设备下发指令
*/
@Data
@ApiModel(description = "属性")
public class CmdTagVo {
@ApiModelProperty("属性英文名")
private String nameEn;
@ApiModelProperty(value = "写值结果1为成功其他为失败")
private String result;
}

View File

@ -0,0 +1,35 @@
package com.fastbee.iot.model.haiwei;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Data
@ApiModel(description = "海为设备")
public class HaiWeiDeviceInfoVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("设备ID")
private Long deviceId;
@ApiModelProperty("设备是否在线")
private Boolean online = false;
@ApiModelProperty("设备编号")
private String serialNumber;
@ApiModelProperty("设备名称")
private String deviceName;
@ApiModelProperty("属性值key为显示分组")
private List<HaiWeiPropertyVo> propertyList;
@ApiModelProperty("设备接收时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date receiveTime;
}

View File

@ -0,0 +1,23 @@
package com.fastbee.iot.model.haiwei;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 设备属性值
*/
@Data
public class HaiWeiHttpVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("物模型ID")
private Long modelId;
@ApiModelProperty("组名称")
private String group;
@ApiModelProperty("属性中文名")
private String nameCn;
}

View File

@ -0,0 +1,39 @@
package com.fastbee.iot.model.haiwei;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.HashMap;
/**
* 设备属性值
*/
@Data
@ApiModel(description = "海为属性值")
public class HaiWeiPropertyVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("物模型ID")
private Long modelId;
@ApiModelProperty("属性中文名")
private String nameCn;
@ApiModelProperty("属性英文名")
private String nameEn;
@ApiModelProperty("值对应的枚举值")
private HashMap<String,String> enumMap;
@ApiModelProperty("")
private Object value;
@ApiModelProperty("单位")
private String unit;
@ApiModelProperty("加单位的值")
private String valueAndUnit;
}

View File

@ -0,0 +1,137 @@
package com.fastbee.iot.model.haiwei;
import com.fastbee.common.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(description = "设备")
public class HaiWeiVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("设备ID")
private Long deviceId;
private String qvyvma;
@ApiModelProperty("设备名称")
private String deviceName;
@ApiModelProperty("产品分类ID")
private Long categoryId;
@Excel(name = "设备参数")
private String devParams;
private Date tenantTime;
private Date userTime;
/** 产品ID */
@ApiModelProperty("产品ID")
private Long productId;
/** 产品名称 */
@ApiModelProperty("产品名称")
private String productName;
/** 用户ID */
@ApiModelProperty("用户ID")
private Long userId;
/** 用户昵称 */
@ApiModelProperty("用户昵称")
private String userName;
/** 租户ID */
@ApiModelProperty("租户ID")
private Long tenantId;
/** 租户名称 */
@ApiModelProperty("租户名称")
private String tenantName;
/** 设备编号 */
@ApiModelProperty("设备编号")
private String serialNumber;
/** 设备类型1-直连设备、2-网关设备、3-监控设备) */
@ApiModelProperty("设备类型1-直连设备、2-网关设备、3-监控设备)")
private Integer deviceType;
/** 设备状态1-未激活2-禁用3-在线4-离线) */
@ApiModelProperty("设备状态1-未激活2-禁用3-在线4-离线)")
private Integer status;
/** 设备影子 */
@ApiModelProperty("是否启用设备影子(0=禁用1=启用)")
private Integer isShadow;
/** 设备所在地址 */
@ApiModelProperty("设备所在地址")
private String networkAddress;
/** 设备入网IP */
@ApiModelProperty("设备入网IP")
private String networkIp;
/** 设备经度 */
@ApiModelProperty("设备经度")
private BigDecimal longitude;
/** 设备纬度 */
@ApiModelProperty("设备纬度")
private BigDecimal latitude;
/** 激活时间 */
@ApiModelProperty("激活时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date activeTime;
/** 子设备网关编号 */
@ApiModelProperty("子设备网关编号")
private String gwDevCode;
/** 物模型值 */
@ApiModelProperty("物模型值")
private String thingsModelValue;
/** 图片地址 */
@ApiModelProperty("图片地址")
private String imgUrl;
/** 是否自定义位置 **/
@ApiModelProperty("定位方式(1=ip自动定位2=设备定位3=自定义)")
private Integer locationWay;
/** 设备摘要 **/
@ApiModelProperty("设备摘要")
private String summary;
private String isView;
private String viewId;
@ApiModelProperty("厂家id")
private Long factoryId;
@ApiModelProperty("是否是模拟设备")
private Integer isSimulate;
@ApiModelProperty("子设备地址")
private Integer slaveId;
@ApiModelProperty("删除标志")
private String delFlag;
private Integer devType;
private Long projectDikuaiId;
}

View File

@ -0,0 +1,15 @@
package com.fastbee.iot.model.haiwei.bo;
import lombok.Data;
import java.util.Map;
@Data
public class CmdHaiWeiBo {
String account;
String machineCode;
String privateKey;
String webapiKey;
String groupTag;
Map<String,String> tags;
}

View File

@ -0,0 +1,13 @@
package com.fastbee.iot.model.haiwei.bo;
import lombok.Data;
@Data
public class HaiWeiBo {
String account;
String machineCode;
String privateKey;
String webapiKey;
String groupTag;
String[] tags;
}

View File

@ -0,0 +1,24 @@
package com.fastbee.iot.model.haiwei.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 向grm设备下发指令
*/
@Data
@ApiModel(description = "向海为设备下发指令")
public class CmdHaiWeiDto {
@ApiModelProperty(value = "设备id", required = true)
private Long deviceId;
@ApiModelProperty(value = "属性英文名", required = true)
private String nameEn;
@ApiModelProperty(value = "属性对应值", required = true)
private String value;
}

View File

@ -27,6 +27,8 @@ public interface ILogService {
/** 保存设备日志 **/ /** 保存设备日志 **/
int saveDeviceLog(DeviceLog deviceLog); int saveDeviceLog(DeviceLog deviceLog);
int saveDeviceLogList(List<DeviceLog> deviceLogEntityList);
/** /**
* 批量保存日志 * 批量保存日志
*/ */

View File

@ -3,6 +3,7 @@ package com.fastbee.iot.tdengine.service.impl;
import com.fastbee.common.utils.DateUtils; import com.fastbee.common.utils.DateUtils;
import com.fastbee.iot.domain.Device; import com.fastbee.iot.domain.Device;
import com.fastbee.iot.domain.DeviceLog; import com.fastbee.iot.domain.DeviceLog;
import com.fastbee.iot.mapper.TableMapper;
import com.fastbee.iot.model.DeviceStatistic; import com.fastbee.iot.model.DeviceStatistic;
import com.fastbee.iot.model.HistoryModel; import com.fastbee.iot.model.HistoryModel;
import com.fastbee.iot.model.ThingsModelLogCountVO; import com.fastbee.iot.model.ThingsModelLogCountVO;
@ -11,7 +12,10 @@ import com.fastbee.iot.tdengine.service.ILogService;
import com.fastbee.iot.mapper.DeviceLogMapper; import com.fastbee.iot.mapper.DeviceLogMapper;
import com.fastbee.iot.model.MonitorModel; import com.fastbee.iot.model.MonitorModel;
import com.fastbee.iot.tdengine.service.model.TdLogDto; import com.fastbee.iot.tdengine.service.model.TdLogDto;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -24,12 +28,40 @@ import java.util.stream.Collectors;
*/ */
public class MySqlLogServiceImpl implements ILogService { public class MySqlLogServiceImpl implements ILogService {
private String tableName = "iot_device_log_";
private DeviceLogMapper deviceLogMapper; private DeviceLogMapper deviceLogMapper;
@Resource
private TableMapper tableMapper;
public MySqlLogServiceImpl(DeviceLogMapper _deviceLogMapper){ public MySqlLogServiceImpl(DeviceLogMapper _deviceLogMapper){
this.deviceLogMapper=_deviceLogMapper; this.deviceLogMapper=_deviceLogMapper;
} }
/**
* 分库存入
* @param deviceLogEntityList
*/
@Override
public int saveDeviceLogList(List<DeviceLog> deviceLogEntityList){
if(deviceLogEntityList.size() > 0){
//DeviceLog deviceLogEntity = deviceLogEntityList.get(0);
//Date createTime = deviceLogEntity.getCreateTime();
//String ym = DateUtils.parseDateToStr(DateUtils.YYYYMM,createTime);
//String ymTableName = tableName + ym;
//if(null == tableMapper.getTableByName(ymTableName)){
// deviceLogMapper.createTable(ymTableName,1L);
//}
//List<String> stringList = deviceLogEntityList.stream()
// .map(a->a.getSerialNumber())
// .collect(Collectors.toList());
//deviceMapper.batchChangeOnline(stringList);
//return deviceLogMapper.saveBatch(deviceLogEntityList,ymTableName);
}
return 0;
}
/*** /***
* 新增设备日志 * 新增设备日志
* @return * @return

View File

@ -44,6 +44,11 @@ public class TdengineLogServiceImpl implements ILogService {
this.dbName=_tDengineConfig.getDbName(); this.dbName=_tDengineConfig.getDbName();
} }
@Override
public int saveDeviceLogList(List<DeviceLog> deviceLogEntityList) {
return 0;
}
/*** /***
* 新增设备日志 * 新增设备日志
* @return * @return

View File

@ -0,0 +1,224 @@
package com.fastbee.iot.timer;//package com.fastbee.farming;
import com.fastbee.common.core.redis.RedisCache;
import com.fastbee.common.core.redis.RedisKeyBuilder;
import com.fastbee.common.utils.DateUtils;
import com.fastbee.common.utils.json.JsonUtils;
import com.fastbee.iot.cache.DeviceCacheConstants;
import com.fastbee.iot.cache.ITSLCache;
import com.fastbee.iot.domain.Device;
import com.fastbee.iot.domain.DeviceLog;
import com.fastbee.iot.httpclient.HttpAPIController;
import com.fastbee.iot.httpclient.HttpResultDTO;
import com.fastbee.iot.model.ThingsModels.PropertyDto;
import com.fastbee.iot.model.haiwei.bo.HaiWeiBo;
import com.fastbee.iot.model.haiwei.HaiWeiDeviceInfoVo;
import com.fastbee.iot.model.haiwei.HaiWeiPropertyVo;
import com.fastbee.iot.service.IDeviceService;
import com.fastbee.iot.tdengine.service.ILogService;
import com.fastbee.iot.tdengine.service.model.TdLogDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.fastbee.iot.enums.ProductTypeEnum.*;
@Component("qxtrTask")
@Slf4j
public class QxtrTask {
@Autowired
private IDeviceService iDeviceService;
@Resource
private ITSLCache itslCache;
@Autowired
private ILogService iLogService;
@Resource
RedisCache redisCache;
private static Pattern pattern = Pattern.compile("[-+]?[0-9]+(\\.[0-9]+)?$");
/**
* 定时任务 新增太阳能设备
*/
public void getSolarDeviceFromHttp() throws Exception {
log.info("定时任务,新增 太阳能设备 数据");
Device device = new Device();
device.setProductId(Long.valueOf(SOLAR_DEVICE.getType()));
List<Device> devices = iDeviceService.selectDeviceList(device);
getDeviceInfo(Long.valueOf(SOLAR_DEVICE.getType()), devices);
}
/**
* 定时任务 流量计设备
*/
public void getFlowMeterDeviceFromHttp() throws Exception {
log.info("定时任务,新增 流量计设备 数据");
Device device = new Device();
device.setProductId(Long.valueOf(FLOW_METER_DEVICE.getType()));
List<Device> devices = iDeviceService.selectDeviceList(device);
getDeviceInfo(Long.valueOf(FLOW_METER_DEVICE.getType()), devices);
}
/**
* 定时任务 门锁控制设备
*/
public void getDoorLockDeviceFromHttp() throws Exception {
log.info("定时任务,新增 门锁控制设备 数据");
Device device = new Device();
device.setProductId(Long.valueOf(DOOR_LOCK_DEVICE.getType()));
List<Device> devices = iDeviceService.selectDeviceList(device);
getDeviceInfo(Long.valueOf(DOOR_LOCK_DEVICE.getType()), devices);
}
/*//////////////////////////////////////////////////////////////////////////////////////////////////////*/
public void getDeviceInfo(Long productId, List<Device> devices) {
Date createTime = new Date();
getDeviceInfoFromHttp(productId, devices, createTime);
}
public void getDeviceInfoFromHttp(Long productId, List<Device> devices, Date createTime) {
String url = "https://cloud.haiwell.com/api/project/machine/datagroup/getTagsValue";
com.alibaba.fastjson2.JSONObject thingsModelObject =
com.alibaba.fastjson2.JSONObject.parseObject(itslCache.getCacheThingsModelByProductId(productId));
com.alibaba.fastjson2.JSONArray thingsList = thingsModelObject.getJSONArray("properties");
List<PropertyDto> properties = thingsList.toList(PropertyDto.class);
Map<String, List<PropertyDto>> stringListMap = properties.stream().collect(Collectors.groupingBy(PropertyDto::getGroup));
for (Device device : devices) {
try {
Map<String, String> devParams = getDevParams(device);
HaiWeiBo haiWeiBo = new HaiWeiBo();
haiWeiBo.setAccount(devParams.get("account"));
haiWeiBo.setMachineCode(devParams.get("machineCode"));
haiWeiBo.setPrivateKey(devParams.get("privateKey"));
haiWeiBo.setWebapiKey(devParams.get("webapiKey"));
Map<String, String> mapAll = new HashMap<>();
for (String group : stringListMap.keySet()) {
List<PropertyDto> propertyDtos = stringListMap.get(group);
haiWeiBo.setGroupTag(group);
String[] tags = new String[propertyDtos.size()];
for (int i = 0; i < propertyDtos.size(); i++) {
tags[i] = propertyDtos.get(i).getId();
}
haiWeiBo.setTags(tags);
HttpResultDTO duhttpResultDTO = HttpAPIController.doPostWithJsonParamAndHeaders(url, JsonUtils.toJsonString(haiWeiBo),
new HashMap<>());
if (null != duhttpResultDTO && duhttpResultDTO.getCode() == 200) {
Object object = com.alibaba.fastjson.JSON.parse(duhttpResultDTO.getBody()); //先转换成Object
Object map = ((Map<String, String>) object).get("result");
if(!ObjectUtils.isEmpty(map)) {
Object map1 = ((Map<String, String>) map).get("data");
mapAll.putAll((Map<String, String>) map1);
}
}
}
setCacheOrDb(device, mapAll, properties);
} catch (Exception e) {
log.error("getDeviceInfoFromHttp error", e);
}
}
}
private void setCacheOrDb(Device deviceEntity, Map<String, String> map, List<PropertyDto> propertyDtos) {
HaiWeiDeviceInfoVo haiWeiDeviceInfoVo = new HaiWeiDeviceInfoVo();
List<HaiWeiPropertyVo> propertyList = new ArrayList<>();
haiWeiDeviceInfoVo.setDeviceId(deviceEntity.getDeviceId());
haiWeiDeviceInfoVo.setSerialNumber(deviceEntity.getSerialNumber());
haiWeiDeviceInfoVo.setDeviceName(deviceEntity.getDeviceName());
haiWeiDeviceInfoVo.setReceiveTime(new Date());
haiWeiDeviceInfoVo.setOnline(true);
for (PropertyDto propertyDto : propertyDtos) {
HaiWeiPropertyVo haiWeiPropertyVo = new HaiWeiPropertyVo();
haiWeiPropertyVo.setModelId(Long.valueOf(propertyDto.getModelId()));
haiWeiPropertyVo.setNameCn(propertyDto.getName());
haiWeiPropertyVo.setNameEn(propertyDto.getId());
com.alibaba.fastjson2.JSONObject datatype = propertyDto.getDatatype();
Object type = datatype.get("type");
//值类型如果是枚举
if ("enum".equals(type)) {
ArrayList<Map> enumList = (ArrayList) datatype.get("enumList");
HashMap<String, String> a = new HashMap<>();
for (Map map1 : enumList) {
a.put((String) map1.get("value"), (String) map1.get("text"));
}
haiWeiPropertyVo.setEnumMap(a);
} else {
haiWeiPropertyVo.setUnit((String) datatype.get("unit"));
}
String s = map.get(propertyDto.getId());
//拿到属性值
if (!ObjectUtils.isEmpty(s)) {
//值为数字取小数点后两位
boolean matches = pattern.matcher(s).matches();
if (matches) {
BigDecimal roundedNumber = new BigDecimal(Double.valueOf(s)).setScale(2, BigDecimal.ROUND_HALF_UP);
s = String.valueOf(roundedNumber);
}
haiWeiPropertyVo.setValue(s);
} else {
haiWeiPropertyVo.setValue("");
}
haiWeiPropertyVo.setValueAndUnit(haiWeiPropertyVo.getValue() + haiWeiPropertyVo.getUnit());
propertyList.add(haiWeiPropertyVo);
}
haiWeiDeviceInfoVo.setPropertyList(propertyList);
//插入缓存
redisCache.setCacheObject(DeviceCacheConstants.getDeviceLogKey(deviceEntity.getDeviceId().toString()), haiWeiDeviceInfoVo);
//插入数据库
List<DeviceLog> deviceLogEntityList = new ArrayList<>();
for (HaiWeiPropertyVo waterFertilizePropertyVo : propertyList) {
DeviceLog deviceLogEntity = new DeviceLog();
deviceLogEntity.setLogValue(waterFertilizePropertyVo.getValue().toString());
deviceLogEntity.setIdentity(waterFertilizePropertyVo.getNameEn());
deviceLogEntity.setModelName(waterFertilizePropertyVo.getNameCn());
deviceLogEntity.setDeviceId(deviceEntity.getDeviceId());
deviceLogEntity.setSerialNumber(deviceEntity.getSerialNumber());
deviceLogEntity.setDeviceName(deviceEntity.getDeviceName());
deviceLogEntity.setLogType(1);
deviceLogEntity.setCreateTime(new Date());
deviceLogEntity.setIsMonitor(0);
deviceLogEntity.setMode(2);
deviceLogEntityList.add(deviceLogEntity);
redisCache.zSetAdd(RedisKeyBuilder.buildDeviceOnlineListKey(), deviceLogEntity.getSerialNumber(), DateUtils.getTimestampSeconds());
}
if (deviceLogEntityList.size() > 0) {
String key = DeviceCacheConstants.getDeviceInsertDb(deviceEntity.getDeviceId());
Object cacheObject = redisCache.getCacheObject(key);
//10分钟插入数据库一次
if (null == cacheObject) {
redisCache.setCacheObject(key, 0, 10, TimeUnit.MINUTES);
TdLogDto dto = new TdLogDto();
dto.setSerialNumber(deviceEntity.getSerialNumber());
dto.setList(deviceLogEntityList);
iLogService.saveBatch(dto);
}
}
}
public Map<String, String> getDevParams(Device device) {
Map<String, String> devData = new HashMap<>();
devData.put("machineCode", device.getSerialNumber());
String remark = device.getRemark();
String[] split = remark.split(",");
for (String s : split) {
String[] split1 = s.split("_");
devData.put(split1[0],split1[1]);
}
return devData;
}
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fastbee.iot.mapper.TableMapper">
<!--创建表的 SQL 语句-->
<update id="createTable" parameterType="java.lang.String">
CREATE TABLE IF NOT EXISTS `${tableName}`
(
`id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
`group_id` int(0) NULL DEFAULT NULL COMMENT '组号',
`username` varchar(20) NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(20) NULL DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 9
CHARACTER SET = utf8mb4 COMMENT ='用于测试的用户表';
</update>
<select id="getTableByName" resultType="java.lang.String">
select table_name from information_schema.tables where TABLE_SCHEMA=(select database())
and table_name = #{tableName}
</select>
<select id="getTableNameList" resultType="java.lang.String">
select table_name from information_schema.tables where TABLE_SCHEMA=(select database())
and table_name in
<foreach item="tableName" collection="array" open="(" separator="," close=")">
#{tableName}
</foreach>
</select>
</mapper>

View File

@ -17,6 +17,7 @@
<result property="datatype" column="datatype"/> <result property="datatype" column="datatype"/>
<result property="formula" column="formula"/> <result property="formula" column="formula"/>
<result property="specs" column="specs"/> <result property="specs" column="specs"/>
<result property="group" column="group"/>
<result property="isChart" column="is_chart"/> <result property="isChart" column="is_chart"/>
<result property="isSharePerm" column="is_share_perm"/> <result property="isSharePerm" column="is_share_perm"/>
<result property="isHistory" column="is_history"/> <result property="isHistory" column="is_history"/>
@ -58,6 +59,7 @@
datatype, datatype,
formula, formula,
specs, specs,
group,
is_chart, is_chart,
is_share_perm, is_share_perm,
is_history, is_history,
@ -83,7 +85,7 @@
end as model_name, end as model_name,
m.model_name as model_name_zh_cn, t.en_us as model_name_en_us, m.model_name as model_name_zh_cn, t.en_us as model_name_en_us,
m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula, m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula,
m.specs, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by, m.specs,m.group, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by,
m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order
from iot_things_model m from iot_things_model m
left join iot_things_model_translate t on m.model_id = t.id left join iot_things_model_translate t on m.model_id = t.id
@ -138,7 +140,7 @@
else m.model_name else m.model_name
end as model_name, end as model_name,
m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula, m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula,
m.specs, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by, m.specs,m.group, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by,
m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order
from iot_things_model m from iot_things_model m
left join iot_things_model_translate t on m.model_id = t.id left join iot_things_model_translate t on m.model_id = t.id
@ -156,7 +158,7 @@
else m.model_name else m.model_name
end as model_name, end as model_name,
m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula, m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula,
m.specs, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by, m.specs, m.group,m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by,
m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order
from iot_things_model m from iot_things_model m
left join iot_things_model_translate t on m.model_id = t.id left join iot_things_model_translate t on m.model_id = t.id
@ -171,7 +173,7 @@
else m.model_name else m.model_name
end as model_name, end as model_name,
m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula, m.product_id, m.product_name, m.tenant_id, m.tenant_name, m.identifier, m.type, m.datatype, m.formula,
m.specs, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by, m.specs,m.group, m.is_chart, m.is_share_perm, m.is_history, m.is_monitor, m.is_app, m.del_flag, m.create_by,
m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order m.create_time, m.update_by, m.update_time, m.remark, m.is_readonly, m.model_order
from iot_things_model m from iot_things_model m
left join iot_things_model_translate t on m.model_id = t.id left join iot_things_model_translate t on m.model_id = t.id
@ -219,6 +221,9 @@
<if test="specs != null and specs != ''"> <if test="specs != null and specs != ''">
specs, specs,
</if> </if>
<if test="group != null and group != ''">
group,
</if>
<if test="isChart != null"> <if test="isChart != null">
is_chart, is_chart,
</if> </if>
@ -290,6 +295,9 @@
<if test="specs != null and specs != ''"> <if test="specs != null and specs != ''">
#{specs}, #{specs},
</if> </if>
<if test="group != null and group != ''">
#{group},
</if>
<if test="isChart != null"> <if test="isChart != null">
#{isChart}, #{isChart},
</if> </if>
@ -344,6 +352,7 @@
type, type,
datatype, datatype,
specs, specs,
group,
is_chart, is_chart,
is_share_perm, is_share_perm,
is_history, is_history,
@ -359,7 +368,7 @@
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
#{model.modelName},#{model.productId},#{model.productName},#{model.tenantId}, #{model.modelName},#{model.productId},#{model.productName},#{model.tenantId},
#{model.tenantName},#{model.identifier},#{model.type},#{model.datatype}, #{model.tenantName},#{model.identifier},#{model.type},#{model.datatype},
#{model.specs},#{model.isChart},#{model.isSharePerm},#{model.isHistory}, #{model.specs},#{model.group},#{model.isChart},#{model.isSharePerm},#{model.isHistory},
#{model.isMonitor},#{model.isApp},#{model.isReadonly},#{model.createBy},#{model.createTime}, #{model.isMonitor},#{model.isApp},#{model.isReadonly},#{model.createBy},#{model.createTime},
#{model.formula} #{model.formula}
</trim> </trim>
@ -399,6 +408,9 @@
<if test="specs != null and specs != ''"> <if test="specs != null and specs != ''">
specs = #{specs}, specs = #{specs},
</if> </if>
<if test="group != null and group != ''">
group = #{group},
</if>
<if test="isChart != null"> <if test="isChart != null">
is_chart = #{isChart}, is_chart = #{isChart},
</if> </if>