保存设备时下发命令,修改设备参数结构

This commit is contained in:
邱贞招 2023-11-18 00:22:56 +08:00
parent 3f2550140b
commit 12a6d3ed5e
11 changed files with 525 additions and 79 deletions

View File

@ -15,6 +15,20 @@ ruoyi:
# 验证码类型 math 数字计算 char 字符验证 # 验证码类型 math 数字计算 char 字符验证
captchaType: math captchaType: math
watering:
iotUrl: https://iot-api.heclouds.com/datapoint
# 产品id 浇花器
productId: 50dd83E8zQ
# 版本号 签名算法版本
version: 2020-05-29
# 用户资源信息 用户id
resourceName: userid/143831
# iot秘钥
accessKey: dJqF0qYhUbK/o1Pr9I5qxNoP14FlJLC+BFK2ZTjUX+lnKwoNYvBYsM/7Xu1ERIzSkUoxVkP/N1RMvGlBKMoBtA==
# 超时响应时间(秒)
timeout: 10
# token过期时间
daysToExpire: 100
# 开发环境配置 # 开发环境配置
server: server:
# 服务器的HTTP端口默认为8080 # 服务器的HTTP端口默认为8080

View File

@ -91,4 +91,67 @@ public class HttpStatus
* 系统警告消息 * 系统警告消息
*/ */
public static final int WARN = 601; public static final int WARN = 601;
/**----------------------------IOT错误码start----------------------------*/
/**
* 成功
*/
public static final String IOT_SUCCESS = "0";
/**
* 错误码 新增设备失败设备已存在
*/
public static final String ERROR_CODE_DEVICE_ALREADY_EXISTS = "10406";
/**
* 错误码 设备不存在
*/
public static final String ERROR_CODE_DEVICE_NON_EXISTENT = "10410";
/**
* 错误码 设备属性设置失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_SET_FAIL = "10411";
/**
* 错误码 设备属性期望设置失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_DESIRE_SET_FAIL = "10412";
/**
* 错误码 设备属性期望查询失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_DESIRE_QUERY_FAIL = "10413";
/**
* 错误码 设备属性获取失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_DESIRE_GET_FAIL = "10414";
/**
* 错误码 设备服务调用失败
*/
public static final String ERROR_CODE_DEVICE_SERVICE_CALL_FAIL = "10415";
/**
* 错误码 设备属性期望删除失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_DESIRE_DALETE_FAIL = "10416";
/**
* 错误码 设备最新数据查询失败
*/
public static final String ERROR_CODE_DEVIE_NEW_DATA_QUERY_FAIL = "10417";
/**
* 错误码 设备属性历史数据查询失败
*/
public static final String ERROR_CODE_DEVICE_ATTRIBUTE_HISTORY_QUERY_FAIL = "10418";
/**
* 错误码 设备事件历史数据查询失败
*/
public static final String ERROR_CODE_DEVICE_EVENT_HISTORY_DATA_QUERY_FAIL = "10419";
/**
* 错误码 设备操作记录查询失败
*/
public static final String ERROR_CODE_DEVICE_OPERATE_RECORD_QUERY_FAIL = "10420";
/**
* 错误码 设备不在线
*/
public static final String ERROR_CODE_DEVICE_NOT_ONLINE = "10421";
/**----------------------------IOT错误码end----------------------------*/
} }

View File

@ -0,0 +1,79 @@
package com.ruoyi.common.constant;
/**
* iot常量信息
*
* @author ruoyi
*/
public class IotConstants {
/**
* 时间单位 分钟
*/
public static final String TIME_MIN = "min";
/**
* 时间单位 小时
*/
public static final String TIME_HOUR = "hour";
/**
* 命令分隔符 @
*/
public static final String COMMAND_SEPARATOR = "@";
/**----------------------------地址start----------------------------*/
/**
* 命令下发地址
*/
public static final String ADDS_COMMAND = "/synccmds";
/**
* 设备数据点地址
*/
public static final String ADDS_HISTORY_DATAPOINTS = "/history-datapoints";
/**
* 设备数据点地址
*/
public static final String ADDS_CURRENT_DATAPOINTS = "/current-datapoints";
/**----------------------------地址end----------------------------*/
/**----------------------------命令start----------------------------*/
/**
* 命令 打开
*/
public static final String COMMAND_OPEN = "open";
/**
* 命令 关闭
*/
public static final String COMMAND_CLOSE = "close";
/**----------------------------命令end----------------------------*/
/**----------------------------启动模式start----------------------------*/
/**
* 启动模式 0-手动模式2-土壤湿度低启动
*/
public static final String START_MODE_MANUAL = "0";
/**
* 启动模式 1-定时模式
*/
public static final String START_MODE_REGULAR = "1";
/**
* 启动模式 2-土壤湿度低启动
*/
public static final String START_MODE_HUMIDITY = "2";
/**----------------------------启动模式end----------------------------*/
}

View File

@ -188,6 +188,78 @@ public class HttpUtils
} }
return result.toString(); return result.toString();
} }
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPostWithToken(String url, String param, String token)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setRequestProperty("Authorization", token);
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
public static String sendSSLPost(String url, String param) public static String sendSSLPost(String url, String param)
{ {

View File

@ -0,0 +1,87 @@
package com.ruoyi.common.utils.onenet;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.http.HttpUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Token {
// IP地址查询
public static final String URL = "http://iot-api.heclouds.com/datapoint/history-datapoints";
public static final String synccmdsUrl = "http://iot-api.heclouds.com/datapoint/synccmds?product_id=50dd83E8zQ&device_name=4827E2945C54&timeout=10";
public static String assembleToken(String version, String resourceName, String expirationTime, String signatureMethod, String accessKey)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
StringBuilder sb = new StringBuilder();
String res = URLEncoder.encode(resourceName, "UTF-8");
String sig = URLEncoder.encode(generatorSignature(version, resourceName, expirationTime, accessKey, signatureMethod), "UTF-8");
sb.append("version=")
.append(version)
.append("&res=")
.append(res)
.append("&et=")
.append(expirationTime)
.append("&method=")
.append(signatureMethod)
.append("&sign=")
.append(sig);
return sb.toString();
}
public static String generatorSignature(String version, String resourceName, String expirationTime, String accessKey, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version;
String signature;
byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
signature = Base64.getEncoder().encodeToString(bytes);
return signature;
}
public static byte[] HmacEncrypt(String data, String key, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKeySpec signinKey = null;
signinKey = new SecretKeySpec(Base64.getDecoder().decode(key),
"Hmac" + signatureMethod.toUpperCase());
//生成一个指定 Mac 算法 Mac 对象
Mac mac = null;
mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());
//用给定密钥初始化 Mac 对象
mac.init(signinKey);
//完成 Mac 操作
return mac.doFinal(data.getBytes());
}
public enum SignatureMethod {
SHA1, MD5, SHA256;
}
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
String version = "2020-05-29";//签名算法版本
String resourceName = "userid/143831";//用户id
String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";//过期时间
String signatureMethod = SignatureMethod.SHA256.name().toLowerCase();//签名方式
String accessKey = "dJqF0qYhUbK/o1Pr9I5qxNoP14FlJLC+BFK2ZTjUX+lnKwoNYvBYsM/7Xu1ERIzSkUoxVkP/N1RMvGlBKMoBtA==";
String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
System.out.println("Authorization:" + token);
String rspStr = HttpUtils.sendGet(URL, token, Constants.UTF8);
HttpUtils.sendPostWithToken(synccmdsUrl,"",token);
// HttpUtils.sendGet()
}
}

View File

@ -17,9 +17,9 @@ export function getDevice(deviceId) {
}) })
} }
// 手动浇水 // 手动浇水
export function watering(deviceId) { export function watering(deviceId,wateringSwitch) {
return request({ return request({
url: '/device/device/watering/' + deviceId, url: '/device/device/watering/' + deviceId+"/"+wateringSwitch,
method: 'get' method: 'get'
}) })
} }

View File

@ -140,13 +140,6 @@
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['device:device:edit']" v-hasPermi="['device:device:edit']"
>修改</el-button> >修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-caret-right"
@click="handleWatering(scope.row)"
v-hasPermi="['device:device:watering']"
>手动浇水</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -248,18 +241,18 @@
</el-form-item> </el-form-item>
<div class="fontdesc margin-40px">按照间隔时间进行定时浇水</div> <div class="fontdesc margin-40px">按照间隔时间进行定时浇水</div>
<div class="div1" > <div class="div1" >
<span class="span1">浇水间隔时间</span> <span class="span1">启动时间</span>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.intervalTime.min"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.startMin"></el-input-number>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.intervalTime.hour"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.startHour"></el-input-number>
</div> </div>
<div class="div1"> <div class="div1">
<span class="span1">浇水时间</span> <span class="span1">喷洒时间</span>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.sprayTime.sec"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.sprayTimeSec"></el-input-number>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.regularWateringJsonObj.sprayTime.min"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.sprayTimeMin"></el-input-number>
</div> </div>
<div class="div1 font11"> <div class="div1 font11">
<span>单次浇水时间不可超过20分钟防止电机过度发热浇水量大可缩短浇水间隔时间</span> <span>单次浇水时间不可超过20分钟防止电机过度发热浇水量大可缩短浇水间隔时间</span>
@ -287,14 +280,14 @@
</el-form-item> </el-form-item>
<div class="fontdesc margin-40px">开启脉冲将会浇水停止相互循环</div> <div class="fontdesc margin-40px">开启脉冲将会浇水停止相互循环</div>
<div class="div1" > <div class="div1" >
<span class="span1">浇水时间</span> <span class="span1">喷洒时间</span>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.pulseModeParamObj.sprayTime"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.pulseModeParamObj.sprayTime"></el-input-number>
</div> </div>
<div class="div1"> <div class="div1">
<span class="span1">停止时间</span> <span class="span1">间隔时间</span>
<span class="span3"></span> <span class="span3"></span>
<el-input-number class="span2" size="mini" v-model="form.pulseModeParamObj.endTime"></el-input-number> <el-input-number class="span2" size="mini" v-model="form.pulseModeParamObj.intervalTime"></el-input-number>
</div> </div>
</el-col> </el-col>
@ -312,6 +305,7 @@
</el-slider> </el-slider>
</el-col> </el-col>
<!-- 息屏 -->
<el-col :span="12"> <el-col :span="12">
<el-form-item label="息屏" prop="screenRestTime" class="margin-top20"> <el-form-item label="息屏" prop="screenRestTime" class="margin-top20">
<el-select v-model="form.screenRestTime" placeholder="请选择息屏时间"> <el-select v-model="form.screenRestTime" placeholder="请选择息屏时间">
@ -325,9 +319,15 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="手动浇水" prop="wateringSwitch" class="margin-top20">
<el-switch
v-model="wateringSwitch"
active-value="1"
inactive-value="0"
@change="handleWatering()"
class="drawer-switch switch-margin" active-color="#13ce66"/>
</el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
@ -336,8 +336,6 @@
</el-col> </el-col>
</el-col> </el-col>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" @click="submitForm"> </el-button>
@ -359,6 +357,7 @@ export default {
dicts: ['as_pulse_mode', 'as_screen_rest_time', 'as_online_status', 'as_water_intensity'], dicts: ['as_pulse_mode', 'as_screen_rest_time', 'as_online_status', 'as_water_intensity'],
data() { data() {
return { return {
wateringSwitch: null,
intervalTime: null, intervalTime: null,
sprayTime: null, sprayTime: null,
//湿 //湿
@ -412,18 +411,15 @@ export default {
}, },
// //
form: { form: {
sprayTimeMin:null,//
sprayTimeSec:null,//
/**1.定时浇水开关*/ /**1.定时浇水开关*/
regularWatering:false, regularWatering:false,
//json {"intervalTime":{"hour":1,"min":1},"sprayTime":{"min":1,"sec":1}} //json {"intervalTime":{"hour":1,"min":1},"sprayTime":{"min":1,"sec":1}}
regularWateringJsonObj:{ regularWateringJsonObj:{
intervalTime:{ startHour: null,
hour:1, startMin: null,
min:1 sprayTime: null,
},
sprayTime:{
min:1,
sec:1
}
}, },
regularWateringJson:null, regularWateringJson:null,
/**2.智能土壤湿度开关*/ /**2.智能土壤湿度开关*/
@ -437,8 +433,8 @@ export default {
pulseMode:false, pulseMode:false,
// {"sprayTime":1,"endTime":1} // {"sprayTime":1,"endTime":1}
pulseModeParamObj:{ pulseModeParamObj:{
sprayTime:1, sprayTime: null,
endTime:1 intervalTime: null
}, },
pulseModeParam:null, pulseModeParam:null,
@ -495,17 +491,14 @@ export default {
// //
reset() { reset() {
this.form = { this.form = {
sprayTimeMin:null,//
sprayTimeSec:null,//
/**1.定时浇水开关*/ /**1.定时浇水开关*/
//json {"intervalTime":{"hour":1,"min":1},"sprayTime":{"min":1,"sec":1}} //json {"intervalTime":{"hour":1,"min":1},"sprayTime":{"min":1,"sec":1}}
regularWateringJsonObj:{ regularWateringJsonObj:{
intervalTime:{ startHour: null,
hour:null, startMin: null,
min:null sprayTime: null,
},
sprayTime:{
min:null,
sec:null
}
}, },
regularWateringJson:null, regularWateringJson:null,
/**2.智能土壤湿度开关*/ /**2.智能土壤湿度开关*/
@ -514,8 +507,8 @@ export default {
/**3.脉冲模式开关*/ /**3.脉冲模式开关*/
// {"sprayTime":1,"endTime":1} // {"sprayTime":1,"endTime":1}
pulseModeParamObj:{ pulseModeParamObj:{
sprayTime:null, sprayTime: null,
endTime:null intervalTime: null
}, },
pulseModeParam:null, pulseModeParam:null,
/**3.水流强度开关*/ /**3.水流强度开关*/
@ -598,6 +591,9 @@ export default {
/** 参数解析成对象*/ /** 参数解析成对象*/
this.form.pulseModeParamObj = JSON.parse(this.form.pulseModeParam); this.form.pulseModeParamObj = JSON.parse(this.form.pulseModeParam);
this.form.regularWateringJsonObj = JSON.parse(this.form.regularWateringJson); this.form.regularWateringJsonObj = JSON.parse(this.form.regularWateringJson);
const sprayTime = this.form.regularWateringJsonObj.sprayTime;
this.form.sprayTimeMin = Math.trunc(sprayTime / 60);
this.form.sprayTimeSec = sprayTime % 60;
this.form.regularWatering = JSON.parse(this.form.regularWatering); this.form.regularWatering = JSON.parse(this.form.regularWatering);
this.form.pulseMode = JSON.parse(this.form.pulseMode); this.form.pulseMode = JSON.parse(this.form.pulseMode);
this.form.soilMoisture = JSON.parse(this.form.soilMoisture); this.form.soilMoisture = JSON.parse(this.form.soilMoisture);
@ -607,17 +603,18 @@ export default {
}); });
}, },
/** 手动浇水 */ /** 手动浇水 */
handleWatering(row) { handleWatering() {
this.reset(); const deviceId = this.form.deviceId;
const deviceId = row.deviceId || this.ids const wateringSwitch = this.wateringSwitch;
watering(deviceId).then(response => { watering(deviceId,wateringSwitch).then(response => {
this.$modal.msgSuccess("手动浇水"); this.$modal.msg(response.msg);
}); });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
this.form.regularWateringJsonObj.sprayTime = this.form.sprayTimeMin*60 + this.form.sprayTimeSec;
this.form.pulseModeParam = JSON.stringify(this.form.pulseModeParamObj); this.form.pulseModeParam = JSON.stringify(this.form.pulseModeParamObj);
this.form.regularWateringJson = JSON.stringify(this.form.regularWateringJsonObj); this.form.regularWateringJson = JSON.stringify(this.form.regularWateringJsonObj);
if (this.form.deviceId != null) { if (this.form.deviceId != null) {
@ -669,7 +666,6 @@ export default {
.fontdesc{ .fontdesc{
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
/*margin-left: 5px*/
} }
.margin-40px{ .margin-40px{
@ -686,11 +682,6 @@ export default {
.div1{ .div1{
margin-left: 20px; margin-left: 20px;
padding: 5px 0 0 0; padding: 5px 0 0 0;
/*border: none;*/
/*outline: none;*/
/*background-color: transparent;*/
/*cursor: pointer;*/
/*width: 90%;*/
height: 40px; height: 40px;
} }
.div1:hover{ .div1:hover{

View File

@ -76,11 +76,11 @@ public class AsDeviceController extends BaseController
* 获取设备列表详细信息 手动浇水 * 获取设备列表详细信息 手动浇水
*/ */
@PreAuthorize("@ss.hasPermi('device:device:query')") @PreAuthorize("@ss.hasPermi('device:device:query')")
@GetMapping(value = "/watering/{deviceId}") @GetMapping(value = "/watering/{deviceId}/{wateringSwitch}")
public AjaxResult watering(@PathVariable("deviceId") Long deviceId) public AjaxResult watering(@PathVariable("deviceId") Long deviceId,@PathVariable("wateringSwitch") Integer wateringSwitch)
{ {
AsDevice device = asDeviceService.selectAsDeviceByDeviceId(deviceId); AsDevice device = asDeviceService.selectAsDeviceByDeviceId(deviceId);
return asDeviceService.watering(device); return asDeviceService.watering(device,wateringSwitch);
} }
/** /**

View File

@ -4,6 +4,7 @@ import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
@ -16,6 +17,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
*/ */
@Data @Data
@TableName(value = "as_watering_record") @TableName(value = "as_watering_record")
@Builder
public class AsWateringRecord extends BaseEntity public class AsWateringRecord extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -67,5 +67,5 @@ public interface IAsDeviceService
* @param device 设备列表主键 * @param device 设备列表主键
* @return 结果 * @return 结果
*/ */
public AjaxResult watering(AsDevice device); public AjaxResult watering(AsDevice device,Integer wateringSwitch);
} }

View File

@ -1,26 +1,31 @@
package com.ruoyi.device.service.impl; package com.ruoyi.device.service.impl;
import java.util.List;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.constant.IotConstants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.mqtt.MqttPushClient; import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.device.domain.AsDeviceClassify; import com.ruoyi.common.utils.onenet.Token;
import com.ruoyi.device.domain.AsDeviceVersion; import com.ruoyi.device.domain.*;
import com.ruoyi.device.domain.AsModel; import com.ruoyi.device.mapper.*;
import com.ruoyi.device.mapper.AsDeviceClassifyMapper;
import com.ruoyi.device.mapper.AsDeviceVersionMapper;
import com.ruoyi.device.mapper.AsModelMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
import com.ruoyi.device.mapper.AsDeviceMapper;
import com.ruoyi.device.domain.AsDevice;
import com.ruoyi.device.service.IAsDeviceService; import com.ruoyi.device.service.IAsDeviceService;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.ruoyi.common.utils.SecurityUtils.getUsername;
/** /**
* 设备列表Service业务层处理 * 设备列表Service业务层处理
@ -31,6 +36,9 @@ import javax.annotation.Resource;
@Service @Service
public class AsDeviceServiceImpl extends ServiceImpl<AsDeviceMapper, AsDevice> implements IAsDeviceService public class AsDeviceServiceImpl extends ServiceImpl<AsDeviceMapper, AsDevice> implements IAsDeviceService
{ {
private static final Logger logger = LoggerFactory.getLogger(AsDeviceServiceImpl.class);
@Resource @Resource
private AsDeviceMapper asDeviceMapper; private AsDeviceMapper asDeviceMapper;
@ -46,10 +54,30 @@ public class AsDeviceServiceImpl extends ServiceImpl<AsDeviceMapper, AsDevice> i
@Resource @Resource
private AsDeviceVersionMapper versionMapper; private AsDeviceVersionMapper versionMapper;
@Resource @Resource
private MqttPushClient mqttPushClient; private AsWateringRecordMapper wateringRecordMapper;
@Value(value = "${watering.iotUrl}")
private String iotUrl;
@Value(value = "${watering.productId}")
private String productId;
@Value(value = "${watering.version}")
private String version;
@Value(value = "${watering.resourceName}")
private String resourceName;
@Value(value = "${watering.accessKey}")
private String accessKey;
@Value(value = "${watering.timeout}")
private String timeout;
@Value(value = "${watering.daysToExpire}")
private Long daysToExpire;
/** /**
@ -104,12 +132,83 @@ public class AsDeviceServiceImpl extends ServiceImpl<AsDeviceMapper, AsDevice> i
* @param asDevice 设备列表 * @param asDevice 设备列表
* @return 结果 * @return 结果
*/ */
@SneakyThrows
@Override @Override
public int updateAsDevice(AsDevice asDevice) public int updateAsDevice(AsDevice asDevice)
{ {
asDevice.setUpdateTime(DateUtils.getNowDate()); asDevice.setUpdateTime(DateUtils.getNowDate());
/** 请求iot设备参数*/
/** 1.获取参数*/
String command = getCommand(asDevice);
logger.info("IOT获取到下发命令:【{}】",command);
/** 3.发送请求*/
String deviceName = asDevice.getMac();//mac地址就是产品名称
String param = "device_name=" + deviceName + "&product_id=" + productId +"&timeout=" + timeout;
String sendUrl = iotUrl+ IotConstants.ADDS_COMMAND + "?"+param;
long expirationTimeInSeconds = TimeUnit.DAYS.toSeconds(daysToExpire);
String expirationTime = String.valueOf(System.currentTimeMillis() / 1000 + expirationTimeInSeconds);
String signatureMethod = Token.SignatureMethod.SHA256.name().toLowerCase();//签名方式
String token = Token.assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
logger.info("IOT获取到Authorization:【{}】",token);
String result = HttpUtils.sendPostWithToken(sendUrl, command, token);
JSONObject paramsObj = JSON.parseObject(result);
String code = paramsObj.getString("code");
String msg = paramsObj.getString("msg");
if (!HttpStatus.IOT_SUCCESS.equals(code))
{
throw new ServiceException(code+"-----"+msg);
}
logger.info("IOT请求调用结果:【{}】",result);
/**4.更新数据库*/
return asDeviceMapper.updateAsDevice(asDevice); return asDeviceMapper.updateAsDevice(asDevice);
} }
private String getCommand(AsDevice asDevice) {
String regularWateringSwitch = "true".equals(asDevice.getRegularWatering()) ? "1" : "0";//定时浇水开关
JSONObject regularWateringJsonObj = JSON.parseObject(asDevice.getRegularWateringJson());
String startHour = regularWateringJsonObj.getString("startHour");//启动时间-小时
String startMin = regularWateringJsonObj.getString("startMin");//启动时间-分钟
String sprayTime = regularWateringJsonObj.getString("sprayTime");//喷洒时间
String soilMoistureSwitch = "true".equals(asDevice.getSoilMoisture()) ? "1" : "0";//土壤湿度开关
Integer soilMoistureOpen = asDevice.getSoilMoistureOpen();//启动土壤湿度
Integer soilMoistureClose = asDevice.getSoilMoistureClose();//关闭土壤湿度
String pulseModeSwitch = "true".equals(asDevice.getPulseMode()) ? "1" : "0";//脉冲模式开关
JSONObject pulseModeParamObj = JSON.parseObject(asDevice.getPulseModeParam());
String sprayTime1 = pulseModeParamObj.getString("sprayTime");//喷洒时间
String intervalTime = pulseModeParamObj.getString("intervalTime");//间隔时间
Integer waterIntensity = asDevice.getWaterIntensity();
String min = asDevice.getScreenRestTime().replace("min", "");//息屏时间转换成分钟数
Integer minNum = Integer.parseInt(min.replace("hour", "")) * 60;
String screenRestTime = min.contains("hour") ? minNum.toString() : min;
String screenRestTimeSwitch = "99".equals(asDevice.getScreenRestTime()) ? "0" : "1";//息屏开关
StringBuilder command = new StringBuilder()
.append("dsjs_sec").append(sprayTime).append(IotConstants.COMMAND_SEPARATOR)
.append("dskaiguan").append(regularWateringSwitch).append(IotConstants.COMMAND_SEPARATOR)
.append("dsstart_hour").append(startHour).append(IotConstants.COMMAND_SEPARATOR)
.append("dsstart_min").append(startMin).append(IotConstants.COMMAND_SEPARATOR)
.append("jiaoshui_qiangdu").append(waterIntensity).append(IotConstants.COMMAND_SEPARATOR)
.append("mckaiguan").append(pulseModeSwitch).append(IotConstants.COMMAND_SEPARATOR)
.append("mcjg_sec").append(intervalTime).append(IotConstants.COMMAND_SEPARATOR)
.append("mcjs_sec").append(sprayTime1).append(IotConstants.COMMAND_SEPARATOR)
.append("setkaiguan").append(screenRestTimeSwitch).append(IotConstants.COMMAND_SEPARATOR)
.append("setxp_min").append(screenRestTime).append(IotConstants.COMMAND_SEPARATOR)
.append("trkaiguan").append(soilMoistureSwitch).append(IotConstants.COMMAND_SEPARATOR)
.append("trstart_sd").append(soilMoistureOpen).append(IotConstants.COMMAND_SEPARATOR)
.append("trend_sd").append(soilMoistureClose).append(IotConstants.COMMAND_SEPARATOR);
return command.toString();
}
/** /**
* 批量删除设备列表 * 批量删除设备列表
@ -135,12 +234,51 @@ public class AsDeviceServiceImpl extends ServiceImpl<AsDeviceMapper, AsDevice> i
return asDeviceMapper.deleteAsDeviceByDeviceId(deviceId); return asDeviceMapper.deleteAsDeviceByDeviceId(deviceId);
} }
/**
* 手动浇水
*
* @param device 设备对象
* @return 结果
*/
@SneakyThrows
@Override @Override
public AjaxResult watering(AsDevice device) { public AjaxResult watering(AsDevice device,Integer wateringSwitch) {
// TODO 手动浇水 调用 onenet /** 1.拼接url */
AjaxResult publish = mqttPushClient.publish(0, false, "topic", "hello world"); String deviceName = device.getMac();//mac地址就是产品名称
System.out.println("topic发送成功-----"+ JSON.toJSONString(publish)); String param = "device_name=" + deviceName + "&product_id=" + productId +"&timeout=" + timeout;
// TODO 保存浇水记录 as_watering_record String sendUrl = iotUrl+ IotConstants.ADDS_COMMAND + "?"+param;
return publish; logger.info("IOT请求地址:【{}】", sendUrl);
/** 2.获取token */
long expirationTimeInSeconds = TimeUnit.DAYS.toSeconds(daysToExpire);
String expirationTime = String.valueOf(System.currentTimeMillis() / 1000 + expirationTimeInSeconds);
String signatureMethod = Token.SignatureMethod.SHA256.name().toLowerCase();//签名方式
String token = Token.assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
logger.info("IOT获取到Authorization:【{}】",token);
/** 3.请求下发 */
String command = wateringSwitch == 1 ? IotConstants.COMMAND_OPEN : IotConstants.COMMAND_CLOSE;
String result = HttpUtils.sendPostWithToken(sendUrl, command, token);
JSONObject paramsObj = JSON.parseObject(result);
String code = paramsObj.getString("code");
String msg = paramsObj.getString("msg");
if (!HttpStatus.IOT_SUCCESS.equals(code))
{
throw new ServiceException(code+"-----"+msg);
}
logger.info("IOT请求调用结果:【{}】",result);
/** 4.保存浇水记录 保存 as_watering_record表*/
AsWateringRecord record = AsWateringRecord.builder()
.deviceId(device.getDeviceId())
.waterTime(DateUtils.getNowDate())
.startMode(IotConstants.START_MODE_MANUAL)
.pulseMode(device.getPulseModeParam())
// .sprayingTime(device.getPulseModeParam()) //喷洒时间
.userName(getUsername())
.build();
int insert = wateringRecordMapper.insertAsWateringRecord(record);
return AjaxResult.success(insert);
} }
} }