From 4805a0c0a74c0bcf8e92317f2f0266b645e4b864 Mon Sep 17 00:00:00 2001 From: mengff <1198151809@qq.com> Date: Wed, 17 Jan 2024 17:07:53 +0800 Subject: [PATCH 1/3] =?UTF-8?q?--=E6=A3=80=E6=B5=8B=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/common/constant/Constants.java | 2 +- .../zc/business/controller/DeviceStatus.java | 181 ++++++++++++++++ .../business/controller/StatusController.java | 147 +++++++++++++ .../java/com/zc/business/domain/Device.java | 65 ++++++ .../java/com/zc/business/domain/Status.java | 205 ++++++++++++++++++ .../com/zc/business/mapper/DeviceMapper.java | 16 ++ .../com/zc/business/mapper/StatusMapper.java | 21 ++ .../business/service/impl/DeviceService.java | 23 ++ .../service/impl/ExcelExportService.java | 192 ++++++++++++++++ .../business/service/impl/StatusService.java | 33 +++ .../mapper/business/DeviceMapper.xml | 16 ++ .../mapper/business/StatusMapper.xml | 94 ++++++++ 12 files changed, 994 insertions(+), 1 deletion(-) create mode 100644 zc-business/src/main/java/com/zc/business/controller/DeviceStatus.java create mode 100644 zc-business/src/main/java/com/zc/business/controller/StatusController.java create mode 100644 zc-business/src/main/java/com/zc/business/domain/Device.java create mode 100644 zc-business/src/main/java/com/zc/business/domain/Status.java create mode 100644 zc-business/src/main/java/com/zc/business/mapper/DeviceMapper.java create mode 100644 zc-business/src/main/java/com/zc/business/mapper/StatusMapper.java create mode 100644 zc-business/src/main/java/com/zc/business/service/impl/DeviceService.java create mode 100644 zc-business/src/main/java/com/zc/business/service/impl/ExcelExportService.java create mode 100644 zc-business/src/main/java/com/zc/business/service/impl/StatusService.java create mode 100644 zc-business/src/main/resources/mapper/business/DeviceMapper.xml create mode 100644 zc-business/src/main/resources/mapper/business/StatusMapper.xml diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index 6e5c8940..8dedcb62 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -157,7 +157,7 @@ public class Constants /** * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) */ - public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; + public static final String[] JOB_WHITELIST_STR = { "com.ruoyi","com.zc" }; /** * 定时任务违规的字符 diff --git a/zc-business/src/main/java/com/zc/business/controller/DeviceStatus.java b/zc-business/src/main/java/com/zc/business/controller/DeviceStatus.java new file mode 100644 index 00000000..31db1c3c --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/controller/DeviceStatus.java @@ -0,0 +1,181 @@ +package com.zc.business.controller; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.zc.business.service.impl.DeviceService; +import com.zc.business.service.impl.ExcelExportService; +import com.zc.business.service.impl.StatusService; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; +import com.zc.business.domain.Status; +import com.zc.business.domain.Device; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +@Component +@EnableScheduling +public class DeviceStatus { + @Autowired + private DeviceService deviceService; + + @Autowired + private StatusService statusService; + + @Autowired + private ExcelExportService excelExportService; + + + //每天凌晨0点到晚上23点整点测试设备状态 + // @Scheduled(cron = "0 0 0-23 * * ?") + // @Scheduled(cron = "0 0 1,5,7,8,11,14,17,19,21,23") + public void deviceStatus() { + DeviceService deviceService= SpringUtils.getBean(DeviceService.class); + StatusService statusService= SpringUtils.getBean(StatusService.class); + ExecutorService executor = Executors.newFixedThreadPool(100); + List deviceList = deviceService.SelectList(); + + List> futures = new ArrayList<>(); + + for (Device device : deviceList) { + Callable task = () -> { + try { + Status status = new Status(); + InetAddress address = InetAddress.getByName(device.getDeviceIp()); + String lostRate = getPingPacketLossRate(device.getDeviceIp()); + boolean reachable = address.isReachable(5000); // Timeout: 5 seconds + + status.setDeviceNo(device.getDeviceNo()); + status.setDeviceName(device.getDeviceName()); + status.setDeviceIp(device.getDeviceIp()); + LocalDateTime localDateTime = LocalDateTime.now(); + status.setTime(localDateTime); + status.setLostRate(lostRate); + + if (reachable) { + status.setDeviceStatus(1); + status.setSuccessRate("100.00%"); + } else { + status.setDeviceStatus(0); + status.setSuccessRate("0.00%"); + } + + statusService.Add(status); + } catch (IOException e) { + System.out.println("Error pinging " + device.getDeviceIp() + ": " + e.getMessage()); + } + + return null; + }; + + futures.add(executor.submit(task)); + } + + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + executor.shutdown(); + } + + + /** + * 计算丢包率 + */ + public String getPingPacketLossRate(String ipAddress) { + try { + // Execute the ping command + Process process = Runtime.getRuntime().exec("ping -c 4 " + ipAddress); // Sending 4 ICMP Echo Request packets + + // Read the output of the command + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + int packetsSent = 0; + int packetsLost = 0; + + while ((line = reader.readLine()) != null) { + // Check for lines containing packet loss information + if (line.contains("packets transmitted")) { + // Extract the number of packets sent and lost + String[] stats = line.split(", "); + packetsSent = Integer.parseInt(stats[0].split(" ")[0]); + packetsLost = Integer.parseInt(stats[0].split(" ")[0])-Integer.parseInt(stats[1].split(" ")[0]); + } + } + + // Calculate and return the packet loss rate + if (packetsSent > 0) { + return String.format("%.2f%%", (double) packetsLost / packetsSent * 100); + } else { + return "0.00%"; // No packets sent + } + } catch (IOException e) { + e.printStackTrace(); + return "-1.00%"; // Error occurred + } + } + + + /** + * 成功率和丢包率按小时分组 + * 每天17点 23点 30分导出excel表 + */ + + // @Scheduled(cron = "0 30 17,23 * * ?") + public void calculateSuccessRate() { + StatusService statusService= SpringUtils.getBean(StatusService.class); + ExcelExportService excelExportService= SpringUtils.getBean(ExcelExportService.class); + + LocalDateTime todayStart = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS); + LocalDateTime currentTime = LocalDateTime.now(); + + + Status status = new Status(); + status.setStartTime(todayStart); + status.setTime(currentTime); + List listStatus = statusService.list(status); + //根据时间分组 + Map> map = listStatus.stream() + .collect(Collectors.groupingBy(Status -> Status.getTime().getHour())); + //根据类型分组 + Map> maps = listStatus.stream().filter(iteam->iteam.getType()!=null).collect(Collectors.groupingBy(Status::getType)); + + String filePath=CreateNamedExcel(); + excelExportService.exportDataToExcel(map,maps,filePath); + } + + + public String CreateNamedExcel() { + LocalDateTime dateTime = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String formattedDateTime = dateTime.format(formatter); + //修改成服务器地址 + String filePath = "/Users/mengfanfeng/Downloads/excel/"+formattedDateTime+"--deviceStatus.xlsx"; + try (Workbook workbook = new XSSFWorkbook()) { + FileOutputStream fileOut = new FileOutputStream(filePath); + workbook.write(fileOut); + System.out.println("Empty named Excel created successfully."); + } catch (IOException e) { + e.printStackTrace(); + } + return filePath; + } + +} + diff --git a/zc-business/src/main/java/com/zc/business/controller/StatusController.java b/zc-business/src/main/java/com/zc/business/controller/StatusController.java new file mode 100644 index 00000000..84029a24 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/controller/StatusController.java @@ -0,0 +1,147 @@ +package com.zc.business.controller; +import com.ruoyi.common.core.domain.AjaxResult; +import com.zc.business.domain.Status; +import com.zc.business.service.impl.StatusService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; +@Api("设备状态") +@RestController +@RequestMapping("/system/status") +public class StatusController { + + @Autowired + private StatusService statusService; + + //设备列表 + @ApiOperation("设备状态柱状按时间和类型") + @GetMapping ("/tablist") + public AjaxResult getTabList(Status status) + { + LocalDateTime todayStart = status.getStartTime().truncatedTo(ChronoUnit.DAYS); + LocalDateTime currentTime = status.getTime().truncatedTo(ChronoUnit.DAYS).plusDays(1); + status.setStartTime(todayStart); + status.setTime(currentTime); + List listStatus = statusService.list(status); + return AjaxResult.success(listStatus); + } + + //按时间划分设备柱状图 + @ApiOperation("设备状态列表按时间和类型") + @GetMapping ("/list") + public AjaxResult getStatusList(Status status) + { + LocalDateTime todayStart = status.getStartTime().truncatedTo(ChronoUnit.DAYS); + LocalDateTime currentTime = status.getTime().truncatedTo(ChronoUnit.DAYS).plusDays(1); + status.setStartTime(todayStart); + status.setTime(currentTime); + String type=status.getType(); + List listStatus = statusService.list(status); + List listStatu=listStatus.stream().filter(iteam ->iteam.getType()!=null && iteam.getType().equals(type)).collect(Collectors.toList()); + //根据时间分组 + Map> map = listStatu.stream() + .collect(Collectors.groupingBy(Status -> (Status.getTime().getYear()+"-"+Status.getTime().getMonthValue()+"-"+Status.getTime().getDayOfYear()))); + //根据类型分组 + // Map> maps = listStatu.stream().filter(iteam->iteam.getType()!=null).collect(Collectors.groupingBy(Status::getType)); + //生成有序map + Map> mapTime = new TreeMap<>(map); + Map mapSort=new TreeMap<>(); + for (Map.Entry> entry : mapTime.entrySet()) { + List groupItems = entry.getValue(); + long count = groupItems.stream().filter(iteam -> iteam.getDeviceStatus() == 1).count(); + String onlineRate=String.format("%.2f%%", (double) count / groupItems.size() * 100); + mapSort.put(entry.getKey(),onlineRate); + } + // Map> mapStatus = new TreeMap<>(maps); + return AjaxResult.success(mapSort); + } + + //按类型划分设备 + @ApiOperation("设备状态列表按类型") + @GetMapping ("/type") + public AjaxResult getTypeList() + { + HashMap itemTypeMap = new HashMap<>(); + itemTypeMap.put("1", "高清网络枪型固定摄像机"); + itemTypeMap.put("2", "高清网络球形摄像机"); + itemTypeMap.put("3", "桥下高清网络球形摄像机"); + itemTypeMap.put("4", "360°全景摄像机"); + itemTypeMap.put("5", "180°全景摄像机"); + itemTypeMap.put("6", "门架式可变信息标志"); + itemTypeMap.put("7", "雨棚可变信息标志"); + itemTypeMap.put("8", "站前悬臂式可变信息标志"); + itemTypeMap.put("9", "气象检测器"); + itemTypeMap.put("10", "路段语音广播系统"); + itemTypeMap.put("11", "护栏碰撞预警系统"); + itemTypeMap.put("12", "毫米波雷达"); + itemTypeMap.put("13", "合流区预警系统"); + itemTypeMap.put("14", "激光疲劳唤醒"); + itemTypeMap.put("15", "一类交通量调查站"); + itemTypeMap.put("16", "智能行车诱导系统"); + itemTypeMap.put("17", "智能设备箱"); + LocalDateTime todayStart = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS); + LocalDateTime currentTime = LocalDateTime.now(); + Status status = new Status(); + status.setStartTime(todayStart); + status.setTime(currentTime); + List listStatus = statusService.list(status); + //根据时间分组 + Map> map = listStatus.stream() + .collect(Collectors.groupingBy(Status -> Status.getTime().getHour())); + Map> ipMap = new TreeMap<>(map); + Integer lastKey = Collections.max(ipMap.keySet()); + List lastEntry = ipMap.get(lastKey); + Map> typeMap = lastEntry.stream().filter(iteam -> iteam.getType() != null).collect(Collectors.groupingBy(Status::getType)); + Map> subMap=new HashMap<>(); + + for (Map.Entry> entrys : typeMap.entrySet()) { + Map maps=new HashMap<>(); + List groupItems = entrys.getValue(); + double lostRate = groupItems.stream() + .mapToDouble(Status -> Double.parseDouble(Status.getLostRate().replace("%", ""))) // 去掉%,并转换为double + .average().getAsDouble(); + double sucessRate = groupItems.stream() + .mapToDouble(Status -> Double.parseDouble(Status.getSuccessRate().replace("%", ""))) // 去掉%,并转换为double + .average().getAsDouble(); + String failRate=String.format("%.2f", (100-sucessRate))+"%"; + //丢包率 + maps.put("lostRate",String.format("%.2f", lostRate)+"%"); + //在线率 + maps.put("sucessRate",String.format("%.2f", sucessRate)+"%"); + //离线率 + maps.put("failRate",failRate); + //总数 + maps.put("sum",String.valueOf(groupItems.size())); + subMap.put(itemTypeMap.get(entrys.getKey()),maps); + } + Map maps=new HashMap<>(); + double lostRate = lastEntry.stream() + .mapToDouble(Status -> Double.parseDouble(Status.getLostRate().replace("%", ""))) // 去掉%,并转换为double + .average().getAsDouble(); + double sucessRate = lastEntry.stream() + .mapToDouble(Status -> Double.parseDouble(Status.getSuccessRate().replace("%", ""))) // 去掉%,并转换为double + .average().getAsDouble(); + String failRate=String.format("%.2f", (100-sucessRate))+"%"; + //丢包率 + maps.put("lostRate",String.format("%.2f", lostRate)+"%"); + //在线率 + maps.put("sucessRate",String.format("%.2f", sucessRate)+"%"); + //离线率 + maps.put("failRate",failRate); + //总数 + maps.put("sum",String.valueOf(lastEntry.size())); + subMap.put("全部设备",maps); + + return AjaxResult.success(subMap); + } + + +} diff --git a/zc-business/src/main/java/com/zc/business/domain/Device.java b/zc-business/src/main/java/com/zc/business/domain/Device.java new file mode 100644 index 00000000..de6dbbff --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/domain/Device.java @@ -0,0 +1,65 @@ +package com.zc.business.domain; + +/** + * @author mengff + * @Date 2020/03/03 + */ +public class Device { + private long id; + + public String getDeviceNo() { + return deviceNo; + } + + public void setDeviceNo(String deviceNo) { + this.deviceNo = deviceNo; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getDeviceIp() { + return deviceIp; + } + + @Override + public String toString() { + return "Device{" + + "id=" + id + + ", deviceNo='" + deviceNo + '\'' + + ", deviceName='" + deviceName + '\'' + + ", deviceIp='" + deviceIp + '\'' + + '}'; + } + + public Device(long id, String deviceNo, String deviceName, String deviceIp) { + this.id = id; + this.deviceNo = deviceNo; + this.deviceName = deviceName; + this.deviceIp = deviceIp; + } + + public void setDeviceIp(String deviceIp) { + this.deviceIp = deviceIp; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + private String deviceNo; + private String deviceName; + private String deviceIp; + + private String type; + +} \ No newline at end of file diff --git a/zc-business/src/main/java/com/zc/business/domain/Status.java b/zc-business/src/main/java/com/zc/business/domain/Status.java new file mode 100644 index 00000000..dbb055bc --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/domain/Status.java @@ -0,0 +1,205 @@ +package com.zc.business.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +/** + * @author mengff + * @Date 2024/01/04 + */ +public class Status { + public String getDeviceIp() { + return deviceIp; + } + + public void setDeviceIp(String deviceIp) { + this.deviceIp = deviceIp; + } + public LocalDateTime getStartTime() { + return startTime; + } + + public Status(long id, String deviceNo, String deviceName, int deviceStatus, LocalDateTime time, LocalDateTime startTime, String deviceIp, String successRate, String lostRate, String direction, String production, String model, String network, String content, String type) { + this.id = id; + this.deviceNo = deviceNo; + this.deviceName = deviceName; + this.deviceStatus = deviceStatus; + this.time = time; + this.startTime = startTime; + this.deviceIp = deviceIp; + this.successRate = successRate; + this.lostRate = lostRate; + this.direction = direction; + this.production = production; + this.model = model; + this.network = network; + this.content = content; + this.type = type; + } + + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + + @Override + public String toString() { + return "Status{" + + "id=" + id + + ", deviceNo='" + deviceNo + '\'' + + ", deviceName='" + deviceName + '\'' + + ", deviceStatus=" + deviceStatus + + ", time=" + time + + ", startTime=" + startTime + + ", deviceIp='" + deviceIp + '\'' + + ", successRate='" + successRate + '\'' + + ", lostRate='" + lostRate + '\'' + + ", direction='" + direction + '\'' + + ", production='" + production + '\'' + + ", model='" + model + '\'' + + ", network='" + network + '\'' + + ", content='" + content + '\'' + + ", type='" + type + '\'' + + '}'; + } + + public LocalDateTime getTime() { + return time; + } + + public void setTime(LocalDateTime time) { + this.time = time; + } + + public String getDeviceNo() { + return deviceNo; + } + + public Status(long id, String deviceNo, String deviceName, int deviceStatus) { + this.id = id; + this.deviceNo = deviceNo; + this.deviceName = deviceName; + this.deviceStatus = deviceStatus; + } + + public Status() { + } + + public void setDeviceNo(String deviceNo) { + this.deviceNo = deviceNo; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public int getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(int deviceStatus) { + this.deviceStatus = deviceStatus; + } + + private long id; + + private String deviceNo; + + + private String deviceName; + private int deviceStatus; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss") + private LocalDateTime time; + + public String getSuccessRate() { + return successRate; + } + + public void setSuccessRate(String successRate) { + this.successRate = successRate; + } + + public String getLostRate() { + return lostRate; + } + + public void setLostRate(String lostRate) { + this.lostRate = lostRate; + } + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss") + private LocalDateTime startTime; + + private String deviceIp; + + private String successRate; + + private String lostRate; + + private String direction; + + private String production; + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getProduction() { + return production; + } + + public void setProduction(String production) { + this.production = production; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getNetwork() { + return network; + } + + public void setNetwork(String network) { + this.network = network; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + private String model; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + private String network; + + private String content; + + private String type; + +} diff --git a/zc-business/src/main/java/com/zc/business/mapper/DeviceMapper.java b/zc-business/src/main/java/com/zc/business/mapper/DeviceMapper.java new file mode 100644 index 00000000..270a9e83 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/mapper/DeviceMapper.java @@ -0,0 +1,16 @@ +package com.zc.business.mapper; + +import com.zc.business.domain.Device; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author mengff + * @Date 2024/01/04 + */ +@Repository +public interface DeviceMapper { + + List SelectList(); +} \ No newline at end of file diff --git a/zc-business/src/main/java/com/zc/business/mapper/StatusMapper.java b/zc-business/src/main/java/com/zc/business/mapper/StatusMapper.java new file mode 100644 index 00000000..1980b0c8 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/mapper/StatusMapper.java @@ -0,0 +1,21 @@ +package com.zc.business.mapper; +import com.zc.business.domain.Status; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author mengff + * @Date 2024/01/04 + */ +@Repository +public interface StatusMapper { + + + + int Add(@Param("status")Status status); + + List listStatus(@Param("status")Status status); + +} diff --git a/zc-business/src/main/java/com/zc/business/service/impl/DeviceService.java b/zc-business/src/main/java/com/zc/business/service/impl/DeviceService.java new file mode 100644 index 00000000..416a0256 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/service/impl/DeviceService.java @@ -0,0 +1,23 @@ +package com.zc.business.service.impl; + +import com.zc.business.domain.Device; +import com.zc.business.mapper.DeviceMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author mengff + * @Date 2024/01/04 + */ +@Service +public class DeviceService { + @Autowired + DeviceMapper deviceMapper; + + public List SelectList() { + return deviceMapper.SelectList(); + } + +} \ No newline at end of file diff --git a/zc-business/src/main/java/com/zc/business/service/impl/ExcelExportService.java b/zc-business/src/main/java/com/zc/business/service/impl/ExcelExportService.java new file mode 100644 index 00000000..012ae181 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/service/impl/ExcelExportService.java @@ -0,0 +1,192 @@ +package com.zc.business.service.impl; + +import com.zc.business.domain.Status; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.stereotype.Service; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +@Service +public class ExcelExportService { + + public void exportDataToExcel(Map> ipMap, Map >categoryMap, String filePath) { + Workbook workbook = new XSSFWorkbook(); + Map> map = new TreeMap<>(ipMap); + Sheet sheet = workbook.createSheet("设备故障率分时统计页"); + int rowNum = 0; + Row row0 = sheet.createRow(0); + row0.createCell(0).setCellValue("设备名称"); + row0.createCell(1).setCellValue("设备IP"); + row0.createCell(2).setCellValue("设备桩号"); + row0.createCell(3).setCellValue("设备方向"); + row0.createCell(4).setCellValue("设备厂家"); + row0.createCell(5).setCellValue("设备型号"); + row0.createCell(6).setCellValue("备注"); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 3, 3)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 4, 4)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 5, 5)); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 6, 6)); + int i=0; + boolean flag = true; + Row row1= sheet.createRow(1); + for (Map.Entry> entry : map.entrySet()) { + row0.createCell(2*i+7).setCellValue(entry.getKey()+"时"); + sheet.addMergedRegion(new CellRangeAddress(0, 0, 2*i+7, 2*i+8)); + row1.createCell(2*i+7).setCellValue("在线率"); + row1.createCell(2*i+8).setCellValue("丢包率"); + rowNum = 2; + List groupItems = entry.getValue(); + for (Status ignored : groupItems) { + int a=rowNum++; + Row row = sheet.getRow(a); // 获取指定索引的行 + if (row == null) { // 如果行不存在,则创建新行 + row = sheet.createRow(a); + } + if(flag) { + row.createCell(0).setCellValue(ignored.getDeviceName()); + row.createCell(1).setCellValue(ignored.getDeviceIp()); + row.createCell(2).setCellValue(ignored.getDeviceNo()); + row.createCell(3).setCellValue(ignored.getDirection()); + row.createCell(4).setCellValue(ignored.getProduction()); + row.createCell(5).setCellValue(ignored.getModel()); + row.createCell(6).setCellValue(ignored.getContent()); + } + row.createCell(2*i+7).setCellValue(ignored.getSuccessRate()); + row.createCell(2*i+8).setCellValue(ignored.getLostRate()); + } + i++; + flag = false; + } + Sheet sheets = workbook.createSheet("设备故障率汇总页"); + createSheet(sheets,categoryMap); + Sheet sheet1 = workbook.createSheet("设备故障率分时汇总页"); + createSheet1(sheet1,ipMap); + try (FileOutputStream outputStream = new FileOutputStream(filePath)) { + workbook.write(outputStream); + } catch (IOException e) { + e.printStackTrace(); + } + System.out.println("excel写入成功!!!!!!"); + + } + public void createSheet1(Sheet sheet,Map> ipMap){ + Map> map = new TreeMap<>(ipMap); + int rowNum = 0; + Row row0 = sheet.createRow(rowNum); + row0.createCell(0).setCellValue("设备分类"); + sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0)); + int i=0; + boolean flag = true; + Row row1= sheet.createRow(1); + for (Map.Entry> entry : map.entrySet()) { + row0.createCell(3 * i + 1).setCellValue(entry.getKey() + "时"); + sheet.addMergedRegion(new CellRangeAddress(0, 0, 3 * i + 1, 3 * i + 3)); + row1.createCell(3 * i + 1).setCellValue("总统计数"); + row1.createCell(3 * i + 2).setCellValue("在线统计数"); + row1.createCell(3 * i + 3).setCellValue("在线率"); + rowNum = 2; + List groupItem = entry.getValue(); + Map> maps = groupItem.stream().filter(iteam -> iteam.getType() != null).collect(Collectors.groupingBy(Status::getType)); + for (Map.Entry> entrys : maps.entrySet()) { + List groupItems = entrys.getValue(); + long b = groupItems.stream().filter(iteam -> iteam.getDeviceStatus() == 1).count(); +// for (Status ignored : groupItems) { + int a = rowNum++; + Row row = sheet.getRow(a); // 获取指定索引的行 + if (row == null) { // 如果行不存在,则创建新行 + row = sheet.createRow(a); + } + HashMap itemTypeMap = new HashMap<>(); + itemTypeMap.put("1", "高清网络枪型固定摄像机"); + itemTypeMap.put("2", "高清网络球形摄像机"); + itemTypeMap.put("3", "桥下高清网络球形摄像机"); + itemTypeMap.put("4", "360°全景摄像机"); + itemTypeMap.put("5", "180°全景摄像机"); + itemTypeMap.put("6", "门架式可变信息标志"); + itemTypeMap.put("7", "雨棚可变信息标志"); + itemTypeMap.put("8", "站前悬臂式可变信息标志"); + itemTypeMap.put("9", "气象检测器"); + itemTypeMap.put("10", "路段语音广播系统"); + itemTypeMap.put("11", "护栏碰撞预警系统"); + itemTypeMap.put("12", "毫米波雷达"); + itemTypeMap.put("13", "合流区预警系统"); + itemTypeMap.put("14", "激光疲劳唤醒"); + itemTypeMap.put("15", "一类交通量调查站"); + itemTypeMap.put("16", "智能行车诱导系统"); + itemTypeMap.put("17", "智能设备箱"); + String type = groupItems.get(0).getType(); + String description = itemTypeMap.get(type); + if (flag) { + row.createCell(0).setCellValue(description); + } + row.createCell(3 * i + 1).setCellValue(groupItems.size()); + row.createCell(3 * i + 2).setCellValue(b); + row.createCell(3 * i + 3).setCellValue(String.format("%.2f%%", (double) b / groupItems.size() * 100)); + } + i++; + flag = false; + // } + } + + } + + public void createSheet(Sheet sheet,Map >categoryMap){ + int rowNum = 0; + Row row = sheet.createRow(rowNum); + row.createCell(0).setCellValue("设备分类"); + row.createCell(1).setCellValue("总统计数"); + row.createCell(2).setCellValue("在线统计数"); + row.createCell(3).setCellValue("在线率"); + rowNum = 1; + for (Map.Entry> entry : categoryMap.entrySet()) { + List groupItems = entry.getValue(); + long a=groupItems.stream().filter(iteam->iteam.getDeviceStatus()==1).count(); + row = sheet.createRow(rowNum++); + HashMap itemTypeMap = new HashMap<>(); + itemTypeMap.put("1", "高清网络枪型固定摄像机"); + itemTypeMap.put("2", "高清网络球形摄像机"); + itemTypeMap.put("3", "桥下高清网络球形摄像机"); + itemTypeMap.put("4", "360°全景摄像机"); + itemTypeMap.put("5", "180°全景摄像机"); + itemTypeMap.put("6", "门架式可变信息标志"); + itemTypeMap.put("7", "雨棚可变信息标志"); + itemTypeMap.put("8", "站前悬臂式可变信息标志"); + itemTypeMap.put("9", "气象检测器"); + itemTypeMap.put("10", "路段语音广播系统"); + itemTypeMap.put("11", "护栏碰撞预警系统"); + itemTypeMap.put("12", "毫米波雷达"); + itemTypeMap.put("13", "合流区预警系统"); + itemTypeMap.put("14", "激光疲劳唤醒"); + itemTypeMap.put("15", "一类交通量调查站"); + itemTypeMap.put("16", "智能行车诱导系统"); + itemTypeMap.put("17", "智能设备箱"); + String type = groupItems.get(0).getType(); + String description = itemTypeMap.get(type); + row.createCell(0).setCellValue(description); + row.createCell(1).setCellValue(groupItems.size()); + row.createCell(2).setCellValue(a); + row.createCell(3).setCellValue(String.format("%.2f%%", (double) a / groupItems.size() * 100)); + + } + + } + + + + + +} + diff --git a/zc-business/src/main/java/com/zc/business/service/impl/StatusService.java b/zc-business/src/main/java/com/zc/business/service/impl/StatusService.java new file mode 100644 index 00000000..f1e4ef64 --- /dev/null +++ b/zc-business/src/main/java/com/zc/business/service/impl/StatusService.java @@ -0,0 +1,33 @@ +package com.zc.business.service.impl; +import com.zc.business.domain.Status; +import com.zc.business.mapper.StatusMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author mengff + * @Date 2024/01/04 + */ +@Service +public class StatusService { + @Autowired + StatusMapper statusMapper; + + + public String Add(Status status) { + int a = statusMapper.Add(status); + if (a == 1) { + return "添加成功"; + } else { + return "添加失败"; + } + } + + public List list(Status status) { + List list = statusMapper.listStatus(status); + return list; + } + +} diff --git a/zc-business/src/main/resources/mapper/business/DeviceMapper.xml b/zc-business/src/main/resources/mapper/business/DeviceMapper.xml new file mode 100644 index 00000000..a64ae26f --- /dev/null +++ b/zc-business/src/main/resources/mapper/business/DeviceMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zc-business/src/main/resources/mapper/business/StatusMapper.xml b/zc-business/src/main/resources/mapper/business/StatusMapper.xml new file mode 100644 index 00000000..1947948f --- /dev/null +++ b/zc-business/src/main/resources/mapper/business/StatusMapper.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO status + + + device_no, + + + device_name, + + + device_status, + + + time, + + + success_rate, + + + + lost_rate, + + + device_ip, + + + + + #{status.deviceNo,jdbcType=VARCHAR}, + + + #{status.deviceName,jdbcType=VARCHAR}, + + + #{status.deviceStatus,jdbcType=INTEGER}, + + + #{status.time,jdbcType=DATE}, + + + #{status.successRate,jdbcType=VARCHAR}, + + + #{status.lostRate,jdbcType=VARCHAR}, + + + + #{status.deviceIp,jdbcType=VARCHAR}, + + + + + + select id, device_no, device_name, device_status, time from status + + + + + From cfc29d819bd067c943b25a06914eb1c7007bdaa0 Mon Sep 17 00:00:00 2001 From: xiepufeng <1072271977@qq.com> Date: Wed, 17 Jan 2024 17:09:42 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=AE=A2=E9=98=85=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=A6=BB=E7=BA=BF=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DcDeviceController.java | 9 ++++++++ .../device/OfflineMessageListener.java | 23 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java b/zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java index e3b528ab..cd512d99 100644 --- a/zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java +++ b/zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java @@ -136,6 +136,7 @@ public class DcDeviceController extends BaseController { * @param deviceId 物联设备id * @return 获取属性数据操作结果 */ + @ApiOperation("获取设备最新属性数据") @GetMapping("/properties/latest/{deviceId}") public AjaxResult getDeviceLatestProperties(@PathVariable @Parameter(description = "设备ID") String deviceId) throws HttpException, IOException { @@ -155,6 +156,7 @@ public class DcDeviceController extends BaseController { * @param props 查询条件 * @return 属性列表 */ + @ApiOperation("获取设备历史属性列表") @GetMapping("/properties/history/{deviceId}/{propertyId}") public AjaxResult queryDeviceProperties(@PathVariable @Parameter(description = "设备ID") String deviceId, @PathVariable @Parameter(description = "属性ID") String propertyId, @@ -178,6 +180,7 @@ public class DcDeviceController extends BaseController { * @param propertyId 属性id * @return 获取属性数据操作结果 */ + @ApiOperation("获取设备指定属性最新数据") @GetMapping("/properties/latest/{deviceId}/{propertyId}") public AjaxResult getDeviceLatestProperty(@PathVariable @Parameter(description = "设备ID") String deviceId, @PathVariable @Parameter(description = "属性ID") String propertyId) throws HttpException, IOException { @@ -196,6 +199,7 @@ public class DcDeviceController extends BaseController { * @param propertyId 属性 * @return 属性实时数据 */ + @ApiOperation("获取设备指定属性实时数据") @GetMapping("/properties/realtime/{deviceId}/{propertyId}") public AjaxResult getDeviceRealtimeProperty( @PathVariable String deviceId, @@ -221,6 +225,7 @@ public class DcDeviceController extends BaseController { * @param props 属性id集 * @return 属性实时数据 */ + @ApiOperation("获取设备属性实时数据") @PostMapping("/properties/realtime/{deviceId}") public AjaxResult getDeviceRealtimeProperties( @PathVariable String deviceId, @@ -249,6 +254,7 @@ public class DcDeviceController extends BaseController { * @param props 参数 * @return 设备属性操作结果 */ + @ApiOperation("设置设备属性值") @PostMapping("/properties/setting/{deviceId}") public AjaxResult setDeviceProperties( @PathVariable String deviceId, @@ -274,6 +280,7 @@ public class DcDeviceController extends BaseController { * @param props 调用参数 * @return 调用结果 */ + @ApiOperation("设备功能调用") @PostMapping("/functions/{deviceId}/{functionId}") public AjaxResult invokedFunction( @PathVariable String deviceId, @@ -302,6 +309,7 @@ public class DcDeviceController extends BaseController { * @param queryParam 查询条件 * @return 查询事件结果 */ + @ApiOperation("查询事件历史数据列表") @GetMapping("/events/history/{deviceId}/{eventId}") public AjaxResult queryPagerDeviceEvents( @PathVariable @Parameter(description = "设备ID") String deviceId, @@ -327,6 +335,7 @@ public class DcDeviceController extends BaseController { * @param id 物联设备id * @return 更新结果 */ + @ApiOperation("获取设备物模型") @GetMapping(value = "/metadata/{id}") public AjaxResult getMetadata(@PathVariable String id) throws HttpException, IOException { diff --git a/zc-business/src/main/java/com/zc/business/message/device/OfflineMessageListener.java b/zc-business/src/main/java/com/zc/business/message/device/OfflineMessageListener.java index a773a5ce..ebd7bded 100644 --- a/zc-business/src/main/java/com/zc/business/message/device/OfflineMessageListener.java +++ b/zc-business/src/main/java/com/zc/business/message/device/OfflineMessageListener.java @@ -1,14 +1,18 @@ package com.zc.business.message.device; +import com.alibaba.fastjson.JSON; import com.zc.common.core.redis.stream.RedisStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.stream.ObjectRecord; import org.springframework.data.redis.connection.stream.RecordId; import org.springframework.data.redis.stream.StreamListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; +import javax.annotation.Resource; +import java.util.List; + /** * 离线消息监听 */ @@ -17,15 +21,30 @@ public class OfflineMessageListener implements StreamListener message) { String streamKay = message.getStream(); RecordId recordId = message.getId(); + threadPoolTaskExecutor.execute(() -> { + List list = JSON.parseArray(message.getValue(), String.class); + this.handle(list); + }); + // 消费完后直接删除消息 redisStream.del(streamKay, String.valueOf(recordId)); } + + /** + * 处理离线消息 + */ + private void handle(List msg) { + System.out.println(msg); + } } From 3dcfb1c9a4fd621300c390d26eb32238466f1332 Mon Sep 17 00:00:00 2001 From: mengff <1198151809@qq.com> Date: Wed, 17 Jan 2024 17:41:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?--=E5=A2=9E=E5=8A=A0=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/controller/StatusController.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/zc-business/src/main/java/com/zc/business/controller/StatusController.java b/zc-business/src/main/java/com/zc/business/controller/StatusController.java index 84029a24..be771e9b 100644 --- a/zc-business/src/main/java/com/zc/business/controller/StatusController.java +++ b/zc-business/src/main/java/com/zc/business/controller/StatusController.java @@ -1,5 +1,7 @@ package com.zc.business.controller; +import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; import com.zc.business.domain.Status; import com.zc.business.service.impl.StatusService; import io.swagger.annotations.Api; @@ -13,29 +15,33 @@ import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; -@Api("设备状态") + +import static com.ruoyi.common.utils.PageUtils.startPage; + +@Api(tags="设备状态") @RestController @RequestMapping("/system/status") -public class StatusController { +public class StatusController extends BaseController { @Autowired private StatusService statusService; //设备列表 - @ApiOperation("设备状态柱状按时间和类型") + @ApiOperation("设备状态列表按时间和类型") @GetMapping ("/tablist") - public AjaxResult getTabList(Status status) + public TableDataInfo getTabList(Status status) { + startPage(); LocalDateTime todayStart = status.getStartTime().truncatedTo(ChronoUnit.DAYS); LocalDateTime currentTime = status.getTime().truncatedTo(ChronoUnit.DAYS).plusDays(1); status.setStartTime(todayStart); status.setTime(currentTime); List listStatus = statusService.list(status); - return AjaxResult.success(listStatus); + return getDataTable(listStatus); } //按时间划分设备柱状图 - @ApiOperation("设备状态列表按时间和类型") + @ApiOperation("设备状态柱状图按时间和类型") @GetMapping ("/list") public AjaxResult getStatusList(Status status) {