package com.sandu.ximon.admin.service; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.aliyuncs.iot.model.v20180120.BatchGetDeviceStateResponse; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.github.pagehelper.PageHelper; import com.sandu.common.domain.CommonPage; import com.sandu.common.execption.BusinessException; import com.sandu.common.redis.RedisService; import com.sandu.common.service.impl.BaseServiceImpl; import com.sandu.ximon.admin.manager.iot.frame.A7Frame; import com.sandu.ximon.admin.manager.iot.frame.FrameBuilder; import com.sandu.ximon.admin.manager.iot.frame.IRequestFrame; import com.sandu.ximon.admin.manager.iot.frame.inner.report.A7PlcOperationReportInnerFrame; import com.sandu.ximon.admin.manager.iot.frame.inner.request.*; import com.sandu.ximon.admin.manager.iot.frame.inner.response.*; import com.sandu.ximon.admin.manager.iot.rrpc.dto.CommonFrame; import com.sandu.ximon.admin.manager.iot.rrpc.dto.WrapResponseCommonFrame; import com.sandu.ximon.admin.manager.iot.rrpc.enums.A2OrderEnum; import com.sandu.ximon.admin.manager.iot.rrpc.enums.A5OrderEnum; import com.sandu.ximon.admin.manager.iot.rrpc.enums.A7OrderEnum; import com.sandu.ximon.admin.manager.iot.rrpc.mainboard.MainBoardInvokeSyncService; import com.sandu.ximon.admin.param.PlcControlParam; import com.sandu.ximon.admin.param.PlcRemarkParam; import com.sandu.ximon.admin.redis.LightKey; import com.sandu.ximon.admin.security.SecurityUtils; import com.sandu.ximon.admin.utils.RedisUtils; import com.sandu.ximon.admin.utils.StoreOperationRecordsUtils; import com.sandu.ximon.dao.bo.PlcBo; import com.sandu.ximon.dao.domain.*; import com.sandu.ximon.dao.enums.DeviceRespStatusEnums; import com.sandu.ximon.dao.enums.OrderByEnums; import com.sandu.ximon.dao.mapper.PlcMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /** * plc路灯表(Plc)表服务接口 * * @author van * @since 2022-12-15 14:45:27 */ @Service @Slf4j @AllArgsConstructor public class PlcService extends BaseServiceImpl { private final RedisService redisService; private final PlcReportDataService plcReportDataService; private final PoleBindingService bindingService; private final PoleService poleService; private final RedisUtils redisUtils; public List listPlc(int pageNo, int pageSize, String keyword, Integer order, Integer seq) { Long clientId = SecurityUtils.getClientId(); //排序字段 String orderByResult = "plc_id"; //正序、倒叙 String orderBySeq = OrderByEnums.ASC.getCode(); if (order != null) { switch (order) { case 1: orderByResult = OrderByEnums.LIGHT_POLE_NAME.getCode(); break; case 2: orderByResult = OrderByEnums.LIGHT_UPDATE_TIME.getCode(); break; case 3: orderByResult = OrderByEnums.LIGHT_CREATE_TIME.getCode(); break; default: } } if (seq != null) { switch (seq) { case 1: orderBySeq = OrderByEnums.ASC.getCode(); break; case 2: orderBySeq = OrderByEnums.DESC.getCode(); break; default: break; } } //排序方式 String orderBy = orderByResult + " " + orderBySeq; PageHelper.startPage(pageNo, pageSize, orderBy); List listPlc = baseMapper.listPlc(clientId, keyword); // 获取最近的上报时间 List deviceCodeList = listPlc.stream().map(Plc::getDeviceCode).collect(Collectors.toList()); //拆分list List> split = CollectionUtil.split(deviceCodeList, 100); List deviceStatuses = null; for (List splist : split) { deviceStatuses = MainBoardInvokeSyncService.getInstance().batchGetDeviceState(splist); if (deviceStatuses != null) { for (PlcBo plcBo : listPlc ) { for (BatchGetDeviceStateResponse.DeviceStatus deviceStatus : deviceStatuses) { if (plcBo.getDeviceCode() != null && plcBo.getDeviceCode().equals(deviceStatus.getDeviceName())) { if ("ONLINE".equals(deviceStatus.getStatus())) { plcBo.setOnlineStatus(0); } else if ("OFFLINE".equals(deviceStatus.getStatus())) { plcBo.setOnlineStatus(1); } else { plcBo.setOnlineStatus(2); } } } } } } if (CollectionUtil.isNotEmpty(deviceCodeList)) { List reportDataList = plcReportDataService.getNewestReportByDeviceCode(deviceCodeList); for (PlcBo plcBo : listPlc) { deviceCodeList.forEach(code -> { PoleBinding bind = bindingService.getPoleIdByMac(code); if (bind != null && plcBo.getDeviceCode().equals(bind.getDeviceCode())) { Long poleId = bind.getPoleId(); Pole pole = poleService.getById(poleId); plcBo.setPoleId(pole.getId()); plcBo.setPoleCode(pole.getDeviceCode()); plcBo.setPoleName(pole.getPoleName()); } }); for (PlcReportData plcReportData : reportDataList) { if (StrUtil.equals(plcBo.getDeviceCode(), plcReportData.getDeviceCode())) { plcBo.setReportTime(plcReportData.getCreateTime1()); break; } } } } return listPlc; } /** * 获取单个plc信息 * * @param deviceCode 设备码 * @return */ public Plc getPlc(String deviceCode) { Plc one = getOne(Wrappers.lambdaQuery().eq(Plc::getDeviceCode, deviceCode)); if (one == null) { return null; } else { Object o = redisService.get(LightKey.REPORT_MAC.key(deviceCode)); if (o != null) { one.setOnlineStatus(1); } else { one.setOnlineStatus(0); } return one; } } public boolean addRemark(PlcRemarkParam param) { Plc plc = getById(param.getPlcId()); if (plc == null) { throw new BusinessException("找不到PLC"); } Plc update = new Plc(); update.setPlcId(param.getPlcId()); update.setPlcRemark(param.getPlcRemark()); return updateById(update); } /** * PLC亮度控制 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> controlBrightness(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcBrightnessReqInnerFrame plcControlFrame = new A7PlcBrightnessReqInnerFrame(param.getBrightness(), param.getPlcAddress()); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcBrightnessRespInnerFrame.class); //存储控制帧指令 StoreOperationRecordsUtils.storeInnerFrameData(param.getDeviceCode(), "PLC帧-亮度开关控制", a7Frame, frame); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String responseStatus = frame.getResponseInnerFrame().getResponseStatus(); int status = HexUtil.hexToInt(responseStatus); map.put("status", status); resultList.add(map); // 更新亮度成功,修改到数据库 if (DeviceRespStatusEnums.SUCCESS.getCode().equals(status)) { Plc plc = new Plc(); if (param.getPlcAddress().equals("0001")){ plc.setPlcLight1(param.getBrightness()); } else if (param.getPlcAddress().equals("0002")){ plc.setPlcLight2(param.getBrightness()); } else if (param.getPlcAddress().equals("0003")){ plc.setPlcLight3(param.getBrightness()); } else if (param.getPlcAddress().equals("FFFF")){ plc.setPlcLight1(param.getBrightness()); plc.setPlcLight2(param.getBrightness()); plc.setPlcLight3(param.getBrightness()); } update(plc, Wrappers.lambdaUpdate(Plc.class).eq(Plc::getDeviceCode, param.getDeviceCode())); } } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } /** * 服务端批量控灯日志记录开始 */ String content = "{PLC控灯请求:" + paramList.toString() + ", PLC控灯结果:" + resultList.toString() + "}"; List codeList = new ArrayList<>(); for (PlcControlParam bean : paramList) { codeList.add(bean.getDeviceCode()); } StoreOperationRecordsUtils.storeOperationData(codeList, null, "服务端批量PLC控灯", content); /** * 服务端批量控灯日志记录结束 */ return resultList; } /** * PLC设置心跳时间 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> setHeartBeatTime(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcSettingHeartBeatTimeReqInnerFrame plcControlFrame = new A7PlcSettingHeartBeatTimeReqInnerFrame(param.getHeartBeatTime()); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcBrightnessRespInnerFrame.class); //存储控制帧指令 StoreOperationRecordsUtils.storeInnerFrameData(param.getDeviceCode(), "PLC帧-设置PLC心跳包间隔时间", a7Frame, frame); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String responseStatus = frame.getResponseInnerFrame().getResponseStatus(); int status = HexUtil.hexToInt(responseStatus); map.put("status", status); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } /** * 服务端批量控灯日志记录开始 */ String content = "{PLC设置心跳时间:" + paramList.toString() + ", PLC设置心跳时间结果:" + resultList.toString() + "}"; List codeList = new ArrayList<>(); for (PlcControlParam bean : paramList) { codeList.add(bean.getDeviceCode()); } StoreOperationRecordsUtils.storeOperationData(codeList, null, "PLC设置心跳时间", content); /** * 服务端批量控灯日志记录结束 */ return resultList; } /** * PLC 查询心跳时间 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> queryHeartBeatTime(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcQueryHeartBeatTimeReqInnerFrame plcControlFrame = new A7PlcQueryHeartBeatTimeReqInnerFrame(); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcQueryHeartBeatTimeRespInnerFrame.class); //存储控制帧指令 StoreOperationRecordsUtils.storeInnerFrameData(param.getDeviceCode(), "PLC帧-设置PLC心跳包间隔时间", a7Frame, frame); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String time = frame.getResponseInnerFrame().getTime(); map.put("status", 0); map.put("time",time); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } /** * 服务端批量控灯日志记录开始 */ String content = "{PLC查询心跳时间:" + paramList.toString() + ", PLC查询心跳时间结果:" + resultList.toString() + "}"; List codeList = new ArrayList<>(); for (PlcControlParam bean : paramList) { codeList.add(bean.getDeviceCode()); } StoreOperationRecordsUtils.storeOperationData(codeList, null, "PLC查询心跳时间", content); /** * 服务端批量控灯日志记录结束 */ return resultList; } /** * PLC 查询心跳包 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> queryHeartBeatData(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcQueryHeartBeatDataReqInnerFrame plcControlFrame = new A7PlcQueryHeartBeatDataReqInnerFrame(); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcQueryHeartBeatDataRespInnerFrame.class); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String data = JSON.toJSONString(frame.getResponseInnerFrame().getHeartbeatReportInnerFrame().getHeartBeatDataPackage()); map.put("status", 0); map.put("heartBeatData",data); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } return resultList; } /** * PLC 查询版本 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> queryVersion(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcQueryVersionReqInnerFrame plcControlFrame = new A7PlcQueryVersionReqInnerFrame(); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcQueryVersionRespInnerFrame.class); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } map.put("status", 0); map.put("hardwareVersion",frame.getResponseInnerFrame().getHardwareVersionDouble()); map.put("softwareVersion",frame.getResponseInnerFrame().getSoftwareVersionDouble()); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } return resultList; } /** * PLC重启 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> reboot(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcRebootReqInnerFrame plcControlFrame = new A7PlcRebootReqInnerFrame(); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcBrightnessRespInnerFrame.class); //存储控制帧指令 StoreOperationRecordsUtils.storeInnerFrameData(param.getDeviceCode(), "PLC帧-设置PLC重启", a7Frame, frame); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String responseStatus = frame.getResponseInnerFrame().getResponseStatus(); int status = HexUtil.hexToInt(responseStatus); map.put("status", status); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } /** * 服务端批量控灯日志记录开始 */ String content = "{PLC重启:" + paramList.toString() + ", PLC重启:" + resultList.toString() + "}"; List codeList = new ArrayList<>(); for (PlcControlParam bean : paramList) { codeList.add(bean.getDeviceCode()); } StoreOperationRecordsUtils.storeOperationData(codeList, null, "PLC重启", content); /** * 服务端批量控灯日志记录结束 */ return resultList; } /** * PLC恢复出厂设置 * * @return com.sandu.ximon.dao.enums.DeviceRespStatusEnums */ public List> reset(List paramList) { if (CollectionUtil.isEmpty(paramList)) { throw new BusinessException("参数不能为空"); } List> resultList = new ArrayList<>(); for (PlcControlParam param : paramList) { A7PlcResetReqInnerFrame plcControlFrame = new A7PlcResetReqInnerFrame(); A7Frame a7Frame = new A7Frame(A7OrderEnum.REQUEST_PLC_DATA.getCode(), plcControlFrame); Map map = new HashMap<>(); try { map.put("deviceCode", param.getDeviceCode()); WrapResponseCommonFrame frame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), a7Frame, A7PlcResetRespInnerFrame.class); //存储控制帧指令 StoreOperationRecordsUtils.storeInnerFrameData(param.getDeviceCode(), "PLC帧-设置PLC恢复出厂设置", a7Frame, frame); if (frame == null) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } String responseStatus = frame.getResponseInnerFrame().getResponseStatus(); int status = HexUtil.hexToInt(responseStatus); IRequestFrame iRequestFrame = FrameBuilder.builderA2().innerFrame(new EmptyRequestInnerFrame()).orderType(A2OrderEnum.REQUEST_MAIN_BOARD_RESET.getCode()).build(); CommonFrame rebootFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(param.getDeviceCode(), iRequestFrame); boolean b = false; if (!"00".equals(rebootFrame.getPayload())) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); continue; } map.put("status", status); resultList.add(map); } catch (BusinessException e) { map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode()); resultList.add(map); } } /** * 服务端批量控灯日志记录开始 */ String content = "{PLC恢复出厂设置:" + paramList.toString() + ", PLC恢复出厂设置:" + resultList.toString() + "}"; List codeList = new ArrayList<>(); for (PlcControlParam bean : paramList) { codeList.add(bean.getDeviceCode()); } StoreOperationRecordsUtils.storeOperationData(codeList, null, "PLC恢复出厂设置", content); /** * 服务端批量控灯日志记录结束 */ return resultList; } /** * 获取用户所有的设备码 */ public CommonPage listDeviceCode(int pageNo, int pageSize, String keyword, String deviceCode, String orderBy) { List list; if (SecurityUtils.getClientId() != null) { PageHelper.startPage(pageNo, pageSize); list = baseMapper.listCode(SecurityUtils.getUserId(), keyword, deviceCode); } else { PageHelper.startPage(pageNo, pageSize, orderBy); list = baseMapper.listCode(null, keyword, deviceCode); } return CommonPage.restPage(list); } public void timeSynchronizationInitiative(String deviceCode, String destinationAddress) { Plc plc = getPlc(deviceCode); if (plc == null) { log.error("PLC主动同步时间请求异常,PLC信息不存在!"); return; } SetCalendar(plc.getPlcId(), destinationAddress); } /** * 设置日历(同心跳包中的6字节日期时间) * * @return */ public String SetCalendar(Long plcId, String address) { Calendar cal = Calendar.getInstance(); //获取当前时间 int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH); int day = cal.get(Calendar.DATE); int hour = cal.get(Calendar.HOUR_OF_DAY); int min = cal.get(Calendar.MINUTE); int sec = cal.get(Calendar.SECOND); Plc one = getById(plcId); if (one == null) { System.out.println("plc不存在!"); } A7PlcSetCalendarReqInnerFrame setCalendarReqInnerFrame = new A7PlcSetCalendarReqInnerFrame(address, year % 100, month + 1, day, hour, min, sec); A7Frame a7Frame = new A7Frame(A5OrderEnum.REQUEST_LIGHT_DATA.getCode(), setCalendarReqInnerFrame); System.out.println(a7Frame + " -----A7Frame"); CommonFrame commonFrame; commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(one.getDeviceCode(), a7Frame); StoreOperationRecordsUtils.storeInnerFrameData(one.getDeviceCode(), "PLC帧-设置日历", a7Frame, commonFrame); System.out.println(commonFrame + " -----commonFrame"); A7PlcOperationReportInnerFrame operationReportInnerFrame = new A7PlcOperationReportInnerFrame().transformFrame(commonFrame.getPayload()); if (operationReportInnerFrame.isValidate()) { return operationReportInnerFrame.getState(); } else { throw new BusinessException("数据校验错误,请重新请求"); } } }