commit 8af05699ca2a18db08dd8869bb2fd0ddf02da84c Author: wu Date: Mon Dec 23 09:26:41 2024 +0800 第一次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..953cff7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + com.parkingLot + parkingLot + 0.0.1-SNAPSHOT + ParkingLot + Demo project for Spring Boot + + 1.8 + UTF-8 + UTF-8 + 2.6.13 + + + + + cn.hutool + hutool-all + 5.8.25 + + + com.alibaba.fastjson2 + fastjson2 + 2.0.41 + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.google.guava + guava + 28.1-jre + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + parkingLot + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + com.parkingLot.ParkingLotApplication + + + + repackage + + repackage + + + + + + + + diff --git a/src/main/java/com/parkingLot/ParkingLotApplication.java b/src/main/java/com/parkingLot/ParkingLotApplication.java new file mode 100644 index 0000000..bec8d01 --- /dev/null +++ b/src/main/java/com/parkingLot/ParkingLotApplication.java @@ -0,0 +1,13 @@ +package com.parkingLot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ParkingLotApplication { + + public static void main(String[] args) { + SpringApplication.run(ParkingLotApplication.class, args); + } + +} diff --git a/src/main/java/com/parkingLot/base/constant/HttpStatus.java b/src/main/java/com/parkingLot/base/constant/HttpStatus.java new file mode 100644 index 0000000..81c9f7d --- /dev/null +++ b/src/main/java/com/parkingLot/base/constant/HttpStatus.java @@ -0,0 +1,93 @@ +package com.parkingLot.base.constant; + +/** + * 返回状态码 + * + * @author ruoyi + */ +public class HttpStatus { + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + public static final int WARN = 601; +} diff --git a/src/main/java/com/parkingLot/base/controller/BaseController.java b/src/main/java/com/parkingLot/base/controller/BaseController.java new file mode 100644 index 0000000..2e00531 --- /dev/null +++ b/src/main/java/com/parkingLot/base/controller/BaseController.java @@ -0,0 +1,78 @@ +package com.parkingLot.base.controller; + +import com.parkingLot.base.domain.AjaxResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * web层通用数据处理 + * + * @author ruoyi + */ +public class BaseController { + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + /** + * 返回成功 + */ + public AjaxResult success() { + return AjaxResult.success(); + } + + /** + * 返回失败消息 + */ + public AjaxResult error() { + return AjaxResult.error(); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(String message) { + return AjaxResult.success(message); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(Object data) { + return AjaxResult.success(data); + } + + /** + * 返回失败消息 + */ + public AjaxResult error(String message) { + return AjaxResult.error(message); + } + + /** + * 返回警告消息 + */ + public AjaxResult warn(String message) { + return AjaxResult.warn(message); + } + + /** + * 响应返回结果 + * + * @param rows 影响行数 + * @return 操作结果 + */ + protected AjaxResult toAjax(int rows) { + return rows > 0 ? AjaxResult.success() : AjaxResult.error(); + } + + /** + * 响应返回结果 + * + * @param result 结果 + * @return 操作结果 + */ + protected AjaxResult toAjax(boolean result) { + return result ? success() : error(); + } + +} diff --git a/src/main/java/com/parkingLot/base/domain/AjaxResult.java b/src/main/java/com/parkingLot/base/domain/AjaxResult.java new file mode 100644 index 0000000..109781a --- /dev/null +++ b/src/main/java/com/parkingLot/base/domain/AjaxResult.java @@ -0,0 +1,202 @@ +package com.parkingLot.base.domain; + + +import cn.hutool.core.bean.BeanUtil; +import com.parkingLot.base.constant.HttpStatus; + +import java.util.HashMap; +import java.util.Objects; + +/** + * 操作消息提醒 + * + * @author ruoyi + */ +public class AjaxResult extends HashMap { + /** + * 状态码 + */ + public static final String CODE_TAG = "code"; + /** + * 返回内容 + */ + public static final String MSG_TAG = "msg"; + /** + * 数据对象 + */ + public static final String DATA_TAG = "data"; + private static final long serialVersionUID = 1L; + + /** + * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 + */ + public AjaxResult() { + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + * @param data 数据对象 + */ + public AjaxResult(int code, String msg, Object data) { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (BeanUtil.isNotEmpty(data)) { + super.put(DATA_TAG, data); + } + } + + /** + * 返回成功消息 + * + * @return 成功消息 + */ + public static AjaxResult success() { + return AjaxResult.success("操作成功"); + } + + /** + * 返回成功数据 + * + * @return 成功消息 + */ + public static AjaxResult success(Object data) { + return AjaxResult.success("操作成功", data); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @return 成功消息 + */ + public static AjaxResult success(String msg) { + return AjaxResult.success(msg, null); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 成功消息 + */ + public static AjaxResult success(String msg, Object data) { + return new AjaxResult(HttpStatus.SUCCESS, msg, data); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult warn(String msg) { + return AjaxResult.warn(msg, null); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static AjaxResult warn(String msg, Object data) { + return new AjaxResult(HttpStatus.WARN, msg, data); + } + + /** + * 返回错误消息 + * + * @return 错误消息 + */ + public static AjaxResult error() { + return AjaxResult.error("操作失败"); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(String msg) { + return AjaxResult.error(msg, null); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 错误消息 + */ + public static AjaxResult error(String msg, Object data) { + return new AjaxResult(HttpStatus.ERROR, msg, data); + } + + /** + * 返回错误消息 + * + * @param code 状态码 + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(int code, String msg) { + return new AjaxResult(code, msg, null); + } + + /** + * 是否为成功消息 + * + * @return 结果 + */ + public boolean isSuccess() { + return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG)); + } + + /** + * 是否为警告消息 + * + * @return 结果 + */ + public boolean isWarn() { + return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG)); + } + + /** + * 是否为错误消息 + * + * @return 结果 + */ + public boolean isError() { + return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG)); + } + + /** + * 方便链式调用 + * + * @param key 键 + * @param value 值 + * @return 数据对象 + */ + @Override + public AjaxResult put(String key, Object value) { + super.put(key, value); + return this; + } +} diff --git a/src/main/java/com/parkingLot/config/GlobalCorsConfig.java b/src/main/java/com/parkingLot/config/GlobalCorsConfig.java new file mode 100644 index 0000000..3d9935b --- /dev/null +++ b/src/main/java/com/parkingLot/config/GlobalCorsConfig.java @@ -0,0 +1,39 @@ +package com.parkingLot.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + + +/** + * 跨域配置 + * + * @author wu + * @since 2024/12/16 15:47 + */ +@Configuration +public class GlobalCorsConfig { + @Bean + public CorsFilter corsFilter() { + //1. 添加 CORS配置信息 + CorsConfiguration config = new CorsConfiguration(); + // 放行哪些原始域 + config.addAllowedOriginPattern("*"); + // 是否发送 Cookie + config.setAllowCredentials(true); + // 放行哪些请求方式 + config.addAllowedMethod("*"); + // 放行哪些原始请求头部信息 + config.addAllowedHeader("*"); + // 暴露哪些头部信息 + config.addExposedHeader("*"); + //2. 添加映射路径 + UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource(); + corsConfigurationSource.registerCorsConfiguration("/**", config); + //3. 返回新的CorsFilter + return new CorsFilter(corsConfigurationSource); + } +} diff --git a/src/main/java/com/parkingLot/config/exception/GlobalExceptionHandler.java b/src/main/java/com/parkingLot/config/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..d86880f --- /dev/null +++ b/src/main/java/com/parkingLot/config/exception/GlobalExceptionHandler.java @@ -0,0 +1,87 @@ +package com.parkingLot.config.exception; + +import com.parkingLot.base.domain.AjaxResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +import javax.servlet.http.HttpServletRequest; + +/** + * 全局异常处理器 + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + + /** + * 请求方式不支持 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); + return AjaxResult.error(e.getMessage()); + } + + + /** + * 请求参数类型不匹配 + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue())); + } + + /** + * 拦截未知的运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult handleBindException(BindException e) { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + +} diff --git a/src/main/java/com/parkingLot/controller/RemoteCallController.java b/src/main/java/com/parkingLot/controller/RemoteCallController.java new file mode 100644 index 0000000..711dd5a --- /dev/null +++ b/src/main/java/com/parkingLot/controller/RemoteCallController.java @@ -0,0 +1,45 @@ +package com.parkingLot.controller; + +import com.parkingLot.base.controller.BaseController; +import com.parkingLot.dto.Response.CommonResponse; +import com.parkingLot.service.RemoteCallService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author wu + * @since 2024/12/12 16:39 + */ +@RestController +@RequestMapping("/remoteCall") +public class RemoteCallController extends BaseController { + + @Resource + private RemoteCallService remoteCallService; + + + /** + * 区域剩余车位查询 + * + * @return 响应类 + */ + @GetMapping("/GetAreaFreeSpaceNum") + public CommonResponse GetAreaFreeSpaceNum() { + return remoteCallService.GetAreaFreeSpaceNum(); + } + + /** + * 根据车牌查询在场数据 + * + * @param plateNo 车牌号 + * @return 响应类 + */ + @GetMapping("/GetCarInfoByPlateNo") + public CommonResponse GetCarInfoByPlateNo(@RequestParam("plateNo") String plateNo) { + return remoteCallService.GetCarInfoByPlateNo(plateNo); + } +} \ No newline at end of file diff --git a/src/main/java/com/parkingLot/dto/AreaInfoDTO.java b/src/main/java/com/parkingLot/dto/AreaInfoDTO.java new file mode 100644 index 0000000..0fa12cc --- /dev/null +++ b/src/main/java/com/parkingLot/dto/AreaInfoDTO.java @@ -0,0 +1,31 @@ +package com.parkingLot.dto; + +import lombok.Data; + +/** + * @author wu + * @since 2024/12/17 13:59 + */ +@Data +public class AreaInfoDTO { + + /** + * 区域编号 + */ + private Integer areaCode; + + /** + * 区域名称 + */ + private String areaName; + + /** + * 区域剩余停车位数 + */ + private Integer freeSpaceNum; + + /** + * 区域停车位数 + */ + private Integer placeCount; +} diff --git a/src/main/java/com/parkingLot/dto/CarInfoDTO.java b/src/main/java/com/parkingLot/dto/CarInfoDTO.java new file mode 100644 index 0000000..60e85d7 --- /dev/null +++ b/src/main/java/com/parkingLot/dto/CarInfoDTO.java @@ -0,0 +1,65 @@ +package com.parkingLot.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author wu + * @since 2024/12/17 14:29 + */ +@Data +public class CarInfoDTO implements Serializable { + + private static final long serialVersionUID = 5405232225738524744L; + + /** + * 车颜色 + */ + private String carColor; + + /** + * 车辆类型 + */ + private String carStyle; + + /** + * 固定车类型 + */ + private Integer carType; + + /** + * 车辆进出场地点 + */ + private String entryPlace; + + /** + * 入场时间 (yyyy-MM-dd HH:mm:ss) + */ + private String entryTime; + + /** + * 车辆进出场图片名称 + */ + private String imgName; + + /** + * 图片信息类型:1:base64位图片信息;2=图片URL(可公网访问地址)0:没有图片信息 + */ + private Integer imgType; + + /** + * 总停车时间(分钟) + */ + private Integer parkingTime; + + /** + * 车牌号,全车牌 + */ + private String plateNo; + + /** + * 出入场唯一记录ID + */ + private String trafficId; +} diff --git a/src/main/java/com/parkingLot/dto/DataDTO.java b/src/main/java/com/parkingLot/dto/DataDTO.java new file mode 100644 index 0000000..6107da2 --- /dev/null +++ b/src/main/java/com/parkingLot/dto/DataDTO.java @@ -0,0 +1,31 @@ +package com.parkingLot.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author wu + * @since 2024/12/17 13:58 + */ +@Data +public class DataDTO { + + private List areaInfo; + + + /** + * 空闲车位数 + */ + private Integer freeSpaceNum; + + /** + * 停车场名称 + */ + private String parkName; + + /** + * 总车位数 + */ + private Integer totalNum; +} diff --git a/src/main/java/com/parkingLot/dto/Response/CommonResponse.java b/src/main/java/com/parkingLot/dto/Response/CommonResponse.java new file mode 100644 index 0000000..25a6dcb --- /dev/null +++ b/src/main/java/com/parkingLot/dto/Response/CommonResponse.java @@ -0,0 +1,28 @@ +package com.parkingLot.dto.Response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 科拓通用响应 + * + * @author wu + * @since 2024/12/17 13:57 + */ +@Data +public class CommonResponse implements Serializable { + private static final long serialVersionUID = -4789816950186563398L; + + + @JsonProperty("data") + private Object data; + + @JsonProperty("resCode") + private String resCode; + + @JsonProperty("resMsg") + private String resMsg; + +} diff --git a/src/main/java/com/parkingLot/quartz/QuartzImg.java b/src/main/java/com/parkingLot/quartz/QuartzImg.java new file mode 100644 index 0000000..a1ad610 --- /dev/null +++ b/src/main/java/com/parkingLot/quartz/QuartzImg.java @@ -0,0 +1,943 @@ +package com.parkingLot.quartz; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import com.parkingLot.dto.AreaInfoDTO; +import com.parkingLot.dto.DataDTO; +import com.parkingLot.dto.Response.CommonResponse; +import com.parkingLot.service.RemoteCallService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * 定时任务更新图片 + * + * @author wu + * @since 2024/12/17 09:15 + */ +@Slf4j +@Configuration +@EnableScheduling +public class QuartzImg { + + @javax.annotation.Resource + private RemoteCallService remoteCallService; + + private DataDTO dataDTO; + + /** + * 获取停车场实时数据 + */ + private void getAreaFreeSpaceNum() { + CommonResponse commonResponse = remoteCallService.GetAreaFreeSpaceNum(); + Object data = commonResponse.getData(); + if (data == null) { + return; + } + dataDTO = BeanUtil.copyProperties(data, DataDTO.class); + } + + /** + * 镇南镇北输出反面91更新图片 + */ + @Scheduled(cron = "0 */1 * * * *") + public void updateImgOne() { + getAreaFreeSpaceNum(); + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.91_反面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇南停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.91输出反面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇北输出正面91更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgTow() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.91_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.91输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇北输出正面92更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgThree() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.92_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.92输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇北输出正面93更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgFour() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.93_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.93输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇南镇北输出正面94更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgFive() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.94_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇南停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.94输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇北输出正面95更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgSix() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.95_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.95输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南输出反面96更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgSeven() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.96_反面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇南停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.96输出反面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + /** + * 镇东镇北输出正面96更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgEight() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.96_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 18); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[2]; + ; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 133; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 2 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = height - 68; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.96输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南镇北输出正面101更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgNine() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.101_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 50); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[3]; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[2] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇南停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 20; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 5 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = yPosition - 70; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.101输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南镇北输出正面102更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgTen() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.102_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 50); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[3]; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[2] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇南停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 20; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 5 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = yPosition - 70; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.102输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南镇北输出正面103更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgEleven() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.103_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 50); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[3]; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[2] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇南停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 20; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 5 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = yPosition - 70; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.103输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南镇北输出正面104更新图片 + */ + @Scheduled(cron = "2 */1 * * * *") + public void updateImgTwelve() { + try { + // 加载图片资源 + Resource resource = new ClassPathResource("static/templates/192.168.1.104_正面.bmp"); + InputStream inputStream = resource.getInputStream(); + Image src = ImageIO.read(inputStream); + int width = src.getWidth(null); + int height = src.getHeight(null); + + // 创建一个新的BufferedImage对象用于绘制 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + // 绘制原始图片 + g.drawImage(src, 0, 0, width, height, null); + // 设置字体颜色 + g.setColor(new Color(152, 251, 152)); // 设置字体颜色为淡绿色 + // 设置加粗字体,大小为18 + Font font = new Font("黑体", Font.BOLD, 50); + g.setFont(font); + // 要绘制的字符串 + String[] text = new String[3]; + // 创建FontMetrics对象用于获取字符串的宽度 + FontMetrics fm = g.getFontMetrics(font); + if (CollectionUtil.isEmpty(dataDTO.getAreaInfo())) { + return; + } + for (AreaInfoDTO dto : dataDTO.getAreaInfo()) { + if ("镇东停车场".equals(dto.getAreaName())) { + text[2] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇南停车场".equals(dto.getAreaName())) { + text[1] = String.valueOf(dto.getFreeSpaceNum()); + } + if ("镇北停车场".equals(dto.getAreaName())) { + text[0] = String.valueOf(dto.getFreeSpaceNum()); + } + } + // 设置初始y坐标 + int yPosition = height - 20; // 初始y位置 + // 循环绘制每个字符串,计算它们的宽度并进行右对齐 + for (String str : text) { + int stringWidth = fm.stringWidth(str); // 计算字符串的宽度 + // 计算绘制文本的x坐标,使文本右对齐 + int xPosition = width - 5 - stringWidth; + g.drawString(str, xPosition, yPosition); // 绘制字符串 + // 调整y坐标,确保文本不重叠 + yPosition = yPosition - 70; + } + // 释放图形上下文 + g.dispose(); + // 输出文件路径 + File out = new File("D:\\fujica\\PushScreenInfo\\192.168.1.104输出正面.bmp"); + // 检查目标文件所在的目录是否存在 + File parentDir = out.getParentFile(); + if (!parentDir.exists()) { + // 如果目录不存在,创建该目录 + parentDir.mkdirs(); + } + // 保存修改后的图片 + ImageIO.write(image, "bmp", out); + log.info("图片保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇南镇北镇北输出正反91更新图片 + */ + @Scheduled(cron = "5 */1 * * * *") + public void updateImgThirteen() { + try { + // 加载第一个图像 + File file1 = new File("D:\\fujica\\PushScreenInfo\\192.168.1.91输出正面.bmp"); + BufferedImage image1 = ImageIO.read(file1); + // 加载第二个图像 + File file2 = new File("D:\\fujica\\PushScreenInfo\\192.168.1.91输出反面.bmp"); + BufferedImage image2 = ImageIO.read(file2); + // 计算合并后图像的宽度和高度 + int totalWidth = image1.getWidth() + image2.getWidth(); // 宽度是两个图像宽度之和 + int maxHeight = Math.max(image1.getHeight(), image2.getHeight()); // 高度是两个图像中较大的高度 + // 创建一个新的BufferedImage对象,用于保存合并后的图像 + BufferedImage mergedImage = new BufferedImage(totalWidth, maxHeight, BufferedImage.TYPE_INT_RGB); + Graphics g = mergedImage.createGraphics(); + // 绘制第一个图像到合并图像的左侧 + g.drawImage(image1, 0, 0, null); + // 绘制第二个图像到合并图像的右侧 + g.drawImage(image2, image1.getWidth(), 0, null); + // 释放图形上下文 + g.dispose(); + // 保存合并后的图像 + File outFile = new File("D:\\fujica\\PushScreenInfo\\192.168.1.91输出正反.bmp"); + ImageIO.write(mergedImage, "bmp", outFile); + log.info("图像合并并保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 镇东镇东镇北镇南输出正反96更新图片 + */ + @Scheduled(cron = "5 */1 * * * *") + public void updateImgFourteen() { + try { + // 加载第一个图像 + File file1 = new File("D:\\fujica\\PushScreenInfo\\192.168.1.96输出正面.bmp"); + BufferedImage image1 = ImageIO.read(file1); + // 加载第二个图像 + File file2 = new File("D:\\fujica\\PushScreenInfo\\192.168.1.96输出反面.bmp"); + BufferedImage image2 = ImageIO.read(file2); + // 计算合并后图像的宽度和高度 + int totalWidth = image1.getWidth() + image2.getWidth(); // 宽度是两个图像宽度之和 + int maxHeight = Math.max(image1.getHeight(), image2.getHeight()); // 高度是两个图像中较大的高度 + // 创建一个新的BufferedImage对象,用于保存合并后的图像 + BufferedImage mergedImage = new BufferedImage(totalWidth, maxHeight, BufferedImage.TYPE_INT_RGB); + Graphics g = mergedImage.createGraphics(); + // 绘制第一个图像到合并图像的左侧 + g.drawImage(image1, 0, 0, null); + // 绘制第二个图像到合并图像的右侧 + g.drawImage(image2, image1.getWidth(), 0, null); + // 释放图形上下文 + g.dispose(); + // 保存合并后的图像 + File outFile = new File("D:\\fujica\\PushScreenInfo\\192.168.1.96输出正反.bmp"); + ImageIO.write(mergedImage, "bmp", outFile); + log.info("图像合并并保存成功!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/parkingLot/service/RemoteCallService.java b/src/main/java/com/parkingLot/service/RemoteCallService.java new file mode 100644 index 0000000..794dd85 --- /dev/null +++ b/src/main/java/com/parkingLot/service/RemoteCallService.java @@ -0,0 +1,27 @@ +package com.parkingLot.service; + +import com.parkingLot.dto.Response.CommonResponse; + +/** + * @author wu + * @since 2024/12/13 09:11 + */ +public interface RemoteCallService { + + + /** + * 区域剩余车位查询 + * + * @return 响应类 + */ + CommonResponse GetAreaFreeSpaceNum(); + + /** + * 根据车牌查询在场数据 + * + * @param plateNo 车牌号 + * @return 响应类 + */ + CommonResponse GetCarInfoByPlateNo(String plateNo); + +} diff --git a/src/main/java/com/parkingLot/service/impl/RemoteCallServiceImpl.java b/src/main/java/com/parkingLot/service/impl/RemoteCallServiceImpl.java new file mode 100644 index 0000000..021799c --- /dev/null +++ b/src/main/java/com/parkingLot/service/impl/RemoteCallServiceImpl.java @@ -0,0 +1,113 @@ +package com.parkingLot.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson2.JSONObject; +import com.parkingLot.dto.CarInfoDTO; +import com.parkingLot.dto.DataDTO; +import com.parkingLot.dto.Response.CommonResponse; +import com.parkingLot.service.RemoteCallService; +import com.parkingLot.utils.SignatureUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Map; + +/** + * @author wu + * @since 2024/12/13 09:11 + */ +@Service +public class RemoteCallServiceImpl implements RemoteCallService { + + @Value("${url}") + private String url; + + @Value("${appId}") + private String appId; + + @Value("${appSecret}") + private String appSecret; + + @Value("${parkId}") + private String parkId; + + /** + * 通用请求 + * + * @param serviceCode 方法名 + * @return 通用请求 + */ + private JSONObject getMap(String serviceCode) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("appId", appId); + jsonObject.put("parkId", parkId); + jsonObject.put("ts", System.currentTimeMillis()); + jsonObject.put("reqId", IdUtil.fastSimpleUUID()); + jsonObject.put("serviceCode", serviceCode); + return jsonObject; + } + + /** + * 区域剩余车位查询 + * + * @return 响应类 + */ + @Override + public CommonResponse GetAreaFreeSpaceNum() { + CommonResponse response = new CommonResponse(); + JSONObject jsonObject = getMap("getAreaFreeSpaceNum"); + String key = SignatureUtil.paramsSign(jsonObject, appSecret); + jsonObject.put("key", key); + String body = jsonObject.toJSONString(); + String result = HttpRequest.post(url + "api/wec/GetAreaFreeSpaceNum") + .header("version", "1.0.0") + .header("accept-language", "zh-CN") + .body(body).execute().body(); + Map map = JSONUtil.parseObj(result); + Object dataObj = map.get("data"); + response.setResMsg((String) map.get("resMsg")); + response.setResCode((String) map.get("resCode")); + if (dataObj == null || dataObj == "" || StrUtil.isEmpty(String.valueOf(dataObj))) { + return response; + } + Map data = JSONUtil.parseObj(dataObj); + DataDTO dataDTO = BeanUtil.toBeanIgnoreCase(data, DataDTO.class, false); + response.setData(dataDTO); + return response; + } + + /** + * 根据车牌查询在场数据 + * + * @param plateNo 车牌号 + * @return 响应类 + */ + @Override + public CommonResponse GetCarInfoByPlateNo(String plateNo) { + CommonResponse response = new CommonResponse(); + JSONObject jsonObject = getMap("getCarInfoByPlateNo"); + jsonObject.put("plateNo", plateNo); + String key = SignatureUtil.paramsSign(jsonObject, appSecret); + jsonObject.put("key", key); + String body = jsonObject.toJSONString(); + String result = HttpRequest.post(url + "api/wec/GetCarInfoByPlateNo") + .header("version", "1.0.0") + .header("accept-language", "zh-CN") + .body(body).execute().body(); + Map map = JSONUtil.parseObj(result); + Object dataObj = map.get("data"); + response.setResMsg((String) map.get("resMsg")); + response.setResCode((String) map.get("resCode")); + if (dataObj == null || dataObj == "" || StrUtil.isEmpty(String.valueOf(dataObj))) { + return response; + } + Map data = JSONUtil.parseObj(dataObj); + CarInfoDTO dataDTO = BeanUtil.toBeanIgnoreCase(data, CarInfoDTO.class, false); + response.setData(dataDTO); + return response; + } +} diff --git a/src/main/java/com/parkingLot/utils/SignatureUtil.java b/src/main/java/com/parkingLot/utils/SignatureUtil.java new file mode 100644 index 0000000..66b6726 --- /dev/null +++ b/src/main/java/com/parkingLot/utils/SignatureUtil.java @@ -0,0 +1,85 @@ +package com.parkingLot.utils; + +import com.alibaba.fastjson2.JSONObject; +import com.google.common.base.Joiner; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.TreeMap; + +/** + * 科拓签名工具 + * + * @author wu + * @since 2024/12/13 09:21 + */ +public class SignatureUtil { + + /** + * 参数签名 + * 示例: + * 参数对象:{"amount":100,"orderNo":"闽C12345","payTime":"2020-03-06 10:57:22","freeDetail":"[{\"code\":\"\",\"money\":100,\"time\":0,\"type\":0}]","paySource":"85d15350778b11e9bbaa506b4b2f6421","outOrderNo":"T20200306124536001","parkId":"1000001","payableAmount":200,"reqId":"5be4e3e6d5704a7d91ccbd9731d970f5","payType":1006,"payMethod":6,"appId":"85d15350778b11e9bbaa506b4b2f6421","freeTime":0,"paymentExt":"{\"deviceNo\":\"123456\"}","freeMoney":100,"ts":1583744086841} + * url拼接:amount=100&freeDetail=[{"code":"","money":100,"time":0,"type":0}]&freeMoney=100&freeTime=0&orderNo=闽C12345&outOrderNo=T20200306124536001&parkId=1000001&payMethod=6&paySource=85d15350778b11e9bbaa506b4b2f6421&payTime=2020-03-06 10:57:22&payType=1006&payableAmount=200&paymentExt={"deviceNo":"123456"}&reqId=5be4e3e6d5704a7d91ccbd9731d970f5&ts=1583744086841&EED96C219E83450A + * 签名结果:B19F7863ADCC8B5442A757AC7B90F6AC + * + * @param requestBody 参数对象 + * @param appSecret 秘钥 + * @return 签名 + */ + public static String paramsSign(JSONObject requestBody, String appSecret) { + TreeMap params = new TreeMap<>(); + //过滤掉key,appId字段,空属性及Map或List等复杂对象 + requestBody.entrySet().stream().filter( + p -> !"key".equals(p.getKey()) + && !"appId".equals(p.getKey()) + && p.getValue() != null + && !(p.getValue() instanceof Map) + && !(p.getValue() instanceof Iterable)) + .forEach(p -> { + if (!p.getValue().equals("")) { + params.put(p.getKey(), p.getValue().toString()); + } + }); + //拼接appSecret + String temp = Joiner.on("&").withKeyValueSeparator("=").join(params).concat("&").concat(appSecret); + return md5(temp).toUpperCase(); + } + + /** + * 对文本执行 md5 摘要加密, 此算法与 mysql,JavaScript生成的md5摘要进行过一致性对比. + * + * @param plainText 需要摘要的文本 + * @return 返回值中的字母为小写 + */ + private static String md5(String plainText) { + if (null == plainText) { + plainText = ""; + } + String mD5Str = null; + try { + // JDK 支持以下6种消息摘要算法,不区分大小写 + // md5,sha(sha-1),md2,sha-256,sha-384,sha-512 + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(plainText.getBytes(StandardCharsets.UTF_8)); + byte[] b = md.digest(); + int i; + StringBuilder builder = new StringBuilder(32); + for (byte value : b) { + i = value; + if (i < 0) { + i += 256; + } + if (i < 16) { + builder.append("0"); + } + builder.append(Integer.toHexString(i)); + } + mD5Str = builder.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return mD5Str; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..efeb8f6 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,18 @@ +# 日志配置 +logging: + level: + com.parkingLot: error + org.springframework: error + +# 科拓请求地址 +url: https://kp-open.keytop.cn/unite-api/ + +# 科拓appId +appId: 13798 + +# 科拓appSecret +appSecret: f387dfe312244e46913b2123c70f934e + +# 车场id +parkId: 512025407 + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..30a08e1 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 9004 + servlet: + # 应用的访问路径 + context-path: /api +spring: + profiles: + active: dev +# 日志配置 +logging: + level: + com.parkingLot: info + org.springframework: info diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..bae3bd0 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/sys-info.log + + + + ${log.path}/sys-info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/sys-error.log + + + + ${log.path}/sys-error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + ${log.path}/sys-user.log + + + ${log.path}/sys-user.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/templates/192.168.1.101_正面.bmp b/src/main/resources/static/templates/192.168.1.101_正面.bmp new file mode 100644 index 0000000..1334810 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.101_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.102_正面.bmp b/src/main/resources/static/templates/192.168.1.102_正面.bmp new file mode 100644 index 0000000..22eebfc Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.102_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.103_正面.bmp b/src/main/resources/static/templates/192.168.1.103_正面.bmp new file mode 100644 index 0000000..ef6f3ef Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.103_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.104_正面.bmp b/src/main/resources/static/templates/192.168.1.104_正面.bmp new file mode 100644 index 0000000..269b0a9 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.104_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.91_反面.bmp b/src/main/resources/static/templates/192.168.1.91_反面.bmp new file mode 100644 index 0000000..2fc81b0 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.91_反面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.91_正面.bmp b/src/main/resources/static/templates/192.168.1.91_正面.bmp new file mode 100644 index 0000000..c1ea71d Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.91_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.92_正面.bmp b/src/main/resources/static/templates/192.168.1.92_正面.bmp new file mode 100644 index 0000000..0a0da05 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.92_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.93_反面.bmp b/src/main/resources/static/templates/192.168.1.93_反面.bmp new file mode 100644 index 0000000..2d640ad Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.93_反面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.93_正面.bmp b/src/main/resources/static/templates/192.168.1.93_正面.bmp new file mode 100644 index 0000000..83b1374 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.93_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.94_正面.bmp b/src/main/resources/static/templates/192.168.1.94_正面.bmp new file mode 100644 index 0000000..347ff5b Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.94_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.95_反面.bmp b/src/main/resources/static/templates/192.168.1.95_反面.bmp new file mode 100644 index 0000000..96d6635 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.95_反面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.95_正面.bmp b/src/main/resources/static/templates/192.168.1.95_正面.bmp new file mode 100644 index 0000000..f9fef3f Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.95_正面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.96_反面.bmp b/src/main/resources/static/templates/192.168.1.96_反面.bmp new file mode 100644 index 0000000..7e371f5 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.96_反面.bmp differ diff --git a/src/main/resources/static/templates/192.168.1.96_正面.bmp b/src/main/resources/static/templates/192.168.1.96_正面.bmp new file mode 100644 index 0000000..48d4af3 Binary files /dev/null and b/src/main/resources/static/templates/192.168.1.96_正面.bmp differ diff --git a/src/test/java/com/parkingLot/ParkingLotApplicationTests.java b/src/test/java/com/parkingLot/ParkingLotApplicationTests.java new file mode 100644 index 0000000..4f5accd --- /dev/null +++ b/src/test/java/com/parkingLot/ParkingLotApplicationTests.java @@ -0,0 +1,13 @@ +package com.parkingLot; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ParkingLotApplicationTests { + + @Test + void contextLoads() { + } + +}