diff --git a/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStartCommand.java b/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStartCommand.java index 132a75e..882bc08 100644 --- a/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStartCommand.java +++ b/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStartCommand.java @@ -2,6 +2,7 @@ package com.iflytop.handacid.app.command.control; import com.iflytop.handacid.app.common.annotation.CommandMapping; import com.iflytop.handacid.app.core.command.BaseCommandHandler; +import com.iflytop.handacid.app.core.state.DeviceState; import com.iflytop.handacid.app.model.dto.CommandDTO; import com.iflytop.handacid.app.service.ChannelCtrlService; import lombok.RequiredArgsConstructor; @@ -11,7 +12,7 @@ import org.springframework.stereotype.Component; import java.util.concurrent.CompletableFuture; /** - * 开始加液(废弃) + * 开始加液 */ @Slf4j @Component @@ -19,9 +20,11 @@ import java.util.concurrent.CompletableFuture; @CommandMapping("solution_add_start") public class SolutionAddStartCommand extends BaseCommandHandler { private final ChannelCtrlService channelCtrlService; + private final DeviceState deviceState; @Override public CompletableFuture handle(CommandDTO commandDTO) { + return runAsync(() -> { channelCtrlService.solutionAddStart(); }); diff --git a/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStopCommand.java b/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStopCommand.java index 2b6685b..7a7e2a6 100644 --- a/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStopCommand.java +++ b/src/main/java/com/iflytop/handacid/app/command/control/SolutionAddStopCommand.java @@ -32,9 +32,7 @@ public class SolutionAddStopCommand extends BaseCommandHandler { @Override public CompletableFuture handle(CommandDTO commandDTO) { - return runAsync(() -> { - channelCtrlService.solutionAddStop(); - }); + return runAsync(channelCtrlService::solutionAddStop); } } diff --git a/src/main/java/com/iflytop/handacid/app/core/listener/BleGamepadEventListener.java b/src/main/java/com/iflytop/handacid/app/core/listener/BleGamepadEventListener.java index 63d742b..e6c2632 100644 --- a/src/main/java/com/iflytop/handacid/app/core/listener/BleGamepadEventListener.java +++ b/src/main/java/com/iflytop/handacid/app/core/listener/BleGamepadEventListener.java @@ -14,6 +14,7 @@ import org.springframework.stereotype.Component; /** * 蓝牙手柄按钮事件监听 + * */ @Component @@ -55,10 +56,10 @@ public class BleGamepadEventListener { } } else if (CmdId.event_ble_gamepad_connected.equals(cmdId)) { log.info("蓝牙手柄 连接成功"); - deviceState.setBluetoothConnected(true); + deviceState.getRemoteControlState().setConnected(true); } else if (CmdId.event_ble_gamepad_disconnected.equals(cmdId)) { log.info("蓝牙手柄 连接断开"); - deviceState.setBluetoothConnected(false); + deviceState.getRemoteControlState().setConnected(false); } } diff --git a/src/main/java/com/iflytop/handacid/app/core/state/DeviceState.java b/src/main/java/com/iflytop/handacid/app/core/state/DeviceState.java index 54863dc..a70047a 100644 --- a/src/main/java/com/iflytop/handacid/app/core/state/DeviceState.java +++ b/src/main/java/com/iflytop/handacid/app/core/state/DeviceState.java @@ -40,13 +40,16 @@ public class DeviceState { @Schema(description = "是否是急停状态,true为急停") private volatile boolean emergencyStop = false; - @Schema(description = "蓝牙是否连接") - private volatile boolean bluetoothConnected = false; + @Schema(description = "遥控器状态") + private volatile RemoteControlState remoteControlState; @Schema(description = "当前登录用户") private volatile User currentUser; - public JSONObject toJSON() { + /** + * 获得当前设备的json快照,增加synchronized保证强一致 + */ + public synchronized JSONObject toJSON() { JSONObject json = new JSONObject(); json.putOnce("channelState", new ArrayList<>(channelStateMap.values())); json.putOnce("mode", mode); @@ -54,7 +57,7 @@ public class DeviceState { json.putOnce("virtual", virtual); json.putOnce("initComplete", initComplete); json.putOnce("emergencyStop", emergencyStop); - json.putOnce("bluetoothConnected", bluetoothConnected); + json.putOnce("remoteControlState", remoteControlState); json.putOnce("currentUser", currentUser); return json; } diff --git a/src/main/java/com/iflytop/handacid/app/core/state/RemoteControlState.java b/src/main/java/com/iflytop/handacid/app/core/state/RemoteControlState.java new file mode 100644 index 0000000..17c55bc --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/core/state/RemoteControlState.java @@ -0,0 +1,27 @@ +package com.iflytop.handacid.app.core.state; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Schema(description = "遥控器状态") +@Data +@Component +@Scope("prototype") +@RequiredArgsConstructor +@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"}) +public class RemoteControlState { + + @Schema(description = "遥控器是否连接") + private volatile boolean connected = false; + + @Schema(description = "当前电量(0-100%)") + private volatile int batteryLevel = 0; + + @Schema(description = "是否正在充电") + private volatile boolean charging = false; + +} diff --git a/src/main/java/com/iflytop/handacid/app/scheduled/BleGamepadStateScheduledTask.java b/src/main/java/com/iflytop/handacid/app/scheduled/BleGamepadStateScheduledTask.java new file mode 100644 index 0000000..ab31fd1 --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/scheduled/BleGamepadStateScheduledTask.java @@ -0,0 +1,39 @@ +package com.iflytop.handacid.app.scheduled; + +import com.iflytop.handacid.app.core.state.DeviceState; +import com.iflytop.handacid.hardware.drivers.BleGamepadDriver; +import com.iflytop.handacid.hardware.type.BleGamepadMid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +/** + * 定时采集蓝牙的连接状态和电量 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class BleGamepadStateScheduledTask { + private final BleGamepadDriver bleGamepadDriver; + private final DeviceState deviceState; + + @Scheduled(fixedRate = 30 * 1000) + public void fetchTrayState() { + try { + + if (!deviceState.isVirtual()) { + boolean is_connect = bleGamepadDriver.is_connected(BleGamepadMid.BleGamePad); + deviceState.getRemoteControlState().setConnected(is_connect); + if (is_connect) { + Integer[] power_state = bleGamepadDriver.get_power_state(BleGamepadMid.BleGamePad); + deviceState.getRemoteControlState().setBatteryLevel(power_state[0]); + deviceState.getRemoteControlState().setCharging(power_state[1] != 0); + } + } + } catch (Exception e) { + log.error("定时采集蓝牙的连接状态和电量错误", e); + } + + } +} diff --git a/src/main/java/com/iflytop/handacid/app/service/ChannelCtrlService.java b/src/main/java/com/iflytop/handacid/app/service/ChannelCtrlService.java index 7f74e41..03346d3 100644 --- a/src/main/java/com/iflytop/handacid/app/service/ChannelCtrlService.java +++ b/src/main/java/com/iflytop/handacid/app/service/ChannelCtrlService.java @@ -1,6 +1,5 @@ package com.iflytop.handacid.app.service; -import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.iflytop.handacid.app.common.enums.ChannelCode; import com.iflytop.handacid.app.common.enums.ChannelStateCode; diff --git a/src/main/java/com/iflytop/handacid/app/service/DeviceInitService.java b/src/main/java/com/iflytop/handacid/app/service/DeviceInitService.java index 9a93d24..9f23c48 100644 --- a/src/main/java/com/iflytop/handacid/app/service/DeviceInitService.java +++ b/src/main/java/com/iflytop/handacid/app/service/DeviceInitService.java @@ -8,6 +8,7 @@ import com.iflytop.handacid.app.core.command.DeviceCommand; import com.iflytop.handacid.app.core.command.DeviceCommandGenerator; import com.iflytop.handacid.app.core.state.ChannelState; import com.iflytop.handacid.app.core.state.DeviceState; +import com.iflytop.handacid.app.core.state.RemoteControlState; import com.iflytop.handacid.common.model.bo.DeviceInitializationData; import com.iflytop.handacid.common.model.entity.Channel; import com.iflytop.handacid.common.model.entity.DeviceParamConfig; @@ -38,6 +39,7 @@ public class DeviceInitService { private boolean isLink = false; private final DeviceState deviceState; private final ObjectProvider channelStateObjectProvider; + private final ObjectProvider remoteControlStateObjectProvider; private final ChannelService channelService; private final DeviceCommandService deviceCommandService; private final DeviceParamConfigService deviceParamConfigService; @@ -52,10 +54,9 @@ public class DeviceInitService { new Thread(() -> { try { log.info("初始化开始"); - initDeviceState(); initDeviceSetData();//初始化设备参数 initEnable();//使能 - // initDeviceState();//初始化设备状态 + initDeviceState(); log.info("初始化完毕"); } catch (Exception e) { throw new RuntimeException(e); @@ -99,8 +100,8 @@ public class DeviceInitService { ChannelState channelState = channelStateObjectProvider.getObject(code, solution.getId(), solution.getName(), channel.getConcentration(), channel.getTargetVolume(), channel.getReceivedVolume(), channel.getCurrentVolume()); deviceState.getChannelStateMap().put(code, channelState); } - SolutionAddMode mode = SolutionAddMode.valueOf(systemConfigService.getValueByKey(SystemConfigKey.SOLUTION_ADD_MODE)); - deviceState.setMode(mode); + deviceState.setMode(SolutionAddMode.valueOf(systemConfigService.getValueByKey(SystemConfigKey.SOLUTION_ADD_MODE))); + deviceState.setRemoteControlState(remoteControlStateObjectProvider.getObject()); log.info("初始化 initDeviceState完毕"); } diff --git a/src/main/java/com/iflytop/handacid/hardware/comm/can/A8kCanBusConnection.java b/src/main/java/com/iflytop/handacid/hardware/comm/can/A8kCanBusConnection.java index c061fcd..3a4208d 100644 --- a/src/main/java/com/iflytop/handacid/hardware/comm/can/A8kCanBusConnection.java +++ b/src/main/java/com/iflytop/handacid/hardware/comm/can/A8kCanBusConnection.java @@ -9,6 +9,7 @@ import com.iflytop.handacid.hardware.type.CmdId; import com.iflytop.handacid.hardware.type.MId; import com.iflytop.handacid.hardware.type.ModuleStatus; import com.iflytop.handacid.hardware.type.appevent.A8kCanBusOnConnectEvent; +import com.iflytop.handacid.hardware.type.appevent.A8kHardwareReport; import com.iflytop.handacid.hardware.type.error.A8kEcode; import com.iflytop.handacid.hardware.type.error.AEHardwareError; import com.iflytop.handacid.hardware.utils.OS; @@ -38,8 +39,8 @@ public class A8kCanBusConnection extends WebSocketClient { @Resource AppEventBusService eventBus; - String datachurl = null; - String cmdchurl = null; + String datachurl = null; + String cmdchurl = null; Boolean firstCall = true; @Value("${device.enableCanBus}") @@ -48,12 +49,12 @@ public class A8kCanBusConnection extends WebSocketClient { static class ProcessContext { BlockingQueue receiptQueue = new LinkedBlockingQueue<>(); // - A8kPacket cmdPacket; - Map txcmdcache = new HashMap<>(); + A8kPacket cmdPacket; + Map txcmdcache = new HashMap<>(); public A8kPacket getReceipt(int overtime) { - long end = System.currentTimeMillis() + overtime; + long end = System.currentTimeMillis() + overtime; A8kPacket packet = null; while (System.currentTimeMillis() < end) { try { @@ -96,7 +97,7 @@ public class A8kCanBusConnection extends WebSocketClient { synchronized void storageTxLastCmd(A8kPacket pack) { - MId mid = MId.valueOf(pack.getModuleId()); + MId mid = MId.valueOf(pack.getModuleId()); CmdId cmdId = CmdId.valueOf(pack.getCmdId()); if (cmdId != null && cmdId.isActionCmd()) txcmdcache.put(mid, cmdId); @@ -108,8 +109,8 @@ public class A8kCanBusConnection extends WebSocketClient { } - ProcessContext context = new ProcessContext(); - int packetIndex = 0;//发送包的packetIndex + ProcessContext context = new ProcessContext(); + int packetIndex = 0;//发送包的packetIndex public A8kCanBusConnection(String cmdchurl, String datachurl) { @@ -117,26 +118,30 @@ public class A8kCanBusConnection extends WebSocketClient { log.info("new A8kCanBusConnection: {} {}", cmdchurl, datachurl); this.datachurl = datachurl; - this.cmdchurl = cmdchurl; - packetIndex = 0; + this.cmdchurl = cmdchurl; + packetIndex = 0; } - @Override public void onOpen(ServerHandshake serverHandshake) { + @Override + public void onOpen(ServerHandshake serverHandshake) { log.info("a8k canbus connect sucess"); eventBus.pushEvent(new A8kCanBusOnConnectEvent()); } - @Override public void onMessage(String s) { + @Override + public void onMessage(String s) { log.trace("RX-RAW: {}", s); processCanRxMessage(s); } - @Override public void onClose(int i, String s, boolean b) { + @Override + public void onClose(int i, String s, boolean b) { log.warn("a8k canbus lost connection..."); } - @Override public void onError(Exception e) { + @Override + public void onError(Exception e) { log.info("a8k can-websocket-channel on error"); } @@ -293,7 +298,7 @@ public class A8kCanBusConnection extends WebSocketClient { } /** - * 处理接收到的消息 + * 处理接收到的消息 */ private void processCanRxMessage(String s) { byte[] rx = ByteArray.hexStringToBytes(s); @@ -321,11 +326,11 @@ public class A8kCanBusConnection extends WebSocketClient { if (packet.getPacketType() == A8kPacket.PACKET_TYPE_ACK || packet.getPacketType() == A8kPacket.PACKET_TYPE_ERROR_ACK) { - log.trace("RX-ACK |RAW:{}| {}", s, packet); + log.debug("RX-ACK |RAW:{}| {}", s, packet); context.pushReceipt(packet); } else if (packet.getPacketType() == A8kPacket.PACKET_TYPE_EVENT) { - log.trace("RX-REPORT |RAW:{}| {}", s, packet); -// eventBus.pushEvent(new A8kHardwareReport(packet)); + log.debug("RX-REPORT |RAW:{}| {}", s, packet); + eventBus.pushEvent(new A8kHardwareReport(packet)); } else { log.warn("RX-UNPROCESSABLE: |RAW:{}| {}", s, packet); } @@ -342,9 +347,9 @@ public class A8kCanBusConnection extends WebSocketClient { public HttpResponse callLocalCmd(String path) { // 创建一个HttpClient实例 - HttpClient httpClient = HttpClient.newHttpClient(); - HttpRequest httpRequest = HttpRequest.newBuilder().uri(URI.create(String.format("%s/%s", cmdchurl, path))).build(); - HttpResponse ret = null; + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest httpRequest = HttpRequest.newBuilder().uri(URI.create(String.format("%s/%s", cmdchurl, path))).build(); + HttpResponse ret = null; try { ret = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); } catch (Exception e) { @@ -355,9 +360,9 @@ public class A8kCanBusConnection extends WebSocketClient { } public static void main(String[] args) { - HttpClient httpClient = HttpClient.newHttpClient(); - HttpRequest httpRequest = HttpRequest.newBuilder().uri(URI.create("http://192.168.8.10:19004/zexcan/restart")).build(); - HttpResponse ret = null; + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest httpRequest = HttpRequest.newBuilder().uri(URI.create("http://192.168.8.10:19004/zexcan/restart")).build(); + HttpResponse ret = null; try { ret = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); log.info("ret: \t{}", ret.body()); diff --git a/src/main/java/com/iflytop/handacid/hardware/service/AppEventBusService.java b/src/main/java/com/iflytop/handacid/hardware/service/AppEventBusService.java index 3e0508e..bf2c23b 100644 --- a/src/main/java/com/iflytop/handacid/hardware/service/AppEventBusService.java +++ b/src/main/java/com/iflytop/handacid/hardware/service/AppEventBusService.java @@ -15,7 +15,6 @@ import java.util.concurrent.LinkedBlockingQueue; /** * 事件总线 - * */ @Component public class AppEventBusService implements ApplicationListener { @@ -27,9 +26,9 @@ public class AppEventBusService implements ApplicationListener eventQueue = new LinkedBlockingQueue<>(); - List listeners = new ArrayList<>(); + List listeners = new ArrayList<>(); @PostConstruct public void init() {