package com.ld.igds.protocol.modbus.command; import com.ld.igds.common.CoreDeviceService; import com.ld.igds.common.CoreSerService; import com.ld.igds.constant.BizType; import com.ld.igds.constant.Constant; import com.ld.igds.constant.DeviceStatus; import com.ld.igds.constant.DeviceType; import com.ld.igds.io.RemoteControlService; import com.ld.igds.io.constant.OrderRespEnum; import com.ld.igds.io.constant.ProtocolEnum; import com.ld.igds.io.request.DeviceAutoControlRequest; import com.ld.igds.io.request.DeviceControlRequest; import com.ld.igds.io.request.ExeDevice; import com.ld.igds.io.request.TempControlRequest; import com.ld.igds.io.response.DeviceControlResponse; import com.ld.igds.modbus.service.HModbusService; import com.ld.igds.models.Device; import com.ld.igds.models.DeviceModbus; import com.ld.igds.models.DeviceSer; import com.ld.igds.protocol.modbus.ModbusUtil2; import com.ld.igds.protocol.modbus.ServerUtil; import com.ld.igds.protocol.modbus.data.ModbusTcp; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; /** * 当前协议针对标准Modbus-TCP协议 * * @Desc: * @author: andy.jia * @update-time: 2023/8/11 10:07 */ @Slf4j @Component(RemoteControlServiceImpl.BEAN_ID) public class RemoteControlServiceImpl implements RemoteControlService { public static final String BEAN_ID = "modbus.remoteControlService"; @Resource private CoreDeviceService coreDeviceService; @Resource private HModbusService deviceModbusService; @Resource private AnalysisService analysisService; @Resource private CoreSerService coreSerService; @Override public String getProtocol() { return ProtocolEnum.TCP_MODBUS.getCode(); } @Override public DeviceControlResponse deviceControl(DeviceControlRequest request) { List deviceList = request.getDeviceList(); if (null == deviceList || deviceList.isEmpty()) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "没有需要执行的设备"); } try { DeviceModbus deviceModbus; ModbusTcp modbusTcp; ModbusTcp modbusTcpLink = null; String temp = Constant.YN_N; DeviceSer deviceSer; for (ExeDevice exeDevice : deviceList) { deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), exeDevice.getPassCode() + ""); if (null == deviceModbus) { log.error("当前设备---{}{},为获取到配置的MODBUS信息", exeDevice.getSerId(), exeDevice.getName()); continue; } modbusTcp = new ModbusTcp(deviceModbus); modbusTcp.setIp(request.getIp()); modbusTcp.setPort(request.getPort()); //若Modbus设备配置分机,则使用所配置分机的IP、端口 if (StringUtils.isNotEmpty(deviceModbus.getSerId())) { deviceSer = coreSerService.getCacheSer(request.getCompanyId(), deviceModbus.getSerId()); modbusTcp.setIp(deviceSer.getIp()); modbusTcp.setPort(deviceSer.getPort()); } modbusTcp.setBizCode(exeDevice.getPassCode() + ""); modbusTcp.setSerId(request.getSerId()); modbusTcp.setCompanyId(request.getCompanyId()); //根据设备目标目标状态,选择需要执行的通道 if (DeviceStatus.CLOSE.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getClose(); } if (DeviceStatus.OPEN.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getOpen(); } //环流风机-关 if (DeviceStatus.F_CLOSE.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getStop(); } //环流风机-开 if (DeviceStatus.F_OPEN.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getOpen(); } if (StringUtils.isBlank(exeDevice.getLink()) || "null".equals(exeDevice.getLink())) { //根据设备目标状态,调用MODBUS执行 modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, exeDevice.getTargetStatus()); continue; } deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), exeDevice.getLink()); if (null == deviceModbus) continue; modbusTcpLink = new ModbusTcp(deviceModbus); modbusTcpLink.setIp(request.getIp()); modbusTcpLink.setPort(request.getPort()); modbusTcpLink.setBizCode(exeDevice.getLink()); modbusTcpLink.setSerId(request.getSerId()); modbusTcpLink.setCompanyId(request.getCompanyId()); //若Modbus设备配置分机,则使用所配置分机的IP、端口 if (StringUtils.isNotEmpty(deviceModbus.getSerId())) { deviceSer = coreSerService.getCacheSer(request.getCompanyId(), deviceModbus.getSerId()); modbusTcpLink.setIp(deviceSer.getIp()); modbusTcpLink.setPort(deviceSer.getPort()); } //如果是开风机 if (DeviceStatus.F_OPEN.getCode().equals(exeDevice.getTargetStatus())) { //先开窗口 temp = modbusTcp.getDeviceModbus().getOpen(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, DeviceStatus.OPEN.getCode()); Thread.sleep(300); //再开风机 temp = modbusTcpLink.getDeviceModbus().getOpen(); modbusTcpLink.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcpLink, DeviceStatus.OPEN.getCode()); } //如果关风机 if (DeviceStatus.F_CLOSE.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcpLink.getDeviceModbus().getStop(); modbusTcpLink.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcpLink, DeviceStatus.CLOSE.getCode()); } //如果开窗 if (DeviceStatus.W_OPEN.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getOpen(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, exeDevice.getTargetStatus()); } //如果是关窗户 if (DeviceStatus.W_CLOSE.getCode().equals(exeDevice.getTargetStatus())) { //先关风机 temp = modbusTcpLink.getDeviceModbus().getStop(); modbusTcpLink.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcpLink, DeviceStatus.CLOSE.getCode()); Thread.sleep(300); //在关窗户 temp = modbusTcp.getDeviceModbus().getClose(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, DeviceStatus.CLOSE.getCode()); } } } catch (Exception e) { log.error("调用MODBUS-TCP执行异常:{}", e); return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "后台执行异常:" + e.getMessage()); } return new DeviceControlResponse(OrderRespEnum.ORDER_SUCCESS); } private void doWriteExe(ModbusTcp modbusTcp, String targetStatus) throws Exception { boolean exeResult = ModbusUtil2.writeCoilStatus(modbusTcp.getIp(), modbusTcp.getPort(), modbusTcp.getAddrExe(), true); if (exeResult) { //根据Modbus-TCP,将写过的值,恢复原来的值 ModbusUtil2.writeCoilStatus(modbusTcp.getIp(), modbusTcp.getPort(), modbusTcp.getAddrExe(), false); log.debug("--------写入值---{}-{}-{}", modbusTcp.getSerId(), modbusTcp.getBizCode(), targetStatus); ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), targetStatus); } } @Override public DeviceControlResponse closeAll(DeviceControlRequest request) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体不支持"); } @Override public DeviceControlResponse queryStatus(DeviceControlRequest request) { try { List list = coreDeviceService.getCacheDeviceBySerId(request.getCompanyId(), request.getSerId()); if (null == list || list.isEmpty()) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "未获取到设备列表信息"); } DeviceModbus deviceModbus; ModbusTcp modbusTcp; ModbusTcp modbusTcpLink; for (Device device : list) { deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), device.getPassCode() + ""); //空调设备单独查询 if(DeviceType.TYPE_05.getCode().equals(device.getType())){ deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), device.getPassCode() + "", BizType.TEMPCONTROL.getCode()); } if (null == deviceModbus) { log.error("当前设备---{}{},为获取到配置的MODBUS信息", device.getSerId(), device.getName()); continue; } if (Constant.YN_N.equals(deviceModbus.getOpen())) continue; modbusTcp = new ModbusTcp(deviceModbus); modbusTcp.setIp(request.getIp()); modbusTcp.setPort(request.getPort()); modbusTcp.setBizCode(device.getPassCode() + ""); modbusTcp.setSerId(device.getSerId()); modbusTcp.setCompanyId(device.getCompanyId()); //空调状态单独读取 if(DeviceType.TYPE_05.getCode().equals(device.getType())){ doReadTempStatus(modbusTcp); continue; } doReadStatus(modbusTcp, false); if (StringUtils.isBlank(device.getLink()) || "null".equals(device.getLink())) continue; Thread.sleep(300); deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), device.getLink()); if (null == deviceModbus) continue; modbusTcpLink = new ModbusTcp(deviceModbus); modbusTcpLink.setIp(request.getIp()); modbusTcpLink.setPort(request.getPort()); modbusTcpLink.setSerId(device.getSerId()); modbusTcpLink.setBizCode(device.getLink()); modbusTcpLink.setCompanyId(device.getCompanyId()); modbusTcpLink.setAddrExe(ServerUtil.getAddrExe(modbusTcp.getDeviceModbus().getOpenEnd())); doReadStatus(modbusTcpLink, true); } } catch (Exception e) { log.error("调用MODBUS-TCP执行异常:{}", e); return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "后台执行异常:" + e.getLocalizedMessage()); } analysisService.analysisDevice(request, 3000); return new DeviceControlResponse(OrderRespEnum.ORDER_SUCCESS); } /** * 读取状态,同时读取开状态和关闭状态 * * @param modbusTcp * @param flag 是否是关联设备 * @throws Exception */ private void doReadStatus(ModbusTcp modbusTcp, Boolean flag) throws Exception { if (Constant.YN_N.equals(modbusTcp.getDeviceModbus().getOpen())) return; if (Constant.YN_N.equals(modbusTcp.getDeviceModbus().getOpenEnd())) return; int addrExe = ServerUtil.getAddrExe(modbusTcp.getDeviceModbus().getOpenEnd()); boolean result = ModbusUtil2.readInputStatus(modbusTcp.getIp(), modbusTcp.getPort(), addrExe); log.debug("---------读风窗风口开到位状态(或其他设备运行状态)------{}-{}-{}", modbusTcp.getBizCode(), addrExe, result); String statusOpen = DeviceStatus.OPEN.getCode(); String statusClose = DeviceStatus.CLOSE.getCode(); if(flag){ statusOpen = DeviceStatus.F_OPEN.getCode(); statusClose = DeviceStatus.F_CLOSE.getCode(); } if (result) { ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), statusOpen); }else { ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), statusClose); } if (Constant.YN_N.equals(modbusTcp.getDeviceModbus().getCloseEnd())) return; addrExe = ServerUtil.getAddrExe(modbusTcp.getDeviceModbus().getCloseEnd()); result = ModbusUtil2.readInputStatus(modbusTcp.getIp(), modbusTcp.getPort(), addrExe); log.debug("---------读风窗风口关到位状态------{}-{}-{}", modbusTcp.getBizCode(), addrExe, result); if (result) { ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), DeviceStatus.CLOSE.getCode()); }else { ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), DeviceStatus.OPEN.getCode()); } } /** * 读取空调设备状态 * * @param modbusTcp * @throws Exception */ private void doReadTempStatus(ModbusTcp modbusTcp) throws Exception { if (Constant.YN_N.equals(modbusTcp.getDeviceModbus().getOpenEnd())) return; int addrExe = ServerUtil.getAddrExe(modbusTcp.getDeviceModbus().getOpenEnd()); Number number = ModbusUtil2.readHoldingRegister(modbusTcp.getIp(), modbusTcp.getPort(), addrExe); log.debug("---------读空调运行状态------{}-{}-{}", modbusTcp.getBizCode(), addrExe, number); int num = number.intValue(); if(num == 1){ ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), DeviceStatus.OPEN.getCode()); } if(num == 2){ ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getBizCode(), DeviceStatus.CLOSE.getCode()); } } @Override public DeviceControlResponse tempControl(TempControlRequest request) { ExeDevice exeDevice = request.getExeDevice(); if (null == exeDevice) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "没有需要执行的设备"); } try { ModbusTcp modbusTcp; String temp = Constant.YN_N; DeviceSer deviceSer; DeviceModbus deviceModbus = deviceModbusService.getCacheDeviceModbus(request.getCompanyId(), exeDevice.getPassCode() + "", BizType.TEMPCONTROL.getCode()); if (null == deviceModbus) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "未获取到配置的MODBUS信息"); } modbusTcp = new ModbusTcp(deviceModbus); modbusTcp.setIp(request.getIp()); modbusTcp.setPort(request.getPort()); //若Modbus设备配置分机,则使用所配置分机的IP、端口 if (StringUtils.isNotEmpty(deviceModbus.getSerId())) { deviceSer = coreSerService.getCacheSer(request.getCompanyId(), deviceModbus.getSerId()); modbusTcp.setIp(deviceSer.getIp()); modbusTcp.setPort(deviceSer.getPort()); } modbusTcp.setBizCode(exeDevice.getPassCode() + ""); modbusTcp.setSerId(request.getSerId()); modbusTcp.setCompanyId(request.getCompanyId()); //开空调时,需要发送两条命令,一条设置温度命令,一条开启命令 if (DeviceStatus.OPEN.getCode().equals(exeDevice.getTargetStatus())) { //设置温度 temp = modbusTcp.getDeviceModbus().getClose(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, exeDevice.getTargetStatus()); boolean exeResult = ModbusUtil2.writeRegister(modbusTcp.getIp(), modbusTcp.getPort(), modbusTcp.getAddrExe(), Integer.valueOf(request.getTargetTemp())); //开空调 if (exeResult) { temp = modbusTcp.getDeviceModbus().getOpen(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, exeDevice.getTargetStatus()); } } //关空调时,只发送一条关闭命令 if (DeviceStatus.CLOSE.getCode().equals(exeDevice.getTargetStatus())) { temp = modbusTcp.getDeviceModbus().getStop(); modbusTcp.setAddrExe(ServerUtil.getAddrExe(temp)); doWriteExe(modbusTcp, exeDevice.getTargetStatus()); } } catch (Exception e) { log.error("调用MODBUS-TCP执行异常:{}", e); return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "后台执行异常:" + e.getMessage()); } return new DeviceControlResponse(OrderRespEnum.ORDER_SUCCESS); } @Override public DeviceControlResponse airAutoControl(DeviceAutoControlRequest request) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体未接入当前控制"); } @Override public DeviceControlResponse n2AutoControl(DeviceAutoControlRequest request) { return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体未接入当前控制"); } }