Browse Source

feat:增加虚拟模式

master
白凤吉 3 weeks ago
parent
commit
af9bc14008
  1. 30
      src/main/java/com/qyft/ms/app/controller/TestController.java
  2. 16
      src/main/java/com/qyft/ms/app/core/event/VirtualDeviceCmdResponseEvent.java
  3. 12
      src/main/java/com/qyft/ms/app/core/listener/DeviceInitializerListener.java
  4. 20
      src/main/java/com/qyft/ms/app/core/listener/VirtualDeviceCmdResponseEventListener.java
  5. 7
      src/main/java/com/qyft/ms/app/device/status/DeviceStatus.java
  6. 13
      src/main/java/com/qyft/ms/app/service/TestService.java
  7. 48
      src/main/java/com/qyft/ms/app/service/VirtualDeviceService.java
  8. 19
      src/main/java/com/qyft/ms/system/service/device/DeviceCommandService.java

30
src/main/java/com/qyft/ms/app/controller/TestController.java

@ -0,0 +1,30 @@
package com.qyft.ms.app.controller;
import com.qyft.ms.app.device.status.DeviceStatus;
import com.qyft.ms.system.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试用
*/
@Tag(name = "测试用")
@RestController
@RequestMapping("/api/test")
@RequiredArgsConstructor
@Slf4j
public class TestController {
private final DeviceStatus deviceStatus;
@Operation(summary = "启动虚拟模式")
@PostMapping("/virtual")
public Result<?> changeVirtualMode() {
deviceStatus.setVirtual(true);
return Result.success();
}
}

16
src/main/java/com/qyft/ms/app/core/event/VirtualDeviceCmdResponseEvent.java

@ -0,0 +1,16 @@
package com.qyft.ms.app.core.event;
import com.qyft.ms.system.model.bo.DeviceCommand;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public class VirtualDeviceCmdResponseEvent extends ApplicationEvent {
private final DeviceCommand cmdToDevice;
public VirtualDeviceCmdResponseEvent(Object source, DeviceCommand cmdToDevice) {
super(source);
this.cmdToDevice = cmdToDevice;
}
}

12
src/main/java/com/qyft/ms/app/core/listener/DeviceInitializerListener.java

@ -27,11 +27,13 @@ public class DeviceInitializerListener {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Runnable task = () -> { Runnable task = () -> {
try { try {
DeviceCommand overallDeviceStatusGetCommand = DeviceCommandGenerator.overallDeviceStatusGet();
CommandFuture overallDeviceStatusGetCommandFuture = deviceCommandService.sendCommandNoFront(overallDeviceStatusGetCommand);
overallDeviceStatusGetCommandFuture.getResponseFuture().get(5, TimeUnit.SECONDS);
boolean emergencyStop = overallDeviceStatusGetCommandFuture.getResponseResult().getJSONObject("data").getBool("emergencyStop");
deviceStatus.setStopPressed(emergencyStop);
if(!deviceStatus.isVirtual()){
DeviceCommand overallDeviceStatusGetCommand = DeviceCommandGenerator.overallDeviceStatusGet();
CommandFuture overallDeviceStatusGetCommandFuture = deviceCommandService.sendCommandNoFront(overallDeviceStatusGetCommand);
overallDeviceStatusGetCommandFuture.getResponseFuture().get(5, TimeUnit.SECONDS);
boolean emergencyStop = overallDeviceStatusGetCommandFuture.getResponseResult().getJSONObject("data").getBool("emergencyStop");
deviceStatus.setStopPressed(emergencyStop);
}
scheduler.shutdown(); scheduler.shutdown();
} catch (Exception e) { } catch (Exception e) {
log.error("开机获取急停状态失败", e); log.error("开机获取急停状态失败", e);

20
src/main/java/com/qyft/ms/app/core/listener/VirtualDeviceCmdResponseEventListener.java

@ -0,0 +1,20 @@
package com.qyft.ms.app.core.listener;
import com.qyft.ms.app.core.event.VirtualDeviceCmdResponseEvent;
import com.qyft.ms.app.service.VirtualDeviceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class VirtualDeviceCmdResponseEventListener {
private final VirtualDeviceService virtualDeviceService;
@EventListener
public void handleDeviceTcpMessageEvent(VirtualDeviceCmdResponseEvent event) {
virtualDeviceService.completeCommandResponse(event.getCmdToDevice());
}
}

7
src/main/java/com/qyft/ms/app/device/status/DeviceStatus.java

@ -1,6 +1,7 @@
package com.qyft.ms.app.device.status; package com.qyft.ms.app.device.status;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -56,6 +57,11 @@ public class DeviceStatus {
*/ */
private volatile boolean stopPressed = false; private volatile boolean stopPressed = false;
/**
* 是否启动虚拟模式
*/
private boolean virtual = false;
public JSONObject toJSON() { public JSONObject toJSON() {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.putOnce("spraying", spraying); json.putOnce("spraying", spraying);
@ -67,6 +73,7 @@ public class DeviceStatus {
json.putOnce("dehumidifierRunning", dehumidifierRunning); json.putOnce("dehumidifierRunning", dehumidifierRunning);
json.putOnce("selfTestCompleted", selfTestCompleted); json.putOnce("selfTestCompleted", selfTestCompleted);
json.putOnce("stopPressed", stopPressed); json.putOnce("stopPressed", stopPressed);
json.putOnce("virtual", virtual);
return json; return json;
} }

13
src/main/java/com/qyft/ms/app/service/TestService.java

@ -0,0 +1,13 @@
package com.qyft.ms.app.service;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 测试用
*/
@Service
@RequiredArgsConstructor
public class TestService {
}

48
src/main/java/com/qyft/ms/app/service/VirtualDeviceService.java

@ -0,0 +1,48 @@
package com.qyft.ms.app.service;
import cn.hutool.json.JSONObject;
import com.qyft.ms.system.model.bo.DeviceCommand;
import com.qyft.ms.system.service.device.DeviceCommandService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 虚拟设备服务
*/
@Service
@RequiredArgsConstructor
public class VirtualDeviceService {
private final DeviceCommandService deviceCommandService;
public void completeCommandResponse(DeviceCommand cmdToDevice) {
new Thread(() -> {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.putOnce("cmdId", cmdToDevice.getCmdId());
jsonObject.putOnce("success", true);
String code = cmdToDevice.getCmdCode();
String action = cmdToDevice.getAction();
String device = cmdToDevice.getDevice();
if (code.contains("controlMotorCmd")) {
if (!action.contains("set")) {//非设置电机参数也就是电机移动
Thread.sleep(300);
}
} else if (code.contains("getInfoCmd")) {
if (device.contains("humidity")) {
if (action.contains("get")) {//获取温度
JSONObject data = new JSONObject();
data.putOnce("humidity", 26);
jsonObject.putOnce("data", data);
}
}
}
deviceCommandService.completeCommandResponse(jsonObject);
} catch (InterruptedException e) {
// 处理中断异常
Thread.currentThread().interrupt();
}
}).start();
}
}

19
src/main/java/com/qyft/ms/system/service/device/DeviceCommandService.java

@ -1,6 +1,8 @@
package com.qyft.ms.system.service.device; package com.qyft.ms.system.service.device;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.qyft.ms.app.core.event.VirtualDeviceCmdResponseEvent;
import com.qyft.ms.app.device.status.DeviceStatus; import com.qyft.ms.app.device.status.DeviceStatus;
import com.qyft.ms.system.common.constant.CommandStatus; import com.qyft.ms.system.common.constant.CommandStatus;
import com.qyft.ms.system.common.device.command.CommandFuture; import com.qyft.ms.system.common.device.command.CommandFuture;
@ -11,6 +13,7 @@ import com.qyft.ms.system.model.bo.DeviceCommand;
import com.qyft.ms.system.service.WebSocketService; import com.qyft.ms.system.service.WebSocketService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -20,13 +23,12 @@ import java.util.concurrent.ConcurrentMap;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class DeviceCommandService { public class DeviceCommandService {
private final ConcurrentMap<Integer, CommandFuture> commandFutureMap = new ConcurrentHashMap<>(); private final ConcurrentMap<Integer, CommandFuture> commandFutureMap = new ConcurrentHashMap<>();
private final DeviceTcpClient deviceTcpClient; private final DeviceTcpClient deviceTcpClient;
private final WebSocketService webSocketService; private final WebSocketService webSocketService;
private final DeviceStatus deviceStatus; private final DeviceStatus deviceStatus;
private final ApplicationEventPublisher publisher;
public CommandFuture executeCommand(DeviceCommand cmdToDevice) { public CommandFuture executeCommand(DeviceCommand cmdToDevice) {
int cmdId = CyclicNumberGenerator.getInstance().generateNumber(); int cmdId = CyclicNumberGenerator.getInstance().generateNumber();
@ -34,9 +36,16 @@ public class DeviceCommandService {
CommandFuture cmdFuture = new CommandFuture(); CommandFuture cmdFuture = new CommandFuture();
commandFutureMap.put(cmdToDevice.getCmdId(), cmdFuture); commandFutureMap.put(cmdToDevice.getCmdId(), cmdFuture);
cmdFuture.setStartSendTime(System.currentTimeMillis()); cmdFuture.setStartSendTime(System.currentTimeMillis());
if (!deviceTcpClient.sendToJSON(cmdToDevice)) {
commandFutureMap.remove(cmdToDevice.getCmdId());
throw new RuntimeException("向设备发送指令失败");
if (deviceStatus.isVirtual()) {
log.info("模拟向设备发送TCP指令:{}", JSONUtil.toJsonStr(cmdToDevice));
//模拟反馈
publisher.publishEvent(new VirtualDeviceCmdResponseEvent(this, cmdToDevice));
} else {
if (!deviceTcpClient.sendToJSON(cmdToDevice)) {
commandFutureMap.remove(cmdToDevice.getCmdId());
throw new RuntimeException("向设备发送指令失败");
}
} }
cmdFuture.getResponseFuture().whenComplete((result, ex) -> { cmdFuture.getResponseFuture().whenComplete((result, ex) -> {

Loading…
Cancel
Save