feat (farm): 设备对接,修复部分bug
- 重构设备接口 - 修复部分bug
This commit is contained in:
13
Readme.md
13
Readme.md
@@ -42,4 +42,15 @@ cn.iocoder.yudao.module.farm.controller.admin
|
||||
├── xxx // 角色管理
|
||||
├── xxx // 菜单管理
|
||||
└── xxx // 字典管理
|
||||
````
|
||||
````
|
||||
|
||||
|
||||
# 设备商提供能力
|
||||
| 功能类型 | 土壤设备 | 水肥机 |
|
||||
|--------------|----------|----------|
|
||||
| 登录 | ✅ 支持 | ✅ 支持 |
|
||||
| 获取设备列表 | ✅ 支持 | ✅ 支持 |
|
||||
| 获取实时数据 | ✅ 支持 | ✅ 支持 |
|
||||
| 获取历史数据 | ✅ 支持 | ❌ 不支持 |
|
||||
| 更新设备属性 | ❌ 不支持 | ✅ 支持 |
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ApiController {
|
||||
@PostMapping("/digital-cockpit/baseAndDevice/list")
|
||||
@Operation(summary = "数字驾驶舱-基地与设备信息列表")
|
||||
public CommonResult<List<FarmBaseAndDeviceInfoRespVO>> getBaseAndDeviceInfoList(@Valid @RequestBody FarmBaseAndDeviceInfoReqVO req) {
|
||||
CommonResult<List<FarmBaseInfoRespVO>> bResult = baseInfoService.getBaseInfoList(new FarmBaseInfoReqVO(req.getTenantId()));
|
||||
CommonResult<List<FarmBaseInfoRespVO>> bResult = baseInfoService.getBaseInfoList(new FarmBaseInfoReqVO(req.getBaseId(),req.getTenantId()));
|
||||
List<FarmBaseAndDeviceInfoRespVO> dList = BeanUtils.toBean(bResult.getData(), FarmBaseAndDeviceInfoRespVO.class);
|
||||
|
||||
Map<String, String> dtNameMap = deviceInfoService.getDeviceTypeNameMap(req.getTenantId());
|
||||
|
||||
@@ -15,6 +15,9 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FarmBaseAndDeviceInfoReqVO {
|
||||
@Schema(description = "基地D")
|
||||
@NotNull(message = "基地D: 不能为空")
|
||||
private String baseId;
|
||||
@Schema(description = "租户ID")
|
||||
@NotNull(message = "租户ID: 不能为空")
|
||||
private String tenantId;
|
||||
|
||||
@@ -16,6 +16,9 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class FarmBaseInfoReqVO {
|
||||
|
||||
@Schema(description = "基地D")
|
||||
// @NotNull(message = "基地D: 不能为空")
|
||||
private String baseId;
|
||||
@Schema(description = "租户ID")
|
||||
@NotNull(message = "租户ID: 不能为空")
|
||||
private String tenantId;
|
||||
|
||||
@@ -2,11 +2,18 @@ package cn.iocoder.yudao.module.farm.controller.admin.wx;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.api.vo.DeviceStateRespVO;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.wx.vo.*;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.baseinfo.BaseInfoDO;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.deviceinfo.DeviceInfoDO;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.plotinfo.PlotInfoDO;
|
||||
import cn.iocoder.yudao.module.farm.service.baseinfo.BaseInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.deviceinfo.DeviceInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.farminformation.FarmInformationService;
|
||||
import cn.iocoder.yudao.module.farm.service.farmingrecord.FarmingRecordService;
|
||||
import cn.iocoder.yudao.module.farm.service.messagecenter.MessageCenterService;
|
||||
import cn.iocoder.yudao.module.farm.service.plotinfo.PlotInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -20,6 +27,11 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.BINDING_STATE_MAP;
|
||||
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.DEVICE_STATE_MAP;
|
||||
|
||||
/**
|
||||
* @description: 微信端
|
||||
@@ -36,12 +48,18 @@ public class WxController {
|
||||
private final DeviceInfoService deviceInfoService;
|
||||
private final FarmingRecordService farmingRecordService;
|
||||
private final MessageCenterService messageCenterService;
|
||||
private final BaseInfoService baseInfoService;
|
||||
private final PlotInfoService plotInfoService;
|
||||
private final ProductionPlanService productionPlanService;
|
||||
|
||||
public WxController(FarmInformationService farmInformationService, DeviceInfoService deviceInfoService, FarmingRecordService farmingRecordService, MessageCenterService messageCenterService) {
|
||||
public WxController(FarmInformationService farmInformationService, DeviceInfoService deviceInfoService, FarmingRecordService farmingRecordService, MessageCenterService messageCenterService, BaseInfoService baseInfoService, PlotInfoService plotInfoService, ProductionPlanService productionPlanService) {
|
||||
this.farmInformationService = farmInformationService;
|
||||
this.deviceInfoService = deviceInfoService;
|
||||
this.farmingRecordService = farmingRecordService;
|
||||
this.messageCenterService = messageCenterService;
|
||||
this.baseInfoService = baseInfoService;
|
||||
this.plotInfoService = plotInfoService;
|
||||
this.productionPlanService = productionPlanService;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,29 +92,75 @@ public class WxController {
|
||||
@Operation(summary = "获取设备信息")
|
||||
@Parameter(name = "baseId", description = "基地编号")
|
||||
public CommonResult<DeviceInfoRespVO> getDeviceInfoList(@RequestParam("baseId") String baseId) {
|
||||
DeviceInfoRespVO.DeviceRealData realData = new DeviceInfoRespVO.DeviceRealData("剩余电量", 100, "大气湿度", 0, "大气温度", 0);
|
||||
|
||||
DeviceInfoRespVO.DeviceDetail deviceDetail = new DeviceInfoRespVO.DeviceDetail();
|
||||
deviceDetail.setId("DEV001");
|
||||
deviceDetail.setDeviceUniqueId("SN202405270001");
|
||||
deviceDetail.setDeviceType("DT001");
|
||||
deviceDetail.setDeviceTypeName("农业环境气象监测-新");
|
||||
deviceDetail.setImage("http://223.83.152.93:9000/farm/20250909/trsqjc_1757398720478.png");
|
||||
deviceDetail.setImageList(Arrays.asList("http://223.83.152.93:9000/farm/20250909/trsqjc_1757398720478.png"));
|
||||
deviceDetail.setDeviceState(1);
|
||||
deviceDetail.setDeviceStateName("在线");
|
||||
deviceDetail.setBindingState(1);
|
||||
deviceDetail.setBindingStateName("已绑定");
|
||||
deviceDetail.setPlotName("门村村小香薯种植基地");
|
||||
deviceDetail.setRealData(realData);
|
||||
List<DeviceInfoRespVO.PlotInfo> plotInfos = this.getPlotInfos(baseId);
|
||||
ProductionPlanService.CultivatingInfo cultivatingInfo = productionPlanService.getCultivatingInfo(baseId, "");
|
||||
int cultivatingSpecies = cultivatingInfo.getCultivatingSpeciesCount(); // 在种物种
|
||||
int cultivatingPlotCount = cultivatingInfo.getCultivatingPlotCount(); // 在种地块
|
||||
int plotCount = plotInfos.size();
|
||||
BaseInfoDO b = baseInfoService.getBaseInfo(baseId);
|
||||
|
||||
DeviceInfoRespVO d = new DeviceInfoRespVO();
|
||||
d.setTotal(1);
|
||||
d.setOnlineTotal(1);
|
||||
d.setOfflineTotal(0);
|
||||
d.setDeviceDetail(deviceDetail);
|
||||
DeviceInfoRespVO res = new DeviceInfoRespVO();
|
||||
res.setBaseId(baseId);
|
||||
res.setBaseName(b.getName());
|
||||
res.setBaseArea(b.getArea().intValue());
|
||||
res.setBasePoint(b.getPoint());
|
||||
res.setCultivatingPlotCount(cultivatingPlotCount);
|
||||
res.setPlotCount(plotCount);
|
||||
res.setCultivatingSpecies(cultivatingSpecies);
|
||||
res.setPlotInfos(plotInfos);
|
||||
return CommonResult.success(res);
|
||||
}
|
||||
|
||||
return CommonResult.success(d);
|
||||
private List<DeviceInfoRespVO.PlotInfo> getPlotInfos(String baseId) {
|
||||
List<DeviceInfoRespVO.PlotInfo> res = new ArrayList<>();
|
||||
|
||||
List<PlotInfoDO> pList = plotInfoService.getPlotInfos(baseId);
|
||||
pList.forEach(p -> {
|
||||
List<DeviceInfoRespVO.DeviceDetail> deviceInfos = this.getDeviceInfos(baseId, p.getId());
|
||||
DeviceInfoRespVO.PlotInfo target = new DeviceInfoRespVO.PlotInfo();
|
||||
target.setPlotId(p.getId());
|
||||
target.setPlotName(p.getPlotName());
|
||||
target.setPlotArea(p.getPlotArea().intValue());
|
||||
target.setPlotColor(p.getPlotColor());
|
||||
target.setPlotPoint(p.getPoint());
|
||||
target.setDeviceDetails(deviceInfos);
|
||||
res.add(target);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<DeviceInfoRespVO.DeviceDetail> getDeviceInfos(String baseId, String plotId) {
|
||||
Map<String, String> dtMap = deviceInfoService.getDeviceTypeNameMap(String.valueOf(getLoginUser().getTenantId()));
|
||||
List<DeviceInfoDO> bdList = deviceInfoService.getBaseAndDeviceInfoList(baseId, plotId);
|
||||
DeviceStateRespVO ds = deviceInfoService.countDeviceState(baseId, String.valueOf(getLoginUser().getTenantId()));
|
||||
|
||||
return bdList.stream().map(e -> {
|
||||
List<String> imageList = deviceInfoService.getImage(e.getDeviceType());
|
||||
DeviceInfoRespVO.DeviceDetail target = new DeviceInfoRespVO.DeviceDetail();
|
||||
target.setTotal(ds.getTotalDevices());
|
||||
target.setOnlineTotal(ds.getTotalOnlineDevices());
|
||||
target.setOfflineTotal(ds.getTotalOfflineDevices());
|
||||
|
||||
target.setId(e.getId());
|
||||
target.setDeviceUniqueId(e.getDeviceUniqueId());
|
||||
target.setDeviceType(e.getDeviceType());
|
||||
target.setDeviceTypeName(dtMap.get(e.getDeviceType()));
|
||||
target.setImage(imageList.get(0));
|
||||
target.setImageList(imageList);
|
||||
target.setDeviceState(e.getDeviceState());
|
||||
target.setDeviceStateName(DEVICE_STATE_MAP.get(e.getDeviceState()));
|
||||
target.setBindingState(e.getBindingState());
|
||||
target.setBindingStateName(BINDING_STATE_MAP.get(e.getBindingState()));
|
||||
target.setDevicePoint(e.getPoint());
|
||||
// TODO: 2025/9/26 接入真实数据
|
||||
target.setRealData(Arrays.asList(new DeviceInfoRespVO.DeviceRealData("剩余电量", 100),
|
||||
new DeviceInfoRespVO.DeviceRealData("大气湿度", 0),
|
||||
new DeviceInfoRespVO.DeviceRealData("大气温度", 0)
|
||||
));
|
||||
return target;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,16 +16,52 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DeviceInfoRespVO {
|
||||
@Schema(description = "基地ID")
|
||||
private String baseId;
|
||||
@Schema(description = "基地名称")
|
||||
private String baseName;
|
||||
@Schema(description = "基地面积")
|
||||
private Integer baseArea;
|
||||
@Schema(description = "基地坐标")
|
||||
private String basePoint;
|
||||
@Schema(description = "在种地块数量")
|
||||
private Integer cultivatingPlotCount;
|
||||
@Schema(description = "地块总数量")
|
||||
private Integer plotCount;
|
||||
@Schema(description = "在种物种数量")
|
||||
private Integer cultivatingSpecies;
|
||||
@Schema(description = "地块列表")
|
||||
private List<PlotInfo> plotInfos;
|
||||
|
||||
private Integer total;
|
||||
private Integer onlineTotal;
|
||||
private Integer offlineTotal;
|
||||
private DeviceDetail deviceDetail;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class PlotInfo{
|
||||
@Schema(description = "地块ID")
|
||||
private String plotId;
|
||||
@Schema(description = "地块名称")
|
||||
private String plotName;
|
||||
@Schema(description = "地块面积")
|
||||
private Integer plotArea;
|
||||
@Schema(description = "地块坐标")
|
||||
private String plotPoint;
|
||||
@Schema(description = "地块颜色")
|
||||
private String plotColor;
|
||||
@Schema(description = "设备列表")
|
||||
private List<DeviceDetail> deviceDetails;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DeviceDetail{
|
||||
@Schema(description = "设备总数")
|
||||
private Integer total;
|
||||
@Schema(description = "在线设备数量")
|
||||
private Integer onlineTotal;
|
||||
@Schema(description = "离线设备数量")
|
||||
private Integer offlineTotal;
|
||||
|
||||
private String id;
|
||||
@Schema(description = "设备全局唯一标识(设备厂商提供)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String deviceUniqueId;
|
||||
@@ -43,10 +79,10 @@ public class DeviceInfoRespVO {
|
||||
@Schema(description = "绑定状态:1: 绑定; 0: 未绑定")
|
||||
private Integer bindingState;
|
||||
private String bindingStateName;
|
||||
@Schema(description = "地块名称")
|
||||
private String plotName;
|
||||
@Schema(description = "设备坐标")
|
||||
private String devicePoint;
|
||||
@Schema(description = "设备实时数据")
|
||||
private DeviceRealData realData;
|
||||
private List<DeviceRealData> realData;
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -55,10 +91,6 @@ public class DeviceInfoRespVO {
|
||||
public static class DeviceRealData{
|
||||
private String k1;
|
||||
private Integer v1;
|
||||
private String k2;
|
||||
private Integer v2;
|
||||
private String k3;
|
||||
private Integer v3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,5 +102,5 @@ public interface DeviceInfoMapper extends BaseMapperX<DeviceInfoDO> {
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
DeviceStateRespVO countDeviceState(String tenantId);
|
||||
DeviceStateRespVO countDeviceState(@Param("baseId") String baseId,@Param("tenantId") String tenantId);
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static cn.iocoder.yudao.module.farm.manager.devices.commons.DeviceConst.ALARM_STATUS_NAME_MAP;
|
||||
|
||||
/**
|
||||
* @description: 设备管理
|
||||
@@ -23,79 +22,79 @@ import static cn.iocoder.yudao.module.farm.manager.devices.commons.DeviceConst.A
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 10:50
|
||||
*/
|
||||
@Service
|
||||
//@Service
|
||||
public class DeviceManager {
|
||||
|
||||
private final SoilService soilService;
|
||||
private final WaterFertilizerService waterFertilizerService;
|
||||
|
||||
public DeviceManager(SoilService soilService, WaterFertilizerService waterFertilizerService) {
|
||||
this.soilService = soilService;
|
||||
this.waterFertilizerService = waterFertilizerService;
|
||||
}
|
||||
|
||||
public DeviceInfoDetailV2RespVO getRealData(String deviceUniqueId) {
|
||||
DeviceInfoDetailV2RespVO.SoilInfo soilInfo = this.getSoilData(deviceUniqueId);
|
||||
DeviceInfoDetailV2RespVO.WfInfo wfInfo = this.getWfData(deviceUniqueId);
|
||||
return new DeviceInfoDetailV2RespVO(deviceUniqueId, null, null);
|
||||
}
|
||||
|
||||
public DeviceInfoDetailV2RespVO.SoilInfo getSoilData(String deviceUniqueId) {
|
||||
// 判断该deviceUniqueId是否来源于土壤墒情
|
||||
boolean flag = false;
|
||||
if (flag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String tenantId = String.valueOf(getLoginUser().getTenantId());
|
||||
if (!soilService.validateUserToken(tenantId)) {
|
||||
soilService.userLogin();
|
||||
}
|
||||
|
||||
List<RealTimeDataRespVO> realTimeData = soilService.getRealTimeData(new RealTimeDataReqVO(deviceUniqueId));
|
||||
HistoryDataListPageRespVO historyDataList = soilService.getHistoryDataList(new HistoryDataListPageReqVO());
|
||||
return new DeviceInfoDetailV2RespVO.SoilInfo(deviceUniqueId, coverToSoil(realTimeData), coverToSoil(historyDataList));
|
||||
}
|
||||
|
||||
public DeviceInfoDetailV2RespVO.RealTimeData coverToSoil(List<RealTimeDataRespVO> realTimeData) {
|
||||
if (ObjectUtils.isEmpty(realTimeData)) {
|
||||
return null;
|
||||
}
|
||||
RealTimeDataRespVO sourceObj = realTimeData.get(0);
|
||||
return BeanUtils.toBean(sourceObj, DeviceInfoDetailV2RespVO.RealTimeData.class);
|
||||
}
|
||||
|
||||
public List<DeviceInfoDetailV2RespVO.HistoryDataList> coverToSoil(HistoryDataListPageRespVO historyDataList ) {
|
||||
if (ObjectUtils.isEmpty(historyDataList)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<HistoryDataListPageRespVO.Row> source = historyDataList.getRows();
|
||||
return source.stream().map(e -> {
|
||||
DeviceInfoDetailV2RespVO.HistoryDataList target = new DeviceInfoDetailV2RespVO.HistoryDataList();
|
||||
target.setHistoryId(e.getHistoryId());
|
||||
target.setRecordTime(DateUtils.timestampToLocalDateTime(e.getRecordTime()));
|
||||
target.setDeviceAddress(e.getDeviceAddress());
|
||||
target.setAlarmStatus(e.getAlarmStatus());
|
||||
target.setAlarmStatusName(ALARM_STATUS_NAME_MAP.getOrDefault(e.getAlarmStatus(),""));
|
||||
target.setTemStr(e.getTemStr());
|
||||
target.setTemValue(e.getTemValue());
|
||||
target.setHumStr(e.getHumStr());
|
||||
target.setHumValue(e.getHumValue());
|
||||
return target;
|
||||
}).toList();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DeviceInfoDetailV2RespVO.WfInfo getWfData(String deviceUniqueId) {
|
||||
String tenantId = String.valueOf(getLoginUser().getTenantId());
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
// private final SoilService soilService;
|
||||
// private final WaterFertilizerService waterFertilizerService;
|
||||
//
|
||||
// public DeviceManager(SoilService soilService, WaterFertilizerService waterFertilizerService) {
|
||||
// this.soilService = soilService;
|
||||
// this.waterFertilizerService = waterFertilizerService;
|
||||
// }
|
||||
//
|
||||
// public DeviceInfoDetailV2RespVO getRealData(String deviceUniqueId) {
|
||||
// DeviceInfoDetailV2RespVO.SoilInfo soilInfo = this.getSoilData(deviceUniqueId);
|
||||
// DeviceInfoDetailV2RespVO.WfInfo wfInfo = this.getWfData(deviceUniqueId);
|
||||
// return new DeviceInfoDetailV2RespVO(deviceUniqueId, null, null);
|
||||
// }
|
||||
//
|
||||
// public DeviceInfoDetailV2RespVO.SoilInfo getSoilData(String deviceUniqueId) {
|
||||
// // 判断该deviceUniqueId是否来源于土壤墒情
|
||||
// boolean flag = false;
|
||||
// if (flag) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// String tenantId = String.valueOf(getLoginUser().getTenantId());
|
||||
// if (!soilService.validateUserToken(tenantId)) {
|
||||
// soilService.userLogin();
|
||||
// }
|
||||
//
|
||||
// List<RealTimeDataRespVO> realTimeData = soilService.getRealTimeData(new RealTimeDataReqVO(deviceUniqueId));
|
||||
// HistoryDataListPageRespVO historyDataList = soilService.getHistoryDataList(new HistoryDataListPageReqVO());
|
||||
// return new DeviceInfoDetailV2RespVO.SoilInfo(deviceUniqueId, coverToSoil(realTimeData), coverToSoil(historyDataList));
|
||||
// }
|
||||
//
|
||||
// public DeviceInfoDetailV2RespVO.RealTimeData coverToSoil(List<RealTimeDataRespVO> realTimeData) {
|
||||
// if (ObjectUtils.isEmpty(realTimeData)) {
|
||||
// return null;
|
||||
// }
|
||||
// RealTimeDataRespVO sourceObj = realTimeData.get(0);
|
||||
// return BeanUtils.toBean(sourceObj, DeviceInfoDetailV2RespVO.RealTimeData.class);
|
||||
// }
|
||||
//
|
||||
// public List<DeviceInfoDetailV2RespVO.HistoryDataList> coverToSoil(HistoryDataListPageRespVO historyDataList ) {
|
||||
// if (ObjectUtils.isEmpty(historyDataList)) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// List<HistoryDataListPageRespVO.Row> source = historyDataList.getRows();
|
||||
// return source.stream().map(e -> {
|
||||
// DeviceInfoDetailV2RespVO.HistoryDataList target = new DeviceInfoDetailV2RespVO.HistoryDataList();
|
||||
// target.setHistoryId(e.getHistoryId());
|
||||
// target.setRecordTime(DateUtils.timestampToLocalDateTime(e.getRecordTime()));
|
||||
// target.setDeviceAddress(e.getDeviceAddress());
|
||||
// target.setAlarmStatus(e.getAlarmStatus());
|
||||
// target.setAlarmStatusName(ALARM_STATUS_NAME_MAP.getOrDefault(e.getAlarmStatus(),""));
|
||||
// target.setTemStr(e.getTemStr());
|
||||
// target.setTemValue(e.getTemValue());
|
||||
// target.setHumStr(e.getHumStr());
|
||||
// target.setHumValue(e.getHumValue());
|
||||
// return target;
|
||||
// }).toList();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// public DeviceInfoDetailV2RespVO.WfInfo getWfData(String deviceUniqueId) {
|
||||
// String tenantId = String.valueOf(getLoginUser().getTenantId());
|
||||
//
|
||||
//
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,87 +9,97 @@ import java.util.Map;
|
||||
* @date: 2025/9/17 15:24
|
||||
*/
|
||||
public class DeviceConst {
|
||||
|
||||
/**
|
||||
* 四情 设备类型
|
||||
*/
|
||||
public final String DEVICE_TYPE_IRRIGATION = "irrigation"; // 灌溉
|
||||
public final String DEVICE_TYPE_WORM = "worm"; // 虫害
|
||||
public final String DEVICE_TYPE_WORM_FLAG_SHIP = "wormFlagship";
|
||||
public final String DEVICE_TYPE_SOIL = "soil"; // 土壤
|
||||
public final String DEVICE_TYPE_MET = "met"; // 重金属
|
||||
public final String DEVICE_TYPE_SPORE = "spore"; // 孢子
|
||||
public final String DEVICE_TYPE_CAMERA = "camera"; // 监控
|
||||
|
||||
/**
|
||||
* 四情 设备状态
|
||||
*/
|
||||
public final String DEVICE_STATUS_ONLINE = "online";
|
||||
public final String DEVICE_STATUS_OFFLINE = "offline";
|
||||
public final String DEVICE_STATUS_ALARM = "alarm";
|
||||
|
||||
/**
|
||||
* 四情 http 状态
|
||||
*/
|
||||
public final String HTTP_STATUS_1000 = "1000"; // 成功
|
||||
public final String HTTP_STATUS_1001 = "1001"; // 失败 (执行错误)
|
||||
public final String HTTP_STATUS_1002 = "1002"; // 失败 (验证失败)
|
||||
public final String HTTP_STATUS_1003 = "1003"; // 服务端异常
|
||||
public final String HTTP_STATUS_1004 = "1004"; // 登录过期
|
||||
public final String HTTP_STATUS_2000 = "2000"; // 登录超时
|
||||
public final String HTTP_STATUS_4000 = "4000"; // 未登录或登录失败
|
||||
public final String HTTP_STATUS_5000 = "5000"; // 操作失败
|
||||
|
||||
/**
|
||||
* 四情-墒情 设备实时数据 - 节点类型
|
||||
*/
|
||||
public final int NODE_TYPE_1 = 1; // 模拟量
|
||||
public final int NODE_TYPE_1_1 = 1; // 模拟量 使能模拟量
|
||||
public final int NODE_TYPE_1_2 = 2; // 模拟量 使能
|
||||
|
||||
public final int NODE_TYPE_2 = 2; // 模拟量
|
||||
public final int NODE_TYPE_2_1 = 1; // 模拟量 使能模拟量
|
||||
public final int NODE_TYPE_2_2 = 2; // 模拟量 禁用
|
||||
|
||||
public final int NODE_TYPE_3 = 3; // 模拟量
|
||||
public final int NODE_TYPE_3_1 = 1; // 模拟量 禁用模拟量
|
||||
public final int NODE_TYPE_3_2 = 2; // 模拟量 使能
|
||||
|
||||
public final int NODE_TYPE_4 = 4; // 浮点型设备
|
||||
public final int NODE_TYPE_5 = 5; // 开关量型设备
|
||||
public final int NODE_TYPE_6 = 6; // 32位有符号整型
|
||||
public final int NODE_TYPE_7 = 7; // 32位无符号整型
|
||||
public final int NODE_TYPE_8 = 8; // 遥调设备
|
||||
|
||||
/**
|
||||
* 四情-墒情 设备实时数据 - 节点报警等级
|
||||
*/
|
||||
public final int ALARM_STATUS_0 = 0; // 正常
|
||||
public final int ALARM_STATUS_1 = 1; // 超上限报警
|
||||
public final int ALARM_STATUS_2 = 2; // 超下限报警
|
||||
public final int ALARM_STATUS_3 = 3; // 开关闭合报警
|
||||
public final int ALARM_STATUS_4 = 4; // 开关断开报警
|
||||
public final int ALARM_STATUS_5 = 5; // 遥调报警
|
||||
|
||||
/**
|
||||
* 四情-设备报警通知记录 - 通知类型
|
||||
*/
|
||||
public final int NOTICE_TYPE_0 = 0; // 邮箱
|
||||
public final int NOTICE_TYPE_1 = 1; // 短信
|
||||
|
||||
|
||||
|
||||
|
||||
public final static int ALARM_STATUS_NAME_0 = 0; // 正常
|
||||
public final static int ALARM_STATUS_NAME_1 = 1; // 报警
|
||||
|
||||
// TODO: 2025/9/17 UpdateNodeInfoReqVO
|
||||
|
||||
|
||||
public static Map<Integer, String> ALARM_STATUS_NAME_MAP = new HashMap<>();
|
||||
static {
|
||||
ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_0, "正常");
|
||||
ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_1, "报警");
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * 四情 设备类型
|
||||
// *
|
||||
// * 虫情设备普通版: worm;
|
||||
// * 虫情设备旗舰版: wormFlagship;
|
||||
// * 孢子设备: spore;
|
||||
// * 气象设备:met;
|
||||
// * 墒情设备:soil;
|
||||
// * 智慧环控 3.0 设备:irrigation;
|
||||
// * 智慧环控 2.0 设备:irrigation2;
|
||||
// * 摄像头:camera;
|
||||
// *
|
||||
// */
|
||||
// public final String DEVICE_TYPE_IRRIGATION = "irrigation";
|
||||
// public final String DEVICE_TYPE_WORM = "worm";
|
||||
// public final String DEVICE_TYPE_WORM_FLAG_SHIP = "wormFlagship";
|
||||
// public final String DEVICE_TYPE_SOIL = "soil";
|
||||
// public final String DEVICE_TYPE_MET = "met";
|
||||
// public final String DEVICE_TYPE_SPORE = "spore";
|
||||
// public final String DEVICE_TYPE_CAMERA = "camera";
|
||||
//
|
||||
// /**
|
||||
// * 四情 设备状态
|
||||
// */
|
||||
// public final String DEVICE_STATUS_ONLINE = "online";
|
||||
// public final String DEVICE_STATUS_OFFLINE = "offline";
|
||||
// public final String DEVICE_STATUS_ALARM = "alarm";
|
||||
//
|
||||
// /**
|
||||
// * 四情 http 状态
|
||||
// */
|
||||
// public final String HTTP_STATUS_1000 = "1000"; // 成功
|
||||
// public final String HTTP_STATUS_1001 = "1001"; // 失败 (执行错误)
|
||||
// public final String HTTP_STATUS_1002 = "1002"; // 失败 (验证失败)
|
||||
// public final String HTTP_STATUS_1003 = "1003"; // 服务端异常
|
||||
// public final String HTTP_STATUS_1004 = "1004"; // 登录过期
|
||||
// public final String HTTP_STATUS_2000 = "2000"; // 登录超时
|
||||
// public final String HTTP_STATUS_4000 = "4000"; // 未登录或登录失败
|
||||
// public final String HTTP_STATUS_5000 = "5000"; // 操作失败
|
||||
//
|
||||
// /**
|
||||
// * 四情-墒情 设备实时数据 - 节点类型
|
||||
// */
|
||||
// public final int NODE_TYPE_1 = 1; // 模拟量
|
||||
// public final int NODE_TYPE_1_1 = 1; // 模拟量 使能模拟量
|
||||
// public final int NODE_TYPE_1_2 = 2; // 模拟量 使能
|
||||
//
|
||||
// public final int NODE_TYPE_2 = 2; // 模拟量
|
||||
// public final int NODE_TYPE_2_1 = 1; // 模拟量 使能模拟量
|
||||
// public final int NODE_TYPE_2_2 = 2; // 模拟量 禁用
|
||||
//
|
||||
// public final int NODE_TYPE_3 = 3; // 模拟量
|
||||
// public final int NODE_TYPE_3_1 = 1; // 模拟量 禁用模拟量
|
||||
// public final int NODE_TYPE_3_2 = 2; // 模拟量 使能
|
||||
//
|
||||
// public final int NODE_TYPE_4 = 4; // 浮点型设备
|
||||
// public final int NODE_TYPE_5 = 5; // 开关量型设备
|
||||
// public final int NODE_TYPE_6 = 6; // 32位有符号整型
|
||||
// public final int NODE_TYPE_7 = 7; // 32位无符号整型
|
||||
// public final int NODE_TYPE_8 = 8; // 遥调设备
|
||||
//
|
||||
// /**
|
||||
// * 四情-墒情 设备实时数据 - 节点报警等级
|
||||
// */
|
||||
// public final int ALARM_STATUS_0 = 0; // 正常
|
||||
// public final int ALARM_STATUS_1 = 1; // 超上限报警
|
||||
// public final int ALARM_STATUS_2 = 2; // 超下限报警
|
||||
// public final int ALARM_STATUS_3 = 3; // 开关闭合报警
|
||||
// public final int ALARM_STATUS_4 = 4; // 开关断开报警
|
||||
// public final int ALARM_STATUS_5 = 5; // 遥调报警
|
||||
//
|
||||
// /**
|
||||
// * 四情-设备报警通知记录 - 通知类型
|
||||
// */
|
||||
// public final int NOTICE_TYPE_0 = 0; // 邮箱
|
||||
// public final int NOTICE_TYPE_1 = 1; // 短信
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// public final static int ALARM_STATUS_NAME_0 = 0; // 正常
|
||||
// public final static int ALARM_STATUS_NAME_1 = 1; // 报警
|
||||
//
|
||||
// // TODO: 2025/9/17 UpdateNodeInfoReqVO
|
||||
//
|
||||
//
|
||||
// public static Map<Integer, String> ALARM_STATUS_NAME_MAP = new HashMap<>();
|
||||
// static {
|
||||
// ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_0, "正常");
|
||||
// ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_1, "报警");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -9,54 +9,54 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 10:55
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "device-manager")
|
||||
//@Data
|
||||
//@Configuration
|
||||
//@ConfigurationProperties(prefix = "device-manager")
|
||||
public class DeviceConf {
|
||||
|
||||
private FourSituations fourSituations;
|
||||
private WaterAndFertilizer waterAndFertilizer;
|
||||
|
||||
@Data
|
||||
public static class FourSituations {
|
||||
private String hosts;
|
||||
private String username;
|
||||
private String password;
|
||||
private Global global;
|
||||
private Soil soil;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Global {
|
||||
private String url21; // 用户登录
|
||||
private String url22; // 获取登录用户信息
|
||||
private String url23; // 获取子用户信息
|
||||
private String url24; // 设备报警通知记录
|
||||
private String url25; // 获取用户区域
|
||||
private String url26; // 获取用户设备
|
||||
private String url27; // 批量获取摄像头设备信息
|
||||
private String url28; // 获取设备实时数据
|
||||
private String url29; // 区域绑定设备
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Soil {
|
||||
private String url41; // 墒情设备, 获取设备全部信息
|
||||
private String url42; // 墒情设备, 更新设备信息
|
||||
private String url43; // 墒情设备, 更新节点信息
|
||||
private String url44; // 墒情设备, 获取历史数据
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class WaterAndFertilizer {
|
||||
private String hosts;
|
||||
private String username;
|
||||
private String password;
|
||||
private String url1;
|
||||
private String url2;
|
||||
private String url3;
|
||||
private String url4;
|
||||
}
|
||||
// private FourSituations fourSituations;
|
||||
// private WaterAndFertilizer waterAndFertilizer;
|
||||
//
|
||||
// @Data
|
||||
// public static class FourSituations {
|
||||
// private String hosts;
|
||||
// private String username;
|
||||
// private String password;
|
||||
// private Global global;
|
||||
// private Soil soil;
|
||||
// }
|
||||
//
|
||||
// @Data
|
||||
// public static class Global {
|
||||
// private String url21; // 用户登录
|
||||
// private String url22; // 获取登录用户信息
|
||||
// private String url23; // 获取子用户信息
|
||||
// private String url24; // 设备报警通知记录
|
||||
// private String url25; // 获取用户区域
|
||||
// private String url26; // 获取用户设备
|
||||
// private String url27; // 批量获取摄像头设备信息
|
||||
// private String url28; // 获取设备实时数据
|
||||
// private String url29; // 区域绑定设备
|
||||
// }
|
||||
//
|
||||
// @Data
|
||||
// public static class Soil {
|
||||
// private String url41; // 墒情设备, 获取设备全部信息
|
||||
// private String url42; // 墒情设备, 更新设备信息
|
||||
// private String url43; // 墒情设备, 更新节点信息
|
||||
// private String url44; // 墒情设备, 获取历史数据
|
||||
// }
|
||||
//
|
||||
// @Data
|
||||
// public static class WaterAndFertilizer {
|
||||
// private String hosts;
|
||||
// private String username;
|
||||
// private String password;
|
||||
// private String url1;
|
||||
// private String url2;
|
||||
// private String url3;
|
||||
// private String url4;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 14:42
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
//@Configuration
|
||||
//@EnableScheduling
|
||||
public class SchedulingConfig {
|
||||
|
||||
}
|
||||
|
||||
@@ -22,182 +22,182 @@ import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.*;
|
||||
* @date: 2025/9/17 10:57
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
//@Service
|
||||
public class SoilService extends BaseTokenCacheService {
|
||||
|
||||
private final DeviceConf deviceConf;
|
||||
private final HttpClientUtils httpClientUtils;
|
||||
|
||||
public SoilService(DeviceConf deviceConf, HttpClientUtils httpClientUtils) {
|
||||
this.deviceConf = deviceConf;
|
||||
this.httpClientUtils = httpClientUtils;
|
||||
}
|
||||
|
||||
private final String SOIL = "soil_";
|
||||
|
||||
public void userLogin() {
|
||||
String username = deviceConf.getFourSituations().getUsername();
|
||||
String password = deviceConf.getFourSituations().getPassword();
|
||||
|
||||
this.userLogin(new UserLoginReqVO(username,password));
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录获取token
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
public UserLoginRespVO userLogin(UserLoginReqVO req) {
|
||||
String tenantId = getLoginUser().getTenantId().toString();
|
||||
String hosts = deviceConf.getFourSituations().getHosts();
|
||||
String userLoginURL = deviceConf.getFourSituations().getGlobal().getUrl21();
|
||||
|
||||
try {
|
||||
ApiResponse<UserLoginRespVO> response = httpClientUtils.postRequest(hosts, userLoginURL, req, null, UserLoginRespVO.class);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
UserLoginRespVO data = response.getData();
|
||||
// TODO: 2025/9/17 持久化
|
||||
cacheToken(SOIL+tenantId, data);
|
||||
}
|
||||
|
||||
return response.getData();
|
||||
} catch (Exception e) {
|
||||
log.error("租户 {} 登录失败: {}", tenantId, e.getMessage(), e);
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_LOGIN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证租户token有效性
|
||||
*/
|
||||
public boolean validateUserToken(String tenantId) {
|
||||
log.debug("验证租户 {} 的Token", tenantId);
|
||||
return isTokenValidByTenantId(SOIL+tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户设备
|
||||
*/
|
||||
public List<SysUserDeviceRespVO> getSysUserDevice(SysUserDeviceReqVO req) {
|
||||
|
||||
String tenantId = getLoginUser().getTenantId().toString();
|
||||
String token = getTokenByTenantId(tenantId);
|
||||
String hosts = deviceConf.getFourSituations().getHosts();
|
||||
String getSysUserDeviceURL = deviceConf.getFourSituations().getGlobal().getUrl26();
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("token", token);
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("groupId", StringUtils.defaultString(req.getGroupId()));
|
||||
params.put("deviceType", StringUtils.defaultString(req.getDeviceType()));
|
||||
|
||||
try {
|
||||
|
||||
ApiResponse<List<SysUserDeviceRespVO>> response = httpClientUtils.getRequestAsList(hosts, getSysUserDeviceURL, params, headers, SysUserDeviceRespVO.class);
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_DEVICE);
|
||||
}
|
||||
return response.getData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_DEVICE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备实时数据
|
||||
*/
|
||||
public List<RealTimeDataRespVO> getRealTimeData(RealTimeDataReqVO req) {
|
||||
String tenantId = getLoginUser().getTenantId().toString();
|
||||
String token = getTokenByTenantId(tenantId);
|
||||
String hosts = deviceConf.getFourSituations().getHosts();
|
||||
String getSysUserDeviceURL = deviceConf.getFourSituations().getGlobal().getUrl27();
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("token", token);
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("deviceAddrs", req.getDeviceAddrs());
|
||||
|
||||
try {
|
||||
ApiResponse<List<RealTimeDataRespVO>> response = httpClientUtils.getRequestAsList(hosts, getSysUserDeviceURL, params, headers, RealTimeDataRespVO.class);
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_REAL_TIME_DATA);
|
||||
}
|
||||
return response.getData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_REAL_TIME_DATA);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备报警通知记录
|
||||
*/
|
||||
public List<AlarmNoticeRecordRespVO> getAlarmNoticeRecord(AlarmNoticeRecordReqVO req) {
|
||||
|
||||
String tenantId = getLoginUser().getTenantId().toString();
|
||||
String token = getTokenByTenantId(tenantId);
|
||||
String hosts = deviceConf.getFourSituations().getHosts();
|
||||
String getAlarmNoticeRecord = deviceConf.getFourSituations().getGlobal().getUrl24();
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("token", token);
|
||||
Map<String, String> params = req.toFieldValueMap();
|
||||
|
||||
try {
|
||||
ApiResponse<List<AlarmNoticeRecordRespVO>> response = httpClientUtils.getRequestAsList(hosts, getAlarmNoticeRecord, params, headers, AlarmNoticeRecordRespVO.class);
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_ALARM_NOTICE_RECORD);
|
||||
}
|
||||
return response.getData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_ALARM_NOTICE_RECORD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 墒情设备, 获取设备全部信息
|
||||
*/
|
||||
public List<DeviceAllInfoRespVO> getDeviceAllInfo(DeviceAllInfoReqVO req) {
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 墒情设备, 更新设备信息
|
||||
*/
|
||||
public Boolean updateDevice(UpdateDeviceReqVO req) {
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 墒情设备, 更新节点信息
|
||||
*/
|
||||
public Boolean updateNodeInfo(UpdateNodeInfoReqVO req) {
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 墒情设备, 获取历史数据
|
||||
*/
|
||||
public HistoryDataListPageRespVO getHistoryDataList(HistoryDataListPageReqVO req) {
|
||||
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
//
|
||||
// private final DeviceConf deviceConf;
|
||||
// private final HttpClientUtils httpClientUtils;
|
||||
//
|
||||
// public SoilService(DeviceConf deviceConf, HttpClientUtils httpClientUtils) {
|
||||
// this.deviceConf = deviceConf;
|
||||
// this.httpClientUtils = httpClientUtils;
|
||||
// }
|
||||
//
|
||||
// private final String SOIL = "soil_";
|
||||
//
|
||||
// public void userLogin() {
|
||||
// String username = deviceConf.getFourSituations().getUsername();
|
||||
// String password = deviceConf.getFourSituations().getPassword();
|
||||
//
|
||||
// this.userLogin(new UserLoginReqVO(username,password));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 登录获取token
|
||||
// *
|
||||
// * @param req
|
||||
// * @return
|
||||
// */
|
||||
// public UserLoginRespVO userLogin(UserLoginReqVO req) {
|
||||
// String tenantId = getLoginUser().getTenantId().toString();
|
||||
// String hosts = deviceConf.getFourSituations().getHosts();
|
||||
// String userLoginURL = deviceConf.getFourSituations().getGlobal().getUrl21();
|
||||
//
|
||||
// try {
|
||||
// ApiResponse<UserLoginRespVO> response = httpClientUtils.postRequest(hosts, userLoginURL, req, null, UserLoginRespVO.class);
|
||||
//
|
||||
// if (response.isSuccess()) {
|
||||
// UserLoginRespVO data = response.getData();
|
||||
// // TODO: 2025/9/17 持久化
|
||||
// cacheToken(SOIL+tenantId, data);
|
||||
// }
|
||||
//
|
||||
// return response.getData();
|
||||
// } catch (Exception e) {
|
||||
// log.error("租户 {} 登录失败: {}", tenantId, e.getMessage(), e);
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_LOGIN);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 验证租户token有效性
|
||||
// */
|
||||
// public boolean validateUserToken(String tenantId) {
|
||||
// log.debug("验证租户 {} 的Token", tenantId);
|
||||
// return isTokenValidByTenantId(SOIL+tenantId);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取用户设备
|
||||
// */
|
||||
// public List<SysUserDeviceRespVO> getSysUserDevice(SysUserDeviceReqVO req) {
|
||||
//
|
||||
// String tenantId = getLoginUser().getTenantId().toString();
|
||||
// String token = getTokenByTenantId(tenantId);
|
||||
// String hosts = deviceConf.getFourSituations().getHosts();
|
||||
// String getSysUserDeviceURL = deviceConf.getFourSituations().getGlobal().getUrl26();
|
||||
//
|
||||
// Map<String, String> headers = new HashMap<>();
|
||||
// headers.put("token", token);
|
||||
//
|
||||
// Map<String, String> params = new HashMap<>();
|
||||
// params.put("groupId", StringUtils.defaultString(req.getGroupId()));
|
||||
// params.put("deviceType", StringUtils.defaultString(req.getDeviceType()));
|
||||
//
|
||||
// try {
|
||||
//
|
||||
// ApiResponse<List<SysUserDeviceRespVO>> response = httpClientUtils.getRequestAsList(hosts, getSysUserDeviceURL, params, headers, SysUserDeviceRespVO.class);
|
||||
// if (!response.isSuccess()) {
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_DEVICE);
|
||||
// }
|
||||
// return response.getData();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_USER_DEVICE);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取设备实时数据
|
||||
// */
|
||||
// public List<RealTimeDataRespVO> getRealTimeData(RealTimeDataReqVO req) {
|
||||
// String tenantId = getLoginUser().getTenantId().toString();
|
||||
// String token = getTokenByTenantId(tenantId);
|
||||
// String hosts = deviceConf.getFourSituations().getHosts();
|
||||
// String getSysUserDeviceURL = deviceConf.getFourSituations().getGlobal().getUrl27();
|
||||
//
|
||||
// Map<String, String> headers = new HashMap<>();
|
||||
// headers.put("token", token);
|
||||
// Map<String, String> params = new HashMap<>();
|
||||
// params.put("deviceAddrs", req.getDeviceAddrs());
|
||||
//
|
||||
// try {
|
||||
// ApiResponse<List<RealTimeDataRespVO>> response = httpClientUtils.getRequestAsList(hosts, getSysUserDeviceURL, params, headers, RealTimeDataRespVO.class);
|
||||
// if (!response.isSuccess()) {
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_REAL_TIME_DATA);
|
||||
// }
|
||||
// return response.getData();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_REAL_TIME_DATA);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 设备报警通知记录
|
||||
// */
|
||||
// public List<AlarmNoticeRecordRespVO> getAlarmNoticeRecord(AlarmNoticeRecordReqVO req) {
|
||||
//
|
||||
// String tenantId = getLoginUser().getTenantId().toString();
|
||||
// String token = getTokenByTenantId(tenantId);
|
||||
// String hosts = deviceConf.getFourSituations().getHosts();
|
||||
// String getAlarmNoticeRecord = deviceConf.getFourSituations().getGlobal().getUrl24();
|
||||
//
|
||||
// Map<String, String> headers = new HashMap<>();
|
||||
// headers.put("token", token);
|
||||
// Map<String, String> params = req.toFieldValueMap();
|
||||
//
|
||||
// try {
|
||||
// ApiResponse<List<AlarmNoticeRecordRespVO>> response = httpClientUtils.getRequestAsList(hosts, getAlarmNoticeRecord, params, headers, AlarmNoticeRecordRespVO.class);
|
||||
// if (!response.isSuccess()) {
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_ALARM_NOTICE_RECORD);
|
||||
// }
|
||||
// return response.getData();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw exception(DEVICE_INFO_NOT_EXISTS_FOR_ALARM_NOTICE_RECORD);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 墒情设备, 获取设备全部信息
|
||||
// */
|
||||
// public List<DeviceAllInfoRespVO> getDeviceAllInfo(DeviceAllInfoReqVO req) {
|
||||
//
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 墒情设备, 更新设备信息
|
||||
// */
|
||||
// public Boolean updateDevice(UpdateDeviceReqVO req) {
|
||||
//
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 墒情设备, 更新节点信息
|
||||
// */
|
||||
// public Boolean updateNodeInfo(UpdateNodeInfoReqVO req) {
|
||||
//
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 墒情设备, 获取历史数据
|
||||
// */
|
||||
// public HistoryDataListPageRespVO getHistoryDataList(HistoryDataListPageReqVO req) {
|
||||
//
|
||||
//
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.devices.wf;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.devices.conf.DeviceConf;
|
||||
import cn.iocoder.yudao.module.farm.manager.devices.soil.BaseTokenCacheService;
|
||||
import cn.iocoder.yudao.module.farm.manager.devices.wf.dto.*;
|
||||
import cn.iocoder.yudao.module.farm.utils.HttpClientUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.DEVICE_INFO_NOT_EXISTS_FOR_WF_LOGIN;
|
||||
|
||||
/**
|
||||
* @description: 水肥机
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 10:59
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WaterFertilizerService extends BaseTokenCacheService {
|
||||
|
||||
private final DeviceConf deviceConf;
|
||||
private final HttpClientUtils httpClientUtils;
|
||||
|
||||
public WaterFertilizerService(DeviceConf deviceConf, HttpClientUtils httpClientUtils) {
|
||||
this.deviceConf = deviceConf;
|
||||
this.httpClientUtils = httpClientUtils;
|
||||
}
|
||||
|
||||
private final String Authorization = "Authorization";
|
||||
private final String Bearer = "Bearer ";
|
||||
private final String WF = "wf_";
|
||||
|
||||
/**
|
||||
* 获取公钥
|
||||
*/
|
||||
public LoginRespVO login() {
|
||||
String tenantId = getLoginUser().getTenantId().toString();
|
||||
String hosts = deviceConf.getWaterAndFertilizer().getHosts();
|
||||
String loginURL = deviceConf.getWaterAndFertilizer().getUrl1();
|
||||
LoginReqVO req = new LoginReqVO(deviceConf.getWaterAndFertilizer().getUsername(),
|
||||
deviceConf.getWaterAndFertilizer().getPassword());
|
||||
|
||||
try {
|
||||
HttpClientUtils.ApiResponse<LoginRespVO> response = httpClientUtils.postRequest(hosts, loginURL, req, null, LoginRespVO.class);
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_WF_LOGIN);
|
||||
}
|
||||
LoginRespVO data = response.getData();
|
||||
cacheToken(WF+tenantId, data.getToken());
|
||||
return response.getData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw exception(DEVICE_INFO_NOT_EXISTS_FOR_WF_LOGIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备列表
|
||||
* @param userCode 用户名
|
||||
* @return
|
||||
*/
|
||||
public DevicePageRespVO getDeviceList(String userCode) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备实时状态
|
||||
* @param deviceId 设备ID
|
||||
* @return
|
||||
*/
|
||||
public RealTimeDeviceDataRespVO getRealTimeDeviceData(String deviceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改设备属性
|
||||
* @param deviceId 设备ID
|
||||
* @param paramStr 更改值: true: 打开,false: 关闭
|
||||
* @return
|
||||
*/
|
||||
public UpdateDeviceStatusRespVO updateDeviceStatus(String deviceId, String paramStr) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.devices.wf.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 23:07
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DevicePageReqVO {
|
||||
/**
|
||||
* 令牌 必填
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userCode;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.*;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.DeviceService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:44
|
||||
*/
|
||||
@Service
|
||||
public class EquipmentProducerManager {
|
||||
|
||||
private final Map<String, DeviceService> deviceServiceMap;
|
||||
|
||||
public EquipmentProducerManager(List<DeviceService> deviceServices) {
|
||||
this.deviceServiceMap = deviceServices.stream()
|
||||
.collect(Collectors.toMap(DeviceService::getDeviceType, Function.identity()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一登录方法
|
||||
*/
|
||||
public UnifiedLoginResponse login(String deviceType, Long tenantId, String deviceId, Object loginRequest) {
|
||||
DeviceService service = this.getDeviceService(deviceType);
|
||||
return service.login(tenantId, deviceId, loginRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一获取设备列表方法
|
||||
*/
|
||||
public DeviceListResponse getDeviceList(String deviceType, Long tenantId, String token, Object listRequest) {
|
||||
DeviceService service = this.getDeviceService(deviceType);
|
||||
return service.getDeviceList(tenantId, token, listRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一获取实时数据方法
|
||||
*/
|
||||
public RealTimeDataResponse getRealTimeData(String deviceType, Long tenantId, String token, Object realTimeRequest) {
|
||||
DeviceService service = this.getDeviceService(deviceType);
|
||||
return service.getRealTimeData(tenantId, token, realTimeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一获取历史数据方法
|
||||
*/
|
||||
public HistoryDataResponse getHistoryData(String deviceType, Long tenantId, String token, Object historyRequest) {
|
||||
DeviceService service = getDeviceService(deviceType);
|
||||
return service.getHistoryData(tenantId, token, historyRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一更新设备属性方法
|
||||
*/
|
||||
public UpdateDeviceResponse updateDeviceProperties(String deviceType, Long tenantId, String token, Object updateRequest) {
|
||||
DeviceService service = getDeviceService(deviceType);
|
||||
return service.updateDeviceProperties(tenantId, token, updateRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备类型获取对应的设备服务
|
||||
*/
|
||||
private DeviceService getDeviceService(String deviceType) {
|
||||
DeviceService service = deviceServiceMap.get(deviceType);
|
||||
if (service == null) {
|
||||
throw new IllegalArgumentException("不支持的设备类型: " + deviceType);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.commons;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description: 设备常量
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 15:24
|
||||
*/
|
||||
public class DeviceConst {
|
||||
|
||||
/**
|
||||
* 四情 设备类型
|
||||
*
|
||||
* 虫情设备普通版: worm;
|
||||
* 虫情设备旗舰版: wormFlagship;
|
||||
* 孢子设备: spore;
|
||||
* 气象设备:met;
|
||||
* 墒情设备:soil;
|
||||
* 智慧环控 3.0 设备:irrigation;
|
||||
* 智慧环控 2.0 设备:irrigation2;
|
||||
* 摄像头:camera;
|
||||
*
|
||||
*/
|
||||
public final String DEVICE_TYPE_IRRIGATION = "irrigation";
|
||||
public final String DEVICE_TYPE_WORM = "worm";
|
||||
public final String DEVICE_TYPE_WORM_FLAG_SHIP = "wormFlagship";
|
||||
public final String DEVICE_TYPE_SOIL = "soil";
|
||||
public final String DEVICE_TYPE_MET = "met";
|
||||
public final String DEVICE_TYPE_SPORE = "spore";
|
||||
public final String DEVICE_TYPE_CAMERA = "camera";
|
||||
|
||||
/**
|
||||
* 四情 设备状态
|
||||
*/
|
||||
public final String DEVICE_STATUS_ONLINE = "online";
|
||||
public final String DEVICE_STATUS_OFFLINE = "offline";
|
||||
public final String DEVICE_STATUS_ALARM = "alarm";
|
||||
|
||||
/**
|
||||
* 四情 http 状态
|
||||
*/
|
||||
public final String HTTP_STATUS_1000 = "1000"; // 成功
|
||||
public final String HTTP_STATUS_1001 = "1001"; // 失败 (执行错误)
|
||||
public final String HTTP_STATUS_1002 = "1002"; // 失败 (验证失败)
|
||||
public final String HTTP_STATUS_1003 = "1003"; // 服务端异常
|
||||
public final String HTTP_STATUS_1004 = "1004"; // 登录过期
|
||||
public final String HTTP_STATUS_2000 = "2000"; // 登录超时
|
||||
public final String HTTP_STATUS_4000 = "4000"; // 未登录或登录失败
|
||||
public final String HTTP_STATUS_5000 = "5000"; // 操作失败
|
||||
|
||||
/**
|
||||
* 四情-墒情 设备实时数据 - 节点类型
|
||||
*/
|
||||
public final int NODE_TYPE_1 = 1; // 模拟量
|
||||
public final int NODE_TYPE_1_1 = 1; // 模拟量 使能模拟量
|
||||
public final int NODE_TYPE_1_2 = 2; // 模拟量 使能
|
||||
|
||||
public final int NODE_TYPE_2 = 2; // 模拟量
|
||||
public final int NODE_TYPE_2_1 = 1; // 模拟量 使能模拟量
|
||||
public final int NODE_TYPE_2_2 = 2; // 模拟量 禁用
|
||||
|
||||
public final int NODE_TYPE_3 = 3; // 模拟量
|
||||
public final int NODE_TYPE_3_1 = 1; // 模拟量 禁用模拟量
|
||||
public final int NODE_TYPE_3_2 = 2; // 模拟量 使能
|
||||
|
||||
public final int NODE_TYPE_4 = 4; // 浮点型设备
|
||||
public final int NODE_TYPE_5 = 5; // 开关量型设备
|
||||
public final int NODE_TYPE_6 = 6; // 32位有符号整型
|
||||
public final int NODE_TYPE_7 = 7; // 32位无符号整型
|
||||
public final int NODE_TYPE_8 = 8; // 遥调设备
|
||||
|
||||
/**
|
||||
* 四情-墒情 设备实时数据 - 节点报警等级
|
||||
*/
|
||||
public final int ALARM_STATUS_0 = 0; // 正常
|
||||
public final int ALARM_STATUS_1 = 1; // 超上限报警
|
||||
public final int ALARM_STATUS_2 = 2; // 超下限报警
|
||||
public final int ALARM_STATUS_3 = 3; // 开关闭合报警
|
||||
public final int ALARM_STATUS_4 = 4; // 开关断开报警
|
||||
public final int ALARM_STATUS_5 = 5; // 遥调报警
|
||||
|
||||
/**
|
||||
* 四情-设备报警通知记录 - 通知类型
|
||||
*/
|
||||
public final int NOTICE_TYPE_0 = 0; // 邮箱
|
||||
public final int NOTICE_TYPE_1 = 1; // 短信
|
||||
|
||||
|
||||
|
||||
|
||||
public final static int ALARM_STATUS_NAME_0 = 0; // 正常
|
||||
public final static int ALARM_STATUS_NAME_1 = 1; // 报警
|
||||
|
||||
// TODO: 2025/9/17 UpdateNodeInfoReqVO
|
||||
|
||||
|
||||
public static Map<Integer, String> ALARM_STATUS_NAME_MAP = new HashMap<>();
|
||||
static {
|
||||
ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_0, "正常");
|
||||
ALARM_STATUS_NAME_MAP.put(ALARM_STATUS_NAME_1, "报警");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.conf;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @description: 设备配置
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 10:55
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "device-manager")
|
||||
public class DeviceConf {
|
||||
|
||||
private FourSituations fourSituations;
|
||||
private WaterAndFertilizer waterAndFertilizer;
|
||||
|
||||
@Data
|
||||
public static class FourSituations {
|
||||
private String hosts;
|
||||
private String username;
|
||||
private String password;
|
||||
private Global global;
|
||||
private Soil soil;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Global {
|
||||
private String url21; // 用户登录
|
||||
private String url22; // 获取登录用户信息
|
||||
private String url23; // 获取子用户信息
|
||||
private String url24; // 设备报警通知记录
|
||||
private String url25; // 获取用户区域
|
||||
private String url26; // 获取用户设备
|
||||
private String url27; // 批量获取摄像头设备信息
|
||||
private String url28; // 获取设备实时数据
|
||||
private String url29; // 区域绑定设备
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Soil {
|
||||
private String url41; // 墒情设备, 获取设备全部信息
|
||||
private String url42; // 墒情设备, 更新设备信息
|
||||
private String url43; // 墒情设备, 更新节点信息
|
||||
private String url44; // 墒情设备, 获取历史数据
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class WaterAndFertilizer {
|
||||
private String hosts;
|
||||
private String username;
|
||||
private String password;
|
||||
private String url1;
|
||||
private String url2;
|
||||
private String url3;
|
||||
private String url4;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.conf;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 14:42
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class SchedulingConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 统一设备列表响应
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 23:29
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DeviceListResponse {
|
||||
private String code;
|
||||
private String message;
|
||||
private List<TokenCacheService.DeviceInfo> data;
|
||||
|
||||
public static DeviceListResponse success(List<TokenCacheService.DeviceInfo> data) {
|
||||
return new DeviceListResponse("200", "成功", data);
|
||||
}
|
||||
|
||||
public static DeviceListResponse error(String message) {
|
||||
return new DeviceListResponse("500", message, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: TODO
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 20:32
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class HistoryDataResponse {
|
||||
private String code;
|
||||
private String message;
|
||||
private Object data;
|
||||
|
||||
public static HistoryDataResponse success(Object data) {
|
||||
return new HistoryDataResponse("200", "成功", data);
|
||||
}
|
||||
|
||||
public static HistoryDataResponse error(String message) {
|
||||
return new HistoryDataResponse("500", message, null);
|
||||
}
|
||||
|
||||
public static HistoryDataResponse notSupported() {
|
||||
return new HistoryDataResponse("501", "该设备类型不支持历史数据功能", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 实时数据
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 18:32
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealTimeDataResponse {
|
||||
private String code;
|
||||
private String message;
|
||||
private Object data; // 由于不同设备实时数据结构差异大,使用Object类型
|
||||
|
||||
public static RealTimeDataResponse success(Object data) {
|
||||
return new RealTimeDataResponse("200", "成功", data);
|
||||
}
|
||||
|
||||
public static RealTimeDataResponse error(String message) {
|
||||
return new RealTimeDataResponse("500", message, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 统一登录响应
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 21:26
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UnifiedLoginResponse {
|
||||
private String code;
|
||||
private String message;
|
||||
private LoginData data;
|
||||
|
||||
public static UnifiedLoginResponse success(LoginData data) {
|
||||
return new UnifiedLoginResponse("200", "成功", data);
|
||||
}
|
||||
|
||||
public static UnifiedLoginResponse error(String message) {
|
||||
return new UnifiedLoginResponse("500", message, null);
|
||||
}
|
||||
|
||||
// 登录数据
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class LoginData {
|
||||
private String loginSign;
|
||||
private Long currDate;
|
||||
private Long expDate;
|
||||
private String token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 21:09
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UpdateDeviceResponse {
|
||||
private String code;
|
||||
private String message;
|
||||
private Object data;
|
||||
|
||||
public static UpdateDeviceResponse success(Object data) {
|
||||
return new UpdateDeviceResponse("200", "成功", data);
|
||||
}
|
||||
|
||||
public static UpdateDeviceResponse error(String message) {
|
||||
return new UpdateDeviceResponse("500", message, null);
|
||||
}
|
||||
|
||||
public static UpdateDeviceResponse notSupported() {
|
||||
return new UpdateDeviceResponse("501", "该设备类型不支持更新设备属性功能", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.devicelist;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 获取用户设备 请求实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 15:28
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SysUserDeviceReqVO {
|
||||
/**
|
||||
* 区域ID 非必填
|
||||
*/
|
||||
private String groupId;
|
||||
/**
|
||||
* 设备类型 非必填
|
||||
*/
|
||||
private String deviceType;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.devicelist;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 获取用户设备 响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 15:31
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SysUserDeviceRespVO {
|
||||
private String code;
|
||||
private String message;
|
||||
private List<DeviceInfo> data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DeviceInfo{
|
||||
/**
|
||||
* 设备地址
|
||||
*/
|
||||
public String deviceAddr; // 设备编号
|
||||
/**
|
||||
* 区域ID
|
||||
*/
|
||||
public String groupId;
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
public String deviceType;
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
public String deviceName; // 设备名称
|
||||
/**
|
||||
* 设备的经度
|
||||
*/
|
||||
public String deviceLng;
|
||||
/**
|
||||
* 设备的维度
|
||||
*/
|
||||
public String deviceLat;
|
||||
/**
|
||||
* 设备iccid
|
||||
*/
|
||||
public String deviceIccId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.history;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* @description: 墒情设备, 获取历史数据 请求实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 20:53
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class HistoryDataListPageReqVO {
|
||||
/**
|
||||
* 必选
|
||||
* 开始时间 (时间戳)
|
||||
*/
|
||||
private String beginTime;
|
||||
/**
|
||||
* 必选
|
||||
* 结束时间 (时间戳)
|
||||
*/
|
||||
private String endTime;
|
||||
/**
|
||||
* 必选
|
||||
* 设备地址
|
||||
*/
|
||||
private String deviceAddr;
|
||||
/**
|
||||
* 非必选
|
||||
* 节点ID
|
||||
*/
|
||||
private String nodeId;
|
||||
/**
|
||||
* 必选
|
||||
* 页码
|
||||
*/
|
||||
private Integer pages;
|
||||
/**
|
||||
* 必选
|
||||
* 每页数量
|
||||
*/
|
||||
private Integer limit;
|
||||
|
||||
public HistoryDataListPageReqVO(String beginTime, String endTime) {
|
||||
this.beginTime = beginTime;
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
|
||||
public static class HistoryDataTimeRangeUtil {
|
||||
|
||||
/**
|
||||
* 获取近12小时的时间范围
|
||||
*/
|
||||
public static HistoryDataListPageReqVO getLast12Hours() {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime startTime = endTime.minusHours(12);
|
||||
|
||||
return buildRequestVO(startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取近一天的时间范围
|
||||
*/
|
||||
public static HistoryDataListPageReqVO getLast24Hours() {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime startTime = endTime.minusDays(1);
|
||||
|
||||
return buildRequestVO(startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取近三天的时间范围
|
||||
*/
|
||||
public static HistoryDataListPageReqVO getLast3Days() {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime startTime = endTime.minusDays(3);
|
||||
|
||||
return buildRequestVO(startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取近七天的时间范围
|
||||
*/
|
||||
public static HistoryDataListPageReqVO getLast7Days() {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime startTime = endTime.minusDays(7);
|
||||
|
||||
return buildRequestVO(startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求VO对象
|
||||
*/
|
||||
private static HistoryDataListPageReqVO buildRequestVO(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
String beginTimeStamp = String.valueOf(startTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
||||
String endTimeStamp = String.valueOf(endTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
||||
|
||||
return new HistoryDataListPageReqVO(beginTimeStamp, endTimeStamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.history;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 墒情设备, 获取历史数据 响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 20:53
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class HistoryDataListPageRespVO {
|
||||
/**
|
||||
* 页码,每页数量,总页数,总条数
|
||||
*/
|
||||
private Integer pages;
|
||||
private Integer limit;
|
||||
private Integer totalPages;
|
||||
private Integer total;
|
||||
private List<Row> rows;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Row{
|
||||
/**
|
||||
* 记录表 id
|
||||
*/
|
||||
private Integer historyId;
|
||||
/**
|
||||
* 节点编号
|
||||
*/
|
||||
private Integer nodeId;
|
||||
/**
|
||||
* 设备地址
|
||||
*/
|
||||
private String deviceAddress;
|
||||
/**
|
||||
* 模拟量 1
|
||||
*/
|
||||
private String temStr;
|
||||
private Double temValue;
|
||||
/**
|
||||
* 模拟狼 2
|
||||
*/
|
||||
private String humStr;
|
||||
private Double humValue;
|
||||
/**
|
||||
* 是否是报警数据 0:正常 1:报警
|
||||
*/
|
||||
private Integer alarmStatus;
|
||||
/**
|
||||
* 保存时间(时间戳)
|
||||
*/
|
||||
private Long recordTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.login;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 登录请求实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 13:46
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserLoginReqVO {
|
||||
public String loginName;
|
||||
public String loginPwd;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.login;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 登录响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 13:46
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserLoginRespVO {
|
||||
|
||||
private String code;
|
||||
private String message;
|
||||
private VendorData data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class VendorData {
|
||||
/**
|
||||
* 登录标识
|
||||
*/
|
||||
public String loginSign;
|
||||
/**
|
||||
* token 生成时间
|
||||
*/
|
||||
public long currDate;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
public long expDate;
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
public String token;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 设备实时数据 请求实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 19:02
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealTimeDataReqVO {
|
||||
/**
|
||||
* 设备地址 非必定
|
||||
* tips: 多个用英文逗号分隔,空为获取当前用户下的所有设备
|
||||
*/
|
||||
private String deviceAddrs;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.devicelist.SysUserDeviceRespVO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 设备实时数据 相应试题
|
||||
* @author: binda
|
||||
* @date: 2025/9/17 19:01
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealTimeDataRespVO {
|
||||
|
||||
private String code;
|
||||
private String message;
|
||||
private List<DeviceInfo> data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DeviceInfo{
|
||||
/**
|
||||
* 设备地址
|
||||
*/
|
||||
private String deviceAddr;
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
private String deviceName;
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private Double lat;
|
||||
/**
|
||||
* 维度
|
||||
*/
|
||||
private Double lng;
|
||||
/**
|
||||
* 设备状态
|
||||
*/
|
||||
private String status;
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
private String deviceType;
|
||||
|
||||
private List<RealTimeData> data;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class RealTimeData {
|
||||
// 节点编号
|
||||
private Integer nodeId;
|
||||
// 节点名称
|
||||
private String nodeName;
|
||||
// 节点类型
|
||||
private Integer nodeType;
|
||||
// 模拟量1 名称,单位,原值,显示值,报警等级
|
||||
private String temName;
|
||||
private String temUnit;
|
||||
private Double temValue;
|
||||
private String temValueStr;
|
||||
private Integer temAlarmStatus;
|
||||
// 模拟量2 名称,单位,原值,显示值,报警等级
|
||||
private String humName;
|
||||
private String humUnit;
|
||||
private String humValue;
|
||||
private String humValueStr;
|
||||
private String humAlarmStatus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.devicelist;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 23:07
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DevicePageReqVO {
|
||||
/**
|
||||
* 令牌 必填
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userCode;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.devicelist;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 获取设备列表 分页响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/18 14:30
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DevicePageRespVO {
|
||||
private Integer code;
|
||||
private String msg;
|
||||
private Integer total;
|
||||
private List<Row> rows;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Row{
|
||||
private Long deviceId;
|
||||
private Long deptId;
|
||||
private String productCode;
|
||||
private String productName;
|
||||
private String modelCode;
|
||||
private String deviceCode;
|
||||
private String code; // 设备编号
|
||||
private String name;
|
||||
private String farmland;
|
||||
private String modelName;
|
||||
private String userCode;
|
||||
private Double lng;
|
||||
private Double lat;
|
||||
private Long farmlandId;
|
||||
private String delFlag;
|
||||
private String loginIp;
|
||||
private Date loginDate;
|
||||
private String createBy;
|
||||
private Date createTime;
|
||||
private String updateBy;
|
||||
private Date updateTime;
|
||||
private String remark;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.login;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 获取公钥 请求实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/18 14:19
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginReqVO {
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.login;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 获取公钥 响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/18 14:26
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginRespVO {
|
||||
private String code;
|
||||
private String msg;
|
||||
private String token;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.realtime;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: TODO
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 18:09
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealTimeDeviceDataReqVO {
|
||||
|
||||
/**
|
||||
* 设备编号 必填
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.realtime;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 设备实时数据
|
||||
* @author: binda
|
||||
* @date: 2025/9/18 14:38
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealTimeDeviceDataRespVO {
|
||||
private String deviceId;
|
||||
private String name;
|
||||
private String stateText; // 是否在线 中文
|
||||
private String stateValue; // 是否在线 编码
|
||||
private List<ControlProperty> controlProperties;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ControlProperty {
|
||||
private String id; // 开关标识
|
||||
private String name;
|
||||
private String operateType; // 设备类型
|
||||
private String operateValue;
|
||||
private String value;
|
||||
private String formatValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparams;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 21:01
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UpdateDeviceStatusReqVO {
|
||||
private String deviceId;
|
||||
private ParamStr paramStr;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ParamStr{
|
||||
// 设备开关名称
|
||||
private String Value1;
|
||||
// 要修改的值
|
||||
private String Value11;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparams;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @description: 更改设备属性 响应实体
|
||||
* @author: binda
|
||||
* @date: 2025/9/18 14:45
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UpdateDeviceStatusRespVO {
|
||||
private Integer code;
|
||||
private String msg;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:38
|
||||
*/
|
||||
public abstract class AbstractDeviceService extends TokenCacheService implements DeviceService{
|
||||
|
||||
@Override
|
||||
public UnifiedLoginResponse login(Long tenantId, String deviceId, Object loginRequest) {
|
||||
String cacheKey = generateCacheKey(getDeviceType(), tenantId, deviceId);
|
||||
|
||||
// 检查缓存中是否有有效token
|
||||
TokenCacheService.TokenInfo cachedToken = getToken(cacheKey);
|
||||
if (cachedToken != null && isTokenValid(cacheKey)) {
|
||||
return UnifiedLoginResponse.success(convertToLoginData(cachedToken));
|
||||
}
|
||||
|
||||
// 调用具体设备登录
|
||||
UnifiedLoginResponse loginResponse = doLogin(loginRequest);
|
||||
|
||||
if ("200".equals(loginResponse.getCode()) && loginResponse.getData() != null) {
|
||||
// 缓存token信息
|
||||
TokenCacheService.TokenInfo tokenInfo = new TokenCacheService.TokenInfo(
|
||||
loginResponse.getData().getToken(),
|
||||
loginResponse.getData().getCurrDate(),
|
||||
loginResponse.getData().getExpDate(),
|
||||
loginResponse.getData().getLoginSign()
|
||||
);
|
||||
cacheToken(cacheKey, tokenInfo);
|
||||
}
|
||||
|
||||
return loginResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceListResponse getDeviceList(Long tenantId, String token, Object listRequest) {
|
||||
// 验证token有效性
|
||||
String deviceCacheKey = generateDeviceCacheKey(getDeviceType(), tenantId, token);
|
||||
|
||||
// 先检查设备缓存
|
||||
List<DeviceInfo> cachedDevices = getDeviceList(deviceCacheKey);
|
||||
if (cachedDevices != null && !cachedDevices.isEmpty()) {
|
||||
return DeviceListResponse.success(cachedDevices);
|
||||
}
|
||||
|
||||
// 验证token是否有效
|
||||
if (!validateToken(tenantId, token)) {
|
||||
return DeviceListResponse.error("Token无效或已过期");
|
||||
}
|
||||
// TODO: 2025/9/25 如果token过期,直接登录重新获取token
|
||||
|
||||
// 调用具体设备获取列表
|
||||
DeviceListResponse listResponse = doGetDeviceList(token, listRequest);
|
||||
|
||||
if ("200".equals(listResponse.getCode()) && listResponse.getData() != null) {
|
||||
// 缓存设备列表
|
||||
cacheDeviceList(deviceCacheKey, listResponse.getData());
|
||||
}
|
||||
|
||||
return listResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealTimeDataResponse getRealTimeData(Long tenantId, String token, Object realTimeRequest) {
|
||||
// 验证token有效性
|
||||
if (!validateToken(tenantId, token)) {
|
||||
return RealTimeDataResponse.error("Token无效或已过期");
|
||||
}
|
||||
|
||||
// 调用具体设备获取实时数据
|
||||
return doGetRealTimeData(token, realTimeRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoryDataResponse getHistoryData(Long tenantId, String token, Object historyRequest) {
|
||||
// 验证token有效性
|
||||
if (!validateToken(tenantId, token)) {
|
||||
return HistoryDataResponse.error("Token无效或已过期");
|
||||
}
|
||||
|
||||
// 调用具体设备获取历史数据
|
||||
return doGetHistoryData(token, historyRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateDeviceResponse updateDeviceProperties(Long tenantId, String token, Object updateRequest) {
|
||||
// 验证token有效性
|
||||
if (!validateToken(tenantId, token)) {
|
||||
return UpdateDeviceResponse.error("Token无效或已过期");
|
||||
}
|
||||
|
||||
// 调用具体设备更新属性
|
||||
return doUpdateDeviceProperties(token, updateRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 具体设备登录逻辑(由子类实现)
|
||||
*/
|
||||
protected abstract UnifiedLoginResponse doLogin(Object loginRequest);
|
||||
|
||||
/**
|
||||
* 具体设备获取列表逻辑(由子类实现)
|
||||
*/
|
||||
protected abstract DeviceListResponse doGetDeviceList(String token, Object listRequest);
|
||||
|
||||
/**
|
||||
* 具体设备获取实时数据逻辑(由子类实现)
|
||||
*/
|
||||
protected abstract RealTimeDataResponse doGetRealTimeData(String token, Object realTimeRequest);
|
||||
|
||||
/**
|
||||
* 默认实现:不支持设备属性更新功能
|
||||
* 子类可以重写此方法来实现具体的属性更新逻辑
|
||||
*/
|
||||
protected UpdateDeviceResponse doUpdateDeviceProperties(String token, Object updateRequest) {
|
||||
return UpdateDeviceResponse.notSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认实现:不支持历史数据功能
|
||||
* 子类可以重写此方法来实现具体的历史数据获取逻辑
|
||||
*/
|
||||
protected HistoryDataResponse doGetHistoryData(String token, Object historyRequest) {
|
||||
return HistoryDataResponse.notSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换TokenInfo为LoginData
|
||||
*/
|
||||
protected UnifiedLoginResponse.LoginData convertToLoginData(TokenCacheService.TokenInfo tokenInfo) {
|
||||
return new UnifiedLoginResponse.LoginData(
|
||||
tokenInfo.getLoginSign(),
|
||||
tokenInfo.getCurrDate(),
|
||||
tokenInfo.getExpDate(),
|
||||
tokenInfo.getToken()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证token有效性
|
||||
*/
|
||||
private boolean validateToken(Long tenantId, String token) {
|
||||
// 遍历token缓存,查找匹配的token
|
||||
for (Map.Entry<String, TokenCacheService.TokenInfo> entry : tokenCacheMap.entrySet()) {
|
||||
if (entry.getKey().startsWith(getDeviceType() + ":" + tenantId + ":") &&
|
||||
token.equals(entry.getValue().getToken()) &&
|
||||
isTokenValid(entry.getKey())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.*;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @data: 2025/9/25 20:35
|
||||
*/
|
||||
public interface DeviceService {
|
||||
|
||||
String getDeviceType();
|
||||
|
||||
/**
|
||||
* 登录获取token
|
||||
*/
|
||||
UnifiedLoginResponse login(Long tenantId, String deviceId, Object loginRequest);
|
||||
|
||||
/**
|
||||
* 获取设备列表
|
||||
*/
|
||||
DeviceListResponse getDeviceList(Long tenantId, String token, Object listRequest);
|
||||
|
||||
/**
|
||||
* 获取实时数据
|
||||
*/
|
||||
RealTimeDataResponse getRealTimeData(Long tenantId, String token, Object realTimeRequest);
|
||||
|
||||
/**
|
||||
* 获取历史数据
|
||||
*/
|
||||
HistoryDataResponse getHistoryData(Long tenantId, String token, Object historyRequest);
|
||||
|
||||
/**
|
||||
* 更新设备属性
|
||||
*/
|
||||
UpdateDeviceResponse updateDeviceProperties(Long tenantId, String token, Object updateRequest);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @description: 设备历史数据持久化
|
||||
* @author: binda
|
||||
* @date: 2025/9/26 20:37
|
||||
*/
|
||||
@Service
|
||||
public class HistoryDataStorageService {
|
||||
|
||||
// 模拟MySQL表存储 - 实际项目中这里会是MyBatis Mapper或JPA Repository
|
||||
private final Map<String, List<HistoryDataEntity>> historyDataStorage = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public void saveHistoryData(String deviceAddr, List<HistoryDataEntity> historyData) {
|
||||
|
||||
}
|
||||
|
||||
public List<HistoryDataEntity> queryHistoryData(String deviceAddr,
|
||||
Long beginTime,
|
||||
Long endTime,
|
||||
Integer page,
|
||||
Integer limit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getTotalCount(String deviceAddr, Long beginTime, Long endTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class HistoryDataEntity {
|
||||
/**
|
||||
* 记录表 id
|
||||
*/
|
||||
private Integer historyId;
|
||||
/**
|
||||
* 节点编号
|
||||
*/
|
||||
private Integer nodeId;
|
||||
/**
|
||||
* 设备地址
|
||||
*/
|
||||
private String deviceAddress;
|
||||
/**
|
||||
* 模拟量 1
|
||||
*/
|
||||
private String temStr;
|
||||
private Double temValue;
|
||||
/**
|
||||
* 模拟量 2
|
||||
*/
|
||||
private String humStr;
|
||||
private Double humValue;
|
||||
/**
|
||||
* 是否是报警数据 0:正常 1:报警
|
||||
*/
|
||||
private Integer alarmStatus;
|
||||
/**
|
||||
* 保存时间(时间戳)
|
||||
*/
|
||||
private Long recordTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:38
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class TokenCacheService {
|
||||
|
||||
public final Map<String, TokenInfo> tokenCacheMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, List<DeviceInfo>> deviceCacheMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 生成缓存key
|
||||
* @param deviceType 设备类型
|
||||
* @param tenantId 租户ID
|
||||
* @param identifier 设备表主键ID
|
||||
* @return
|
||||
*/
|
||||
public String generateCacheKey(String deviceType, Long tenantId, String identifier) {
|
||||
return deviceType + ":" + tenantId + ":" + identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成设别列表key
|
||||
* @param deviceType 设备类型
|
||||
* @param tenantId 租户ID
|
||||
* @param token 令牌
|
||||
* @return
|
||||
*/
|
||||
public String generateDeviceCacheKey(String deviceType, Long tenantId, String token) {
|
||||
return deviceType + ":" + tenantId + ":" + token;
|
||||
}
|
||||
/**
|
||||
* 缓存token信息
|
||||
*/
|
||||
public void cacheToken(String key, TokenInfo tokenInfo) {
|
||||
tokenCacheMap.put(key, tokenInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过key获取token信息
|
||||
*/
|
||||
public TokenInfo getToken(String key) {
|
||||
return tokenCacheMap.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证token是否有效
|
||||
*/
|
||||
public boolean isTokenValid(String key) {
|
||||
TokenInfo tokenInfo = tokenCacheMap.get(key);
|
||||
if (tokenInfo == null) {
|
||||
return false;
|
||||
}
|
||||
return tokenInfo.getExpDate() > System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除token
|
||||
*/
|
||||
public void removeToken(String key) {
|
||||
tokenCacheMap.remove(key);
|
||||
}
|
||||
|
||||
// 设备列表缓存相关方法
|
||||
public void cacheDeviceList(String key, List<DeviceInfo> deviceList) {
|
||||
deviceCacheMap.put(key, deviceList);
|
||||
}
|
||||
|
||||
public List<DeviceInfo> getDeviceList(String key) {
|
||||
return deviceCacheMap.get(key);
|
||||
}
|
||||
|
||||
public void removeDeviceList(String key) {
|
||||
deviceCacheMap.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定期清除过期token
|
||||
*/
|
||||
@Scheduled(fixedRate = 300000) // 每5分钟执行一次
|
||||
public void cleanupExpiredTokens() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
// 清理过期token
|
||||
Iterator<Map.Entry<String, TokenInfo>> tokenIterator = tokenCacheMap.entrySet().iterator();
|
||||
while (tokenIterator.hasNext()) {
|
||||
Map.Entry<String, TokenInfo> entry = tokenIterator.next();
|
||||
if (entry.getValue().getExpDate() <= currentTime) {
|
||||
tokenIterator.remove();
|
||||
// 同时清理对应的设备缓存
|
||||
removeDeviceList(entry.getKey());
|
||||
}
|
||||
}
|
||||
log.info("清理过期token缓存");
|
||||
|
||||
// 清理长时间未使用的设备缓存(可选)
|
||||
}
|
||||
|
||||
/**
|
||||
* Token信息封装
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class TokenInfo {
|
||||
private String token;
|
||||
private Long currDate;
|
||||
private Long expDate;
|
||||
private String loginSign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token信息封装
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DeviceInfo {
|
||||
// 设备编号
|
||||
private String deviceCode;
|
||||
// 设备名称
|
||||
private String deviceName;
|
||||
// 扩展字段,用于存储原始设备信息
|
||||
private Map<String, Object> extraInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.impl;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.DeviceListResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.HistoryDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.UnifiedLoginResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.devicelist.SysUserDeviceReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.devicelist.SysUserDeviceRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.history.HistoryDataListPageReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.history.HistoryDataListPageRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.login.UserLoginReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.login.UserLoginRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime.RealTimeDataReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime.RealTimeDataRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.AbstractDeviceService;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.HistoryDataStorageService;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @description: 土壤墒情
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:40
|
||||
*/
|
||||
@Service
|
||||
public class SoilService extends AbstractDeviceService {
|
||||
|
||||
private final HistoryDataStorageService historyDataStorageService;
|
||||
|
||||
public SoilService(HistoryDataStorageService historyDataStorageService) {
|
||||
this.historyDataStorageService = historyDataStorageService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceType() {
|
||||
return "soil";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnifiedLoginResponse doLogin(Object loginRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
UserLoginReqVO soilRequest = (UserLoginReqVO) loginRequest;
|
||||
|
||||
// TODO: 2025/9/25 调用土壤设备厂商API POST 请求方式
|
||||
UserLoginRespVO vendorResponse = callSoilVendorApi(soilRequest);
|
||||
|
||||
// 转换为统一响应格式
|
||||
return convertToUnifiedResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return UnifiedLoginResponse.error("土壤设备登录失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceListResponse doGetDeviceList(String token, Object listRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
SysUserDeviceReqVO soilRequest = (SysUserDeviceReqVO) listRequest;
|
||||
|
||||
// TODO: 2025/9/25 调用土壤设备厂商API获取设备列表 GET 请求方式
|
||||
SysUserDeviceRespVO vendorResponse = callSoilDeviceListApi(token, soilRequest);
|
||||
|
||||
// 转换为统一响应格式
|
||||
return convertToUnifiedDeviceResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return DeviceListResponse.error("土壤设备列表获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RealTimeDataResponse doGetRealTimeData(String token, Object realTimeRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
RealTimeDataReqVO soilRequest = (RealTimeDataReqVO) realTimeRequest;
|
||||
|
||||
// TODO: 2025/9/26 调用土壤设备厂商API获取实时数据
|
||||
RealTimeDataRespVO vendorResponse = callSoilRealTimeDataApi(token, soilRequest);
|
||||
|
||||
// 直接返回原始响应数据,不进行统一转换
|
||||
return RealTimeDataResponse.success(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return RealTimeDataResponse.error("土壤设备实时数据获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HistoryDataResponse doGetHistoryData(String token, Object historyRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
HistoryDataListPageReqVO soilRequest = (HistoryDataListPageReqVO) historyRequest;
|
||||
|
||||
// TODO: 2025/9/26 调用土壤设备厂商API获取历史数据
|
||||
HistoryDataListPageRespVO vendorResponse = callSoilHistoryDataApi(token, soilRequest);
|
||||
|
||||
// TODO: 2025/9/26 模拟保存到MySQL
|
||||
saveHistoryDataToDatabase(vendorResponse, soilRequest);
|
||||
|
||||
return HistoryDataResponse.success(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return HistoryDataResponse.error("土壤设备历史数据获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private UserLoginRespVO callSoilVendorApi(UserLoginReqVO request) {
|
||||
// 模拟调用土壤设备厂商API
|
||||
// 实际实现中这里会是HTTP请求
|
||||
UserLoginRespVO response = new UserLoginRespVO();
|
||||
response.setCode("200");
|
||||
response.setMessage("成功");
|
||||
response.setData(new UserLoginRespVO.VendorData());
|
||||
response.getData().setLoginSign("soil-login-sign-" + System.currentTimeMillis());
|
||||
response.getData().setCurrDate(System.currentTimeMillis());
|
||||
response.getData().setExpDate(System.currentTimeMillis() + 3600000); // 1小时后过期
|
||||
response.getData().setToken("soil-token-" + System.currentTimeMillis());
|
||||
return response;
|
||||
}
|
||||
|
||||
private UnifiedLoginResponse convertToUnifiedResponse(UserLoginRespVO vendorResponse) {
|
||||
if (!"200".equals(vendorResponse.getCode())) {
|
||||
return UnifiedLoginResponse.error(vendorResponse.getMessage());
|
||||
}
|
||||
|
||||
UnifiedLoginResponse.LoginData loginData = new UnifiedLoginResponse.LoginData(
|
||||
vendorResponse.getData().getLoginSign(),
|
||||
vendorResponse.getData().getCurrDate(),
|
||||
vendorResponse.getData().getExpDate(),
|
||||
vendorResponse.getData().getToken()
|
||||
);
|
||||
|
||||
return UnifiedLoginResponse.success(loginData);
|
||||
}
|
||||
|
||||
private SysUserDeviceRespVO callSoilDeviceListApi(String token, SysUserDeviceReqVO request) {
|
||||
// 模拟调用土壤设备厂商API
|
||||
SysUserDeviceRespVO response = new SysUserDeviceRespVO();
|
||||
response.setCode("200");
|
||||
response.setMessage("成功");
|
||||
|
||||
List<SysUserDeviceRespVO.DeviceInfo> deviceList = new ArrayList<>();
|
||||
|
||||
// 模拟设备数据
|
||||
SysUserDeviceRespVO.DeviceInfo device1 = new SysUserDeviceRespVO.DeviceInfo();
|
||||
device1.setDeviceAddr("SOIL_001");
|
||||
device1.setDeviceName("土壤监测设备1");
|
||||
device1.setGroupId("G001");
|
||||
device1.setDeviceType("SOIL_MONITOR");
|
||||
deviceList.add(device1);
|
||||
|
||||
SysUserDeviceRespVO.DeviceInfo device2 = new SysUserDeviceRespVO.DeviceInfo();
|
||||
device2.setDeviceAddr("SOIL_002");
|
||||
device2.setDeviceName("土壤监测设备2");
|
||||
device2.setGroupId("G001");
|
||||
device2.setDeviceType("SOIL_MONITOR");
|
||||
deviceList.add(device2);
|
||||
|
||||
response.setData(deviceList);
|
||||
return response;
|
||||
}
|
||||
|
||||
private DeviceListResponse convertToUnifiedDeviceResponse(SysUserDeviceRespVO vendorResponse) {
|
||||
if (!"200".equals(vendorResponse.getCode())) {
|
||||
return DeviceListResponse.error(vendorResponse.getMessage());
|
||||
}
|
||||
|
||||
List<TokenCacheService.DeviceInfo> unifiedDevices = vendorResponse.getData().stream()
|
||||
.map(vendorDevice -> {
|
||||
TokenCacheService.DeviceInfo device = new TokenCacheService.DeviceInfo();
|
||||
device.setDeviceCode(vendorDevice.getDeviceAddr());
|
||||
device.setDeviceName(vendorDevice.getDeviceName());
|
||||
|
||||
// 保存原始设备信息到extraInfo
|
||||
Map<String, Object> extraInfo = new HashMap<>();
|
||||
extraInfo.put("groupId", vendorDevice.getGroupId());
|
||||
extraInfo.put("deviceType", vendorDevice.getDeviceType());
|
||||
extraInfo.put("deviceLng", vendorDevice.getDeviceLng());
|
||||
extraInfo.put("deviceLat", vendorDevice.getDeviceLat());
|
||||
extraInfo.put("deviceIccId", vendorDevice.getDeviceIccId());
|
||||
device.setExtraInfo(extraInfo);
|
||||
|
||||
return device;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return DeviceListResponse.success(unifiedDevices);
|
||||
}
|
||||
|
||||
private RealTimeDataRespVO callSoilRealTimeDataApi(String token, RealTimeDataReqVO request) {
|
||||
// 模拟调用土壤设备厂商API获取实时数据
|
||||
RealTimeDataRespVO response = new RealTimeDataRespVO();
|
||||
response.setCode("200");
|
||||
response.setMessage("成功");
|
||||
|
||||
List<RealTimeDataRespVO.DeviceInfo> deviceList = new ArrayList<>();
|
||||
|
||||
// 模拟设备1的实时数据
|
||||
RealTimeDataRespVO.DeviceInfo device1 = new RealTimeDataRespVO.DeviceInfo();
|
||||
device1.setDeviceAddr("SOIL_001");
|
||||
device1.setDeviceName("土壤监测设备1");
|
||||
device1.setLat(39.9093);
|
||||
device1.setLng(116.3974);
|
||||
device1.setStatus("在线");
|
||||
device1.setDeviceType("SOIL_MONITOR");
|
||||
|
||||
List<RealTimeDataRespVO.RealTimeData> realTimeDataList1 = new ArrayList<>();
|
||||
|
||||
// 节点1数据
|
||||
RealTimeDataRespVO.RealTimeData node1 = new RealTimeDataRespVO.RealTimeData();
|
||||
node1.setNodeId(1);
|
||||
node1.setNodeName("土壤温度监测点");
|
||||
node1.setNodeType(1);
|
||||
node1.setTemName("土壤温度");
|
||||
node1.setTemUnit("°C");
|
||||
node1.setTemValue(25.6);
|
||||
node1.setTemValueStr("25.6°C");
|
||||
node1.setTemAlarmStatus(0);
|
||||
realTimeDataList1.add(node1);
|
||||
|
||||
// 节点2数据
|
||||
RealTimeDataRespVO.RealTimeData node2 = new RealTimeDataRespVO.RealTimeData();
|
||||
node2.setNodeId(2);
|
||||
node2.setNodeName("土壤湿度监测点");
|
||||
node2.setNodeType(2);
|
||||
node2.setHumName("土壤湿度");
|
||||
node2.setHumUnit("%");
|
||||
node2.setHumValue("65.2");
|
||||
node2.setHumValueStr("65.2%");
|
||||
node2.setHumAlarmStatus("0");
|
||||
realTimeDataList1.add(node2);
|
||||
|
||||
device1.setData(realTimeDataList1);
|
||||
deviceList.add(device1);
|
||||
|
||||
// 模拟设备2的实时数据(如果请求了多个设备)
|
||||
if (request.getDeviceAddrs() != null && request.getDeviceAddrs().contains("SOIL_002")) {
|
||||
RealTimeDataRespVO.DeviceInfo device2 = new RealTimeDataRespVO.DeviceInfo();
|
||||
device2.setDeviceAddr("SOIL_002");
|
||||
device2.setDeviceName("土壤监测设备2");
|
||||
device2.setLat(39.9193);
|
||||
device2.setLng(116.4074);
|
||||
device2.setStatus("离线");
|
||||
device2.setDeviceType("SOIL_MONITOR");
|
||||
|
||||
List<RealTimeDataRespVO.RealTimeData> realTimeDataList2 = new ArrayList<>();
|
||||
RealTimeDataRespVO.RealTimeData node3 = new RealTimeDataRespVO.RealTimeData();
|
||||
node3.setNodeId(1);
|
||||
node3.setNodeName("土壤温度监测点");
|
||||
node3.setNodeType(1);
|
||||
node3.setTemName("土壤温度");
|
||||
node3.setTemUnit("°C");
|
||||
node3.setTemValue(23.1);
|
||||
node3.setTemValueStr("23.1°C");
|
||||
node3.setTemAlarmStatus(0);
|
||||
realTimeDataList2.add(node3);
|
||||
|
||||
device2.setData(realTimeDataList2);
|
||||
deviceList.add(device2);
|
||||
}
|
||||
|
||||
response.setData(deviceList);
|
||||
return response;
|
||||
}
|
||||
|
||||
private HistoryDataListPageRespVO callSoilHistoryDataApi(String token, HistoryDataListPageReqVO request) {
|
||||
// 模拟调用土壤设备厂商API获取历史数据
|
||||
HistoryDataListPageRespVO response = new HistoryDataListPageRespVO();
|
||||
|
||||
// 设置分页信息
|
||||
response.setPages(request.getPages());
|
||||
response.setLimit(request.getLimit());
|
||||
|
||||
// 模拟从厂商API获取的数据
|
||||
List<HistoryDataListPageRespVO.Row> rows = generateMockHistoryData(
|
||||
request.getDeviceAddr(),
|
||||
Long.parseLong(request.getBeginTime()),
|
||||
Long.parseLong(request.getEndTime()),
|
||||
request.getNodeId()
|
||||
);
|
||||
|
||||
int total = rows.size();
|
||||
int totalPages = (int) Math.ceil((double) total / request.getLimit());
|
||||
|
||||
// 分页处理
|
||||
int fromIndex = (request.getPages() - 1) * request.getLimit();
|
||||
int toIndex = Math.min(fromIndex + request.getLimit(), total);
|
||||
|
||||
if (fromIndex >= total) {
|
||||
response.setRows(new ArrayList<>());
|
||||
} else {
|
||||
response.setRows(rows.subList(fromIndex, toIndex));
|
||||
}
|
||||
|
||||
response.setTotalPages(totalPages);
|
||||
response.setTotal(total);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private List<HistoryDataListPageRespVO.Row> generateMockHistoryData(String deviceAddr, Long beginTime, Long endTime, String nodeId) {
|
||||
List<HistoryDataListPageRespVO.Row> rows = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
|
||||
// 生成模拟数据 - 假设每小时间隔一条数据
|
||||
long currentTime = beginTime;
|
||||
int recordId = 1;
|
||||
|
||||
while (currentTime <= endTime) {
|
||||
HistoryDataListPageRespVO.Row row = new HistoryDataListPageRespVO.Row();
|
||||
row.setHistoryId(recordId++);
|
||||
row.setNodeId(nodeId != null ? Integer.parseInt(nodeId) : 1);
|
||||
row.setDeviceAddress(deviceAddr);
|
||||
|
||||
// 模拟温度数据
|
||||
double tempValue = 20 + random.nextDouble() * 15; // 20-35°C
|
||||
row.setTemValue(tempValue);
|
||||
row.setTemStr(String.format("%.1f°C", tempValue));
|
||||
|
||||
// 模拟湿度数据
|
||||
double humidityValue = 30 + random.nextDouble() * 40; // 30-70%
|
||||
row.setHumValue(humidityValue);
|
||||
row.setHumStr(String.format("%.1f%%", humidityValue));
|
||||
|
||||
// 模拟报警状态(5%的概率报警)
|
||||
row.setAlarmStatus(random.nextDouble() < 0.05 ? 1 : 0);
|
||||
row.setRecordTime(currentTime);
|
||||
|
||||
rows.add(row);
|
||||
currentTime += 3600000; // 增加1小时
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
private void saveHistoryDataToDatabase(HistoryDataListPageRespVO response, HistoryDataListPageReqVO request) {
|
||||
if (historyDataStorageService != null && response.getRows() != null) {
|
||||
// 转换为实体类
|
||||
List<HistoryDataStorageService.HistoryDataEntity> entities = response.getRows().stream()
|
||||
.map(row -> {
|
||||
HistoryDataStorageService.HistoryDataEntity entity = new HistoryDataStorageService.HistoryDataEntity();
|
||||
entity.setHistoryId(row.getHistoryId());
|
||||
entity.setNodeId(row.getNodeId());
|
||||
entity.setDeviceAddress(row.getDeviceAddress());
|
||||
entity.setTemStr(row.getTemStr());
|
||||
entity.setTemValue(row.getTemValue());
|
||||
entity.setHumStr(row.getHumStr());
|
||||
entity.setHumValue(row.getHumValue());
|
||||
entity.setAlarmStatus(row.getAlarmStatus());
|
||||
entity.setRecordTime(row.getRecordTime());
|
||||
return entity;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 保存到模拟数据库
|
||||
historyDataStorageService.saveHistoryData(request.getDeviceAddr(), entities);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.impl;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.DeviceListResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.UnifiedLoginResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.UpdateDeviceResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.devicelist.DevicePageReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.devicelist.DevicePageRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.login.LoginReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.login.LoginRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.realtime.RealTimeDeviceDataReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.realtime.RealTimeDeviceDataRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparams.UpdateDeviceStatusReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparams.UpdateDeviceStatusRespVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.AbstractDeviceService;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @description: 水肥机
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:42
|
||||
*/
|
||||
@Service
|
||||
public class WaterFertilizerService extends AbstractDeviceService {
|
||||
|
||||
@Override
|
||||
public String getDeviceType() {
|
||||
return "water_fertilizer";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnifiedLoginResponse doLogin(Object loginRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
LoginReqVO wfRequest = (LoginReqVO) loginRequest;
|
||||
|
||||
// TODO: 2025/9/25 调用水肥机设备厂商API POST 请求方式
|
||||
LoginRespVO vendorResponse = callWFVendorApi(wfRequest);
|
||||
|
||||
// 转换为统一响应格式
|
||||
return convertToUnifiedResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return UnifiedLoginResponse.error("水肥机设备登录失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceListResponse doGetDeviceList(String token, Object listRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
DevicePageReqVO wfRequest = (DevicePageReqVO) listRequest;
|
||||
|
||||
// TODO: 2025/9/25 调用水肥机设备厂商API获取设备列表 GET 请求方式
|
||||
DevicePageRespVO vendorResponse = callWFDeviceListApi(token, wfRequest);
|
||||
|
||||
// 转换为统一响应格式
|
||||
return convertToUnifiedDeviceResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return DeviceListResponse.error("水肥机设备列表获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RealTimeDataResponse doGetRealTimeData(String token, Object realTimeRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
RealTimeDeviceDataReqVO wfRequest = (RealTimeDeviceDataReqVO) realTimeRequest;
|
||||
|
||||
// TODO: 2025/9/26 调用水肥机设备厂商API获取实时数据
|
||||
RealTimeDeviceDataRespVO vendorResponse = callWFRealTimeDataApi(token, wfRequest);
|
||||
|
||||
// 直接返回原始响应数据,不进行统一转换
|
||||
return RealTimeDataResponse.success(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return RealTimeDataResponse.error("水肥机设备实时数据获取失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpdateDeviceResponse doUpdateDeviceProperties(String token, Object updateRequest) {
|
||||
try {
|
||||
// 转换请求参数
|
||||
UpdateDeviceStatusReqVO wfRequest = (UpdateDeviceStatusReqVO) updateRequest;
|
||||
|
||||
// TODO: 2025/9/26 调用水肥机设备厂商API更新设备属性
|
||||
UpdateDeviceStatusRespVO vendorResponse = callWFUpdateDeviceApi(token, wfRequest);
|
||||
|
||||
// 转换为统一响应格式
|
||||
return convertToUnifiedUpdateResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
return UpdateDeviceResponse.error("水肥机设备属性更新失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private LoginRespVO callWFVendorApi(LoginReqVO request) {
|
||||
// 模拟调用水肥机设备厂商API
|
||||
LoginRespVO response = new LoginRespVO();
|
||||
response.setCode("200");
|
||||
response.setMsg("成功");
|
||||
response.setToken("wf-token-" + System.currentTimeMillis());
|
||||
return response;
|
||||
}
|
||||
|
||||
private UnifiedLoginResponse convertToUnifiedResponse(LoginRespVO vendorResponse) {
|
||||
if (!"200".equals(vendorResponse.getCode())) {
|
||||
return UnifiedLoginResponse.error(vendorResponse.getMsg());
|
||||
}
|
||||
|
||||
// 水肥机响应缺少一些字段,设置默认值
|
||||
long currentTime = System.currentTimeMillis();
|
||||
UnifiedLoginResponse.LoginData loginData = new UnifiedLoginResponse.LoginData(
|
||||
"wf-login-sign-" + currentTime, // 生成登录标识
|
||||
currentTime, // token生成时间
|
||||
currentTime + 3600000 * 2, // 2小时后过期
|
||||
vendorResponse.getToken() // 实际token
|
||||
);
|
||||
|
||||
return UnifiedLoginResponse.success(loginData);
|
||||
}
|
||||
|
||||
private DevicePageRespVO callWFDeviceListApi(String token, DevicePageReqVO request) {
|
||||
// 模拟调用水肥机设备厂商API
|
||||
DevicePageRespVO response = new DevicePageRespVO();
|
||||
response.setCode(200);
|
||||
response.setMsg("成功");
|
||||
response.setTotal(2);
|
||||
|
||||
List<DevicePageRespVO.Row> rows = new ArrayList<>();
|
||||
|
||||
// 模拟设备数据
|
||||
DevicePageRespVO.Row row1 = new DevicePageRespVO.Row();
|
||||
row1.setDeviceId(1L);
|
||||
row1.setCode("WF_001");
|
||||
row1.setName("水肥机设备1");
|
||||
row1.setLng(116.3974);
|
||||
row1.setLat(39.9093);
|
||||
rows.add(row1);
|
||||
|
||||
DevicePageRespVO.Row row2 = new DevicePageRespVO.Row();
|
||||
row2.setDeviceId(2L);
|
||||
row2.setCode("WF_002");
|
||||
row2.setName("水肥机设备2");
|
||||
row2.setLng(116.4074);
|
||||
row2.setLat(39.9193);
|
||||
rows.add(row2);
|
||||
|
||||
response.setRows(rows);
|
||||
return response;
|
||||
}
|
||||
|
||||
private DeviceListResponse convertToUnifiedDeviceResponse(DevicePageRespVO vendorResponse) {
|
||||
if (vendorResponse.getCode() != 200) {
|
||||
return DeviceListResponse.error(vendorResponse.getMsg());
|
||||
}
|
||||
|
||||
List<TokenCacheService.DeviceInfo> unifiedDevices = vendorResponse.getRows().stream()
|
||||
.map(vendorDevice -> {
|
||||
TokenCacheService.DeviceInfo device = new TokenCacheService.DeviceInfo();
|
||||
device.setDeviceCode(vendorDevice.getCode());
|
||||
device.setDeviceName(vendorDevice.getName());
|
||||
|
||||
// 保存原始设备信息到extraInfo
|
||||
Map<String, Object> extraInfo = new HashMap<>();
|
||||
extraInfo.put("deviceId", vendorDevice.getDeviceId());
|
||||
extraInfo.put("deptId", vendorDevice.getDeptId());
|
||||
extraInfo.put("lng", vendorDevice.getLng());
|
||||
extraInfo.put("lat", vendorDevice.getLat());
|
||||
extraInfo.put("farmland", vendorDevice.getFarmland());
|
||||
device.setExtraInfo(extraInfo);
|
||||
|
||||
return device;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return DeviceListResponse.success(unifiedDevices);
|
||||
}
|
||||
|
||||
private RealTimeDeviceDataRespVO callWFRealTimeDataApi(String token, RealTimeDeviceDataReqVO request) {
|
||||
// 模拟调用水肥机设备厂商API获取实时数据
|
||||
RealTimeDeviceDataRespVO response = new RealTimeDeviceDataRespVO();
|
||||
response.setDeviceId(request.getDeviceId());
|
||||
response.setName("水肥机设备-" + request.getDeviceId());
|
||||
response.setStateText("在线");
|
||||
response.setStateValue("online");
|
||||
|
||||
List<RealTimeDeviceDataRespVO.ControlProperty> controlProperties = new ArrayList<>();
|
||||
|
||||
// 模拟控制属性1 - 水泵状态
|
||||
RealTimeDeviceDataRespVO.ControlProperty prop1 = new RealTimeDeviceDataRespVO.ControlProperty();
|
||||
prop1.setId("pump_switch");
|
||||
prop1.setName("水泵开关");
|
||||
prop1.setOperateType("switch");
|
||||
prop1.setOperateValue("on,off");
|
||||
prop1.setValue("on");
|
||||
prop1.setFormatValue("开启");
|
||||
controlProperties.add(prop1);
|
||||
|
||||
// 模拟控制属性2 - 施肥状态
|
||||
RealTimeDeviceDataRespVO.ControlProperty prop2 = new RealTimeDeviceDataRespVO.ControlProperty();
|
||||
prop2.setId("fertilizer_switch");
|
||||
prop2.setName("施肥开关");
|
||||
prop2.setOperateType("switch");
|
||||
prop2.setOperateValue("on,off");
|
||||
prop2.setValue("off");
|
||||
prop2.setFormatValue("关闭");
|
||||
controlProperties.add(prop2);
|
||||
|
||||
// 模拟控制属性3 - 流量监测
|
||||
RealTimeDeviceDataRespVO.ControlProperty prop3 = new RealTimeDeviceDataRespVO.ControlProperty();
|
||||
prop3.setId("flow_rate");
|
||||
prop3.setName("水流量");
|
||||
prop3.setOperateType("monitor");
|
||||
prop3.setOperateValue("");
|
||||
prop3.setValue("12.5");
|
||||
prop3.setFormatValue("12.5 L/min");
|
||||
controlProperties.add(prop3);
|
||||
|
||||
// 模拟控制属性4 - EC值
|
||||
RealTimeDeviceDataRespVO.ControlProperty prop4 = new RealTimeDeviceDataRespVO.ControlProperty();
|
||||
prop4.setId("ec_value");
|
||||
prop4.setName("EC值");
|
||||
prop4.setOperateType("monitor");
|
||||
prop4.setOperateValue("");
|
||||
prop4.setValue("2.1");
|
||||
prop4.setFormatValue("2.1 mS/cm");
|
||||
controlProperties.add(prop4);
|
||||
|
||||
// 模拟控制属性5 - PH值
|
||||
RealTimeDeviceDataRespVO.ControlProperty prop5 = new RealTimeDeviceDataRespVO.ControlProperty();
|
||||
prop5.setId("ph_value");
|
||||
prop5.setName("PH值");
|
||||
prop5.setOperateType("monitor");
|
||||
prop5.setOperateValue("");
|
||||
prop5.setValue("6.8");
|
||||
prop5.setFormatValue("6.8");
|
||||
controlProperties.add(prop5);
|
||||
|
||||
response.setControlProperties(controlProperties);
|
||||
return response;
|
||||
}
|
||||
|
||||
private UpdateDeviceStatusRespVO callWFUpdateDeviceApi(String token, UpdateDeviceStatusReqVO request) {
|
||||
// 模拟调用水肥机设备厂商API更新设备属性
|
||||
UpdateDeviceStatusRespVO response = new UpdateDeviceStatusRespVO();
|
||||
|
||||
// 模拟设备控制逻辑
|
||||
String deviceId = request.getDeviceId();
|
||||
String switchName = request.getParamStr().getValue1();
|
||||
String newValue = request.getParamStr().getValue11();
|
||||
|
||||
System.out.println("更新水肥机设备属性 - 设备ID: " + deviceId +
|
||||
", 开关名称: " + switchName + ", 新值: " + newValue);
|
||||
|
||||
// 模拟不同的控制逻辑
|
||||
if ("pump_switch".equals(switchName)) {
|
||||
if ("on".equals(newValue)) {
|
||||
System.out.println("水泵开关已开启");
|
||||
response.setCode(200);
|
||||
response.setMsg("水泵开启成功");
|
||||
} else if ("off".equals(newValue)) {
|
||||
System.out.println("水泵开关已关闭");
|
||||
response.setCode(200);
|
||||
response.setMsg("水泵关闭成功");
|
||||
} else {
|
||||
response.setCode(400);
|
||||
response.setMsg("无效的水泵开关值: " + newValue);
|
||||
}
|
||||
} else if ("fertilizer_switch".equals(switchName)) {
|
||||
if ("on".equals(newValue)) {
|
||||
System.out.println("施肥开关已开启");
|
||||
response.setCode(200);
|
||||
response.setMsg("施肥开启成功");
|
||||
} else if ("off".equals(newValue)) {
|
||||
System.out.println("施肥开关已关闭");
|
||||
response.setCode(200);
|
||||
response.setMsg("施肥关闭成功");
|
||||
} else {
|
||||
response.setCode(400);
|
||||
response.setMsg("无效的施肥开关值: " + newValue);
|
||||
}
|
||||
} else if ("water_flow".equals(switchName)) {
|
||||
try {
|
||||
double flowRate = Double.parseDouble(newValue);
|
||||
if (flowRate > 0 && flowRate <= 100) {
|
||||
System.out.println("水流量设置为: " + flowRate + " L/min");
|
||||
response.setCode(200);
|
||||
response.setMsg("水流量设置成功");
|
||||
} else {
|
||||
response.setCode(400);
|
||||
response.setMsg("水流量值超出范围 (0-100 L/min)");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
response.setCode(400);
|
||||
response.setMsg("无效的水流量值: " + newValue);
|
||||
}
|
||||
} else {
|
||||
response.setCode(404);
|
||||
response.setMsg("不支持的设备开关: " + switchName);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private UpdateDeviceResponse convertToUnifiedUpdateResponse(UpdateDeviceStatusRespVO vendorResponse) {
|
||||
if (vendorResponse.getCode() == 200) {
|
||||
return UpdateDeviceResponse.success(vendorResponse);
|
||||
} else {
|
||||
return UpdateDeviceResponse.error(vendorResponse.getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,6 +378,7 @@ public class BaseInfoServiceImpl implements BaseInfoService {
|
||||
public CommonResult<List<FarmBaseInfoRespVO>> getBaseInfoList(FarmBaseInfoReqVO req) {
|
||||
LambdaQueryWrapperX<BaseInfoDO> wrapperX = new LambdaQueryWrapperX<>();
|
||||
wrapperX.eq(BaseInfoDO::getTenantId, req.getTenantId());
|
||||
wrapperX.eqIfPresent(BaseInfoDO::getId, req.getBaseId());
|
||||
wrapperX.eq(BaseInfoDO::getDeleted, CommonConstants.NO_CODE);
|
||||
List<BaseInfoDO> list = baseInfoMapper.selectList(wrapperX);
|
||||
|
||||
|
||||
@@ -103,6 +103,11 @@ public interface DeviceInfoService {
|
||||
* @return
|
||||
*/
|
||||
List<DeviceInfoDO> getBaseAndDeviceInfoList(String baseId);
|
||||
List<DeviceInfoDO> getBaseAndDeviceInfoList(String baseId,String plotId);
|
||||
|
||||
Map<String, String> getDeviceTypeNameMap(String tenantId);
|
||||
|
||||
List<String> getImage(String deviceType);
|
||||
|
||||
DeviceStateRespVO countDeviceState(String baseId, String tenantId);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.farm.service.deviceinfo;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.api.vo.*;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.deviceinfo.vo.DeviceInfoPageReqVO;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.deviceinfo.vo.DeviceInfoSaveReqVO;
|
||||
@@ -56,8 +57,8 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
private BaseInfoMapper baseInfoMapper;
|
||||
@Resource
|
||||
private PlotInfoMapper plotInfoMapper;
|
||||
@Resource
|
||||
private DeviceManager deviceManager;
|
||||
// @Resource
|
||||
// private DeviceManager deviceManager;
|
||||
|
||||
@Override
|
||||
public String createDeviceInfo(DeviceInfoSaveReqVO createReqVO) {
|
||||
@@ -139,9 +140,9 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
target.setDeviceTypeName(map.getOrDefault(target.getDeviceType(), ""));
|
||||
|
||||
// 从设备商服务 获取设备实时/历史数据
|
||||
DeviceInfoDetailV2RespVO realData = deviceManager.getRealData(id);
|
||||
target.setSoilInfo(realData.getSoilInfo());
|
||||
target.setWfInfo(realData.getWfInfo());
|
||||
// DeviceInfoDetailV2RespVO realData = deviceManager.getRealData(id);
|
||||
// target.setSoilInfo(realData.getSoilInfo());
|
||||
// target.setWfInfo(realData.getWfInfo());
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
dtList.add(new DeviceStateRespVO.DeviceType(v1, v2));
|
||||
}
|
||||
|
||||
DeviceStateRespVO res = deviceInfoMapper.countDeviceState(req.getTenantId());
|
||||
DeviceStateRespVO res = deviceInfoMapper.countDeviceState("",req.getTenantId());
|
||||
res.setDeviceTypeList(dtList);
|
||||
return success(res);
|
||||
}
|
||||
@@ -196,6 +197,17 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
return deviceInfoMapper.selectList(DeviceInfoDO::getBaseId,baseId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceInfoDO> getBaseAndDeviceInfoList(String baseId, String plotId) {
|
||||
LambdaQueryWrapperX<DeviceInfoDO> wrapperX = new LambdaQueryWrapperX<>();
|
||||
wrapperX.eq(DeviceInfoDO::getTenantId, String.valueOf(getLoginUser().getTenantId()));
|
||||
wrapperX.eq(DeviceInfoDO::getDeleted, CommonConstants.NO_CODE);
|
||||
|
||||
wrapperX.eqIfPresent(DeviceInfoDO::getBaseId, baseId);
|
||||
wrapperX.eqIfPresent(DeviceInfoDO::getPlotId, plotId);
|
||||
return deviceInfoMapper.selectList(wrapperX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getDeviceTypeNameMap(String tenantId) {
|
||||
List<DeviceClassifyDO> deviceClassifyDOS = deviceClassifyMapper.selectList(DeviceClassifyDO::getTenantId, tenantId);
|
||||
@@ -204,4 +216,14 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
.collect(Collectors.toMap(e -> e.getId().toString(), DeviceClassifyDO::getName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getImage(String deviceType) {
|
||||
DeviceClassifyDO dc = deviceClassifyMapper.selectOne(DeviceClassifyDO::getId, deviceType);
|
||||
return dc.getImageList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStateRespVO countDeviceState(String baseId,String tenantId) {
|
||||
return deviceInfoMapper.countDeviceState(baseId,tenantId);
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,7 @@ public class HomeServiceImpl implements HomeService {
|
||||
private BaseOverviewInfo getCompanyInfo() {
|
||||
LoginUser user = getLoginUser();
|
||||
int baseCount = baseInfoService.getBaseCount(user.getTenantId()); // 基地数量
|
||||
int cropCount = cropFarmingCenterService.getCropCount(user.getTenantId()); // 作物数mong量
|
||||
int cropCount = cropFarmingCenterService.getCropCount(user.getTenantId()); // 作物数量
|
||||
// Double temp = cropFarmingCenterService.getTotalArea(user.getTenantId()); // 总面积
|
||||
Double temp = baseInfoService.getBaseTotalArea(user.getTenantId().toString()); // 总面积
|
||||
int totalArea = 0;
|
||||
|
||||
@@ -8,6 +8,9 @@ import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.Productio
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.productionplan.ProductionPlanDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
@@ -201,4 +204,27 @@ public interface ProductionPlanService {
|
||||
* @return 获取该地块的计划数量
|
||||
*/
|
||||
int getPlanCount(String plotId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基地维护 统计在种物种,地块,地块面积
|
||||
* @param baseId
|
||||
* @param tenantId
|
||||
* @return int[0]: 在种作物数量
|
||||
* int[1]: 在种地块数量
|
||||
* int[2]: 在种地块面积
|
||||
*/
|
||||
CultivatingInfo getCultivatingInfo(String baseId, String tenantId);
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class CultivatingInfo {
|
||||
// 在种物种数量
|
||||
private Integer cultivatingSpeciesCount;
|
||||
// 在种地块数量
|
||||
private Integer cultivatingPlotCount;
|
||||
// 在种地块面积
|
||||
// private Integer cultivatingPlotAreaCount;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.farm.dal.dataobject.baseinfo.BaseInfoDO;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.specieslibrary.SpeciesLibraryDO;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.baseinfo.BaseInfoMapper;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.specieslibrary.SpeciesLibraryMapper;
|
||||
import cn.iocoder.yudao.module.farm.enums.CommonConstants;
|
||||
import cn.iocoder.yudao.module.farm.utils.DateUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
@@ -141,6 +142,7 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
|
||||
|
||||
QueryWrapper<ProductionPlanDO> qw = new QueryWrapper<>();
|
||||
qw.eq("tenant_id", user.getTenantId());
|
||||
qw.eq("plan_status", PLAN_STATUS_2);
|
||||
List<ProductionPlanDO> productionPlanDOS = productionPlanMapper.selectList(qw);
|
||||
|
||||
// 按基地ID分组
|
||||
@@ -406,4 +408,13 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
|
||||
List<ProductionPlanDO> planDOList = productionPlanMapper.selectList("plot_id", plotId);
|
||||
return planDOList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CultivatingInfo getCultivatingInfo(String baseId, String tenantId) {
|
||||
int cultivatingSpeciesCount = this.getGrowingCropCount(baseId);
|
||||
int cultivatingPlotCount = this.getGrowingPlotCount(baseId);
|
||||
return new CultivatingInfo(cultivatingSpeciesCount,cultivatingPlotCount);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -36,6 +36,15 @@
|
||||
SUM(CASE WHEN device_state = 1 THEN 1 ELSE 0 END) as totalOnlineDevices,
|
||||
SUM(CASE WHEN device_state != 1 THEN 1 ELSE 0 END) as totalOfflineDevices
|
||||
FROM farm_device_info
|
||||
WHERE tenant_id = #{tenantId} AND deleted = b'0'
|
||||
<where>
|
||||
deleted = b'0'
|
||||
<if test="baseId != null and baseId != ''">
|
||||
AND base_id = #{baseId}
|
||||
</if>
|
||||
<if test="tenantId != null and tenantId != ''">
|
||||
AND tenant_id = #{tenantId}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -14,9 +14,9 @@
|
||||
resultType="cn.iocoder.yudao.module.farm.controller.admin.api.vo.FarmingDistributionRespVO">
|
||||
SELECT
|
||||
COUNT(*) as totalCount,
|
||||
SUM(CASE WHEN task_status = 0 THEN 1 ELSE 0 END) as notStart,
|
||||
SUM(CASE WHEN task_status = 1 THEN 1 ELSE 0 END) as executingStatusCount,
|
||||
SUM(CASE WHEN task_status = 2 THEN 1 ELSE 0 END) as completedStatusCount
|
||||
COALESCE(SUM(CASE WHEN task_status = 0 THEN 1 ELSE 0 END),0) as notStart,
|
||||
COALESCE(SUM(CASE WHEN task_status = 1 THEN 1 ELSE 0 END),0) as executingStatusCount,
|
||||
COALESCE(SUM(CASE WHEN task_status = 2 THEN 1 ELSE 0 END),0) as completedStatusCount
|
||||
FROM farm_farming_record
|
||||
<where>
|
||||
del_status = 0
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
from farm_production_plan
|
||||
where tenant_id = #{tenantId}
|
||||
and deleted = 0
|
||||
and plan_status = 2
|
||||
</select>
|
||||
|
||||
<select id="getTotalArea" parameterType="Long" resultType="java.lang.Double">
|
||||
|
||||
Reference in New Issue
Block a user