From 2e9928725b589786e5e766aa2931c481883cc4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=98=A5=E5=A3=B099?= Date: Thu, 30 Apr 2026 15:27:06 +0800 Subject: [PATCH] =?UTF-8?q?2026-4-30=E6=B7=BB=E5=8A=A0=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rc_autoplc_backend/.idea/.gitignore | 8 + rc_autoplc_backend/.idea/compiler.xml | 26 + rc_autoplc_backend/.idea/encodings.xml | 10 + rc_autoplc_backend/.idea/jarRepositories.xml | 40 ++ rc_autoplc_backend/.idea/uiDesigner.xml | 124 +++++ .../java/com/rczn/config/Knife4jConfig.java | 38 ++ .../main/java/com/rczn/config/WebConfig.java | 55 ++ .../controller/RolePermissionController.java | 65 +++ .../rczn/controller/SysDicDataController.java | 109 ++++ .../rczn/controller/SysDicTypeController.java | 95 ++++ .../controller/SysPermissionController.java | 128 +++++ .../com/rczn/system/domain/SysDicData.java | 52 ++ .../com/rczn/system/domain/SysDicType.java | 41 ++ .../domain/query/RolePermissionQuery.java | 34 ++ .../system/mapper/RolePermissionMapper.java | 18 + .../rczn/system/mapper/SysDicDataMapper.java | 39 ++ .../rczn/system/mapper/SysDicTypeMapper.java | 34 ++ .../system/mapper/SysPermissionMapper.java | 52 ++ .../system/service/RolePermissionService.java | 15 + .../system/service/SysDicDataService.java | 44 ++ .../system/service/SysDicTypeService.java | 40 ++ .../system/service/SysPermissionService.java | 26 + .../impl/RolePermissionServiceImpl.java | 42 ++ .../service/impl/SysDicDataServiceImpl.java | 97 ++++ .../service/impl/SysDicTypeServiceImpl.java | 84 +++ .../impl/SysPermissionServiceImpl.java | 140 +++++ .../resources/mapper/RolePermissionMapper.xml | 45 ++ .../resources/mapper/SysDicDataMapper.xml | 74 +++ .../resources/mapper/SysDicTypeMapper.xml | 62 +++ .../resources/mapper/SysPermissionMapper.xml | 72 +++ .../com/rczn/RcznAdminApplicationTests.java | 13 + .../cache/IsLandActionParamToPlc.java | 28 + .../rczn/rcznautoplc/cache/PlcRunStatus.java | 110 ++++ .../rcznautoplc/cache/RegisterAddrDic.java | 17 + .../controller/ManageLogController.java | 120 +++++ .../rcznautoplc/controller/PlcController.java | 337 ++++++++++++ .../controller/WebSocketController.java | 23 + .../rczn/rcznautoplc/domain/ManageLog.java | 65 +++ .../rcznautoplc/domain/ModbusConnectObj.java | 85 +++ .../rcznautoplc/domain/PlcConnectObj.java | 84 +++ .../com/rczn/rcznautoplc/domain/UserBusy.java | 111 ++++ .../domain/query/DevInfoQuery.java | 122 +++++ .../domain/query/DevParamQuery.java | 87 +++ .../domain/query/GoodsFlowStatusQuery.java | 75 +++ .../domain/query/GoodsInfoQuery.java | 125 +++++ .../domain/query/IslandInfoQuery.java | 60 +++ .../domain/query/IslandParamQuery.java | 84 +++ .../domain/query/StepInfoQuery.java | 118 +++++ .../rcznautoplc/mapper/ManageLogMapper.java | 27 + .../rcznautoplc/service/ManageLogService.java | 21 + .../rczn/rcznautoplc/service/PlcService.java | 125 +++++ .../service/impl/ManageLogServiceImpl.java | 85 +++ .../service/impl/PlcServiceImpl.java | 499 ++++++++++++++++++ .../com/rczn/rcznautoplc/task/PlcTask.java | 159 ++++++ .../utils/PlcCommonProtcolUtil.java | 282 ++++++++++ .../rczn/rcznautoplc/utils/PlcConnectMap.java | 24 + .../rcznautoplc/mapper/ManageLogMapper.xml | 175 ++++++ .../RcznAutoplcApplicationTests.java | 13 + .../main/java/com/rczn/ModbusCmdConst.java | 23 + .../rczn/config/AsyncThreadPoolConfig.java | 40 ++ .../java/com/rczn/config/WebSocketConfig.java | 14 + .../com/rczn/exception/GlobalException.java | 16 + .../java/com/rczn/modbus/Modbus4jUtils.java | 380 +++++++++++++ .../com/rczn/modbus/Modbus4jWriteUtils.java | 247 +++++++++ .../src/main/java/com/rczn/plc/PLCData.java | 56 ++ .../main/java/com/rczn/plc/S7PlcClient.java | 102 ++++ .../main/java/com/rczn/plc/S7PlcCommun.java | 131 +++++ .../com/rczn/plc_common/S7ConnectorPLC.java | 220 ++++++++ .../src/main/java/com/rczn/task/TestCrc.java | 22 + .../src/main/java/com/rczn/task/TestTask.java | 17 + .../src/main/java/com/rczn/task/Video.java | 46 ++ .../java/com/rczn/utils/BeanFactoryUtils.java | 22 + .../com/rczn/websocket/WebSocketServer.java | 75 +++ .../RcznCommonApplicationTests.java | 13 + 74 files changed, 6207 insertions(+) create mode 100644 rc_autoplc_backend/.idea/.gitignore create mode 100644 rc_autoplc_backend/.idea/compiler.xml create mode 100644 rc_autoplc_backend/.idea/encodings.xml create mode 100644 rc_autoplc_backend/.idea/jarRepositories.xml create mode 100644 rc_autoplc_backend/.idea/uiDesigner.xml create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml create mode 100644 rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml create mode 100644 rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml create mode 100644 rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml create mode 100644 rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java create mode 100644 rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml create mode 100644 rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java create mode 100644 rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java create mode 100644 rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java diff --git a/rc_autoplc_backend/.idea/.gitignore b/rc_autoplc_backend/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/rc_autoplc_backend/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/rc_autoplc_backend/.idea/compiler.xml b/rc_autoplc_backend/.idea/compiler.xml new file mode 100644 index 0000000..c858a1e --- /dev/null +++ b/rc_autoplc_backend/.idea/compiler.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/encodings.xml b/rc_autoplc_backend/.idea/encodings.xml new file mode 100644 index 0000000..e768916 --- /dev/null +++ b/rc_autoplc_backend/.idea/encodings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/jarRepositories.xml b/rc_autoplc_backend/.idea/jarRepositories.xml new file mode 100644 index 0000000..082f15f --- /dev/null +++ b/rc_autoplc_backend/.idea/jarRepositories.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/uiDesigner.xml b/rc_autoplc_backend/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/rc_autoplc_backend/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java new file mode 100644 index 0000000..052ebcc --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java @@ -0,0 +1,38 @@ +package com.rczn.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Knife4jConfig { + + @Bean + public OpenAPI customOpenAPI() { + // 1. 声明JWT认证规则 + String securitySchemeName = "Authorization"; + return new OpenAPI() + // 2. 文档基础信息(可选) + .info(new Info() + .title("XX自动化编程系统API") + .version("1.0.0") + .description("集成JWT认证的Knife4j接口文档")) + // 3. 配置全局认证规则(所有接口默认需要Token) + .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) + // 4. 定义Token的传递方式(请求头+Bearer格式) + .components(new Components() + .addSecuritySchemes(securitySchemeName, + new SecurityScheme() + .name(securitySchemeName) + .type(SecurityScheme.Type.HTTP) // HTTP认证 + .scheme("bearer") // Bearer格式 + .bearerFormat("JWT") // Token类型为JWT + .in(SecurityScheme.In.HEADER) // 放在请求头 + ) + ); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java new file mode 100644 index 0000000..076da1a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java @@ -0,0 +1,55 @@ +package com.rczn.config; + +import com.rczn.interceptors.LoginInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +// 必须启用@Configuration,让Spring扫描到 +@Configuration +public class WebConfig implements WebMvcConfigurer { + + // 必须注入拦截器(取消注释) + @Autowired + LoginInterceptor loginInterceptor; + + // 注册拦截器 + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loginInterceptor) + // 拦截所有请求 + .addPathPatterns("/**") + // 放行Swagger/Knife4j所有相关路径(关键补充/doc.html) + .excludePathPatterns( + // Knife4j自定义UI路径(核心!) + "/doc.html", + // Swagger UI页面相关 + "/swagger-ui/**", + "/webjars/**", + // SpringDoc接口文档数据相关 + "/v3/api-docs/**", + "/v3/api-docs.yaml", + // 旧版Swagger兼容 + "/swagger-resources/**", + "/swagger-ui.html" + ) + // 放行登录/注册接口 + .excludePathPatterns("/user/login", "/user/register"); + } + + // 静态资源映射(适配Knife4j+SpringDoc) + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // Knife4j静态资源(核心补充) + registry.addResourceHandler("/doc.html") + .addResourceLocations("classpath:/META-INF/resources/"); + // Swagger UI静态资源 + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springdoc-openapi-ui/"); + // Webjars通用资源 + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java new file mode 100644 index 0000000..3930764 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java @@ -0,0 +1,65 @@ +package com.rczn.controller; + +import com.rczn.domain.Result; +import com.rczn.system.domain.RolePermission; +import com.rczn.system.domain.query.RolePermissionQuery; +import com.rczn.system.service.RolePermissionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/rolePermission") +@Tag(name = "角色权限管理", description = "角色权限关联接口") +public class RolePermissionController { + + @Autowired + RolePermissionService rolePermissionService; + + @GetMapping("/listByRoleId/{roleId}") + @Operation(summary = "根据角色ID查询权限ID列表") + public Result getListByRoleId( + @Parameter(name = "roleId", required = true) @PathVariable Integer roleId) { + List list = rolePermissionService.selectListByRoleId(roleId); + return Result.success(list); + } + + @PostMapping("/add") + @Operation(summary = "给角色添加权限") + public Result add(@RequestBody RolePermissionQuery rolePermission) { + if (rolePermission.getRoleId() == null || rolePermission.getPermissionId() == null) { + return Result.error("角色ID和权限ID不能为空"); + } + try { + RolePermission rolePermissionEntity = new RolePermission(); + rolePermissionEntity.setRoleId(rolePermission.getRoleId()); + rolePermissionEntity.setPermissionId(rolePermission.getPermissionId()); + rolePermissionService.insert(rolePermissionEntity); + return Result.success("添加成功"); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @DeleteMapping("/del") + @Operation(summary = "删除角色权限关联") + public Result delete( + @RequestParam Integer roleId, + @RequestParam(required = false) Integer permissionId) { + boolean success = rolePermissionService.delete(roleId, permissionId); + return success ? Result.success("删除成功") : Result.error("删除失败"); + } + + @DeleteMapping("/clearByRoleId/{roleId}") + @Operation(summary = "清空某个角色的所有权限") + public Result clearByRoleId( + @Parameter(name = "roleId", required = true) @PathVariable Integer roleId) { + rolePermissionService.deleteByRoleId(roleId); + return Result.success("清空成功"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java new file mode 100644 index 0000000..da28134 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java @@ -0,0 +1,109 @@ +package com.rczn.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.Result; +import com.rczn.system.domain.SysDicData; +import com.rczn.system.service.SysDicDataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping("/sysDicData") +@Tag(name = "字典数据管理", description = "字典数据增删改查+分页查询+按类型查询接口") +public class SysDicDataController { + + @Autowired + private SysDicDataService sysDicDataService; + + @GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "分页查询字典数据", description = "支持字典类型ID、标签、值查询") + @Parameters({ + @Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY), + @Parameter(name = "dicId", description = "字典类型ID(可选)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "dicLabel", description = "数据标签(可选,模糊查询)", required = false, example = "运行", in = ParameterIn.QUERY), + @Parameter(name = "dicValue", description = "数据值(可选,模糊查询)", required = false, example = "1", in = ParameterIn.QUERY) + }) + public Result getDicDataPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer dicId, + @RequestParam(required = false) String dicLabel, + @RequestParam(required = false) String dicValue) { + PageInfo pageBean = sysDicDataService.selectPage(pageNum, pageSize, dicId, dicLabel, dicValue); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询字典数据", description = "支持字典类型ID、标签、值查询") + @Parameters({ + @Parameter(name = "dicId", description = "字典类型ID(可选)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "dicLabel", description = "数据标签(可选,模糊查询)", required = false, example = "运行", in = ParameterIn.QUERY), + @Parameter(name = "dicValue", description = "数据值(可选,模糊查询)", required = false, example = "1", in = ParameterIn.QUERY) + }) + public Result getList( + @RequestParam(required = false) Integer dicId, + @RequestParam(required = false) String dicLabel, + @RequestParam(required = false) String dicValue) { + List list = sysDicDataService.selectList( dicId, dicLabel, dicValue); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个字典数据", description = "根据字典数据ID查询详情") + public Result getDicDataById(@PathVariable Long id) { + SysDicData sysDicData = sysDicDataService.selectById(id); + return sysDicData != null ? Result.success(sysDicData) : Result.error("字典数据不存在"); + } + + @GetMapping(value = "/listByDicId/{dicId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "按字典类型ID查询数据列表", description = "查询指定字典类型下的所有有效数据") + public Result getDicDataByDicId(@PathVariable Integer dicId) { + try { + List list = sysDicDataService.selectByDicId(dicId); + return Result.success(list); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增字典数据", description = "字典类型ID、数据标签为必填项") + public Result addDicData(@RequestBody SysDicData sysDicData) { + try { + Long dicDataId = sysDicDataService.insert(sysDicData); + return Result.success(dicDataId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改字典数据", description = "需传入字典数据ID,其他字段可选(非空则更新)") + public Result updateDicData(@RequestBody SysDicData sysDicData) { + try { + Boolean success = sysDicDataService.update(sysDicData); + return success ? Result.success(true) : Result.error("修改失败(字典数据不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "删除字典数据", description = "逻辑删除(设置delSign=1,不物理删除数据)") + public Result deleteDicData(@PathVariable Long id) { + try { + Boolean success = sysDicDataService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(字典数据不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java new file mode 100644 index 0000000..36a814b --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java @@ -0,0 +1,95 @@ +package com.rczn.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.Result; +import com.rczn.system.domain.SysDicType; +import com.rczn.system.service.SysDicTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/sysDicType") +@Tag(name = "字典类型管理", description = "字典类型增删改查+分页查询接口") +public class SysDicTypeController { + + @Autowired + private SysDicTypeService sysDicTypeService; + + @GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "分页查询字典类型", description = "支持字典名称、编码模糊查询") + @Parameters({ + @Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY), + @Parameter(name = "dicName", description = "字典名称(可选,模糊查询)", required = false, example = "设备状态", in = ParameterIn.QUERY), + @Parameter(name = "dicCode", description = "字典编码(可选,模糊查询)", required = false, example = "DEV_STATUS", in = ParameterIn.QUERY) + }) + public Result getDicTypePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String dicName, + @RequestParam(required = false) String dicCode) { + PageInfo pageBean = sysDicTypeService.selectPage(pageNum, pageSize, dicName, dicCode); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询字典类型列表", description = "支持字典名称、编码模糊查询") + @Parameters({ + @Parameter(name = "dicName", description = "字典名称(可选,模糊查询)", required = false, example = "设备状态", in = ParameterIn.QUERY), + @Parameter(name = "dicCode", description = "字典编码(可选,模糊查询)", required = false, example = "DEV_STATUS", in = ParameterIn.QUERY) + }) + public Result getList( + @RequestParam(required = false) String dicName, + @RequestParam(required = false) String dicCode) { + List list = sysDicTypeService.selectList( dicName, dicCode); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个字典类型", description = "根据字典类型ID查询详情") + public Result getDicTypeById(@PathVariable Long id) { + SysDicType sysDicType = sysDicTypeService.selectById(id); + return sysDicType != null ? Result.success(sysDicType) : Result.error("字典类型不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增字典类型", description = "字典名称为必填项") + public Result addDicType(@RequestBody SysDicType sysDicType) { + try { + Long dicTypeId = sysDicTypeService.insert(sysDicType); + return Result.success(dicTypeId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改字典类型", description = "需传入字典类型ID,其他字段可选(非空则更新)") + public Result updateDicType(@RequestBody SysDicType sysDicType) { + try { + Boolean success = sysDicTypeService.update(sysDicType); + return success ? Result.success(true) : Result.error("修改失败(字典类型不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "删除字典类型", description = "逻辑删除(设置delSign=1,不物理删除数据)") + public Result deleteDicType(@PathVariable Long id) { + try { + Boolean success = sysDicTypeService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(字典类型不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java new file mode 100644 index 0000000..4f7f2bb --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java @@ -0,0 +1,128 @@ +package com.rczn.controller; + +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import com.rczn.system.service.SysPermissionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 权限管理 API(MyBatis 树形结构实现) + */ +@RestController +@RequestMapping("/permission") +@Tag(name = "权限管理", description = "权限增删改查接口(树形结构)") +public class SysPermissionController { + + @Autowired + private SysPermissionService sysPermissionService; + + /** + * 1. 分页查询权限(多条件模糊查询) + */ + @GetMapping("/listPage") + @Operation(summary = "分页查询权限", description = "支持角色名、角色编码模糊查询,页码从1开始") + @Parameters({ + @Parameter(name = "pageNum", description = "页码(必填,从1开始)", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY), + @Parameter(name = "parentId", description = "父级ID(可选)", required = false, example = "0", in = ParameterIn.QUERY), + @Parameter(name = "permissionName", description = "权限名称(模糊查询,可选)", required = false, example = "用户添加", in = ParameterIn.QUERY) + }) + public Result> getRolePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer parentId, + @RequestParam(required = false) String permissionName) { + + PageBean pageBean = sysPermissionService.selectRolePage(pageNum, pageSize, parentId,permissionName); + return Result.success(pageBean); + } + + /** + * 1. 查询权限树形结构列表 + */ + @GetMapping("/list") + @Operation(summary = "查询权限树形列表", description = "返回权限树形结构(parentId为0或null为顶级)") + public Result> getPermissionList() { + List treeList = sysPermissionService.getPermissionList(); + return Result.success(treeList); + } + + /** + * 1. 查询权限树形结构列表 + */ +// @GetMapping("/listByParentId/{parentId}") +// @Operation(summary = "查询权限树形列表", description = "返回权限树形结构(parentId为0或null为顶级)") +// public Result> getPermissionListByParentId(@PathVariable Integer parentId) { +// List treeList = sysPermissionService.getPermissionListByParentId(parentId); +// return Result.success(treeList); +// } + + /** + * 2. 根据ID查询单个权限 + */ + @GetMapping("/getById/{id}") + @Operation(summary = "查询单个权限", description = "根据权限ID查询详情") + public Result getPermissionById( + @Parameter(name = "id", description = "权限ID", required = true, example = "1", in = ParameterIn.PATH) + @PathVariable Integer id) { + + Permission permission = sysPermissionService.getPermissionById(id); + if (permission == null) { + return Result.error("权限ID:" + id + " 不存在"); + } + return Result.success(permission); + } + + /** + * 3. 新增权限 + */ + @PostMapping("/add") + @Operation(summary = "新增权限", description = "提交权限信息创建新权限") + public Result addPermission( + @Parameter(name = "permission", description = "权限信息", required = true) + @RequestBody Permission permission) { + + boolean success = sysPermissionService.addPermission(permission); + return success ? Result.success("新增权限成功") : Result.error("新增失败"); + } + + /** + * 4. 修改权限 + */ + @PutMapping("/update") + @Operation(summary = "修改权限", description = "传入权限ID和需要修改的字段") + public Result updatePermission( + @Parameter(name = "permission", description = "权限信息(必须包含ID)", required = true) + @RequestBody Permission permission) { + + try { + boolean success = sysPermissionService.updatePermission(permission); + return success ? Result.success("修改权限成功") : Result.error("修改失败(权限不存在)"); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + /** + * 5. 根据ID删除权限(逻辑删除) + */ + @DeleteMapping("/del/{id}") + @Operation(summary = "删除权限", description = "根据权限ID逻辑删除") + public Result deletePermission( + @Parameter(name = "id", description = "权限ID", required = true, example = "1", in = ParameterIn.PATH) + @PathVariable Integer id) { + + boolean success = sysPermissionService.deletePermission(id); + return success ? Result.success("删除权限成功") : Result.error("删除失败(权限不存在)"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java new file mode 100644 index 0000000..a64751c --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java @@ -0,0 +1,52 @@ +package com.rczn.system.domain; + +import com.rczn.domain.BaseBean; +import java.time.LocalDateTime; + +/** + * 字典数据实体类 + * 对应表:sys_dic_data + */ +public class SysDicData extends BaseBean { + + // 字典类型id(外键) + private Integer dicId; + + // 数据标签 + private String dicLabel; + + // 数据字典值 + private String dicValue; + + public SysDicData() { + } + + public SysDicData(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + // getter/setter + public Integer getDicId() { + return dicId; + } + + public void setDicId(Integer dicId) { + this.dicId = dicId; + } + + public String getDicLabel() { + return dicLabel; + } + + public void setDicLabel(String dicLabel) { + this.dicLabel = dicLabel; + } + + public String getDicValue() { + return dicValue; + } + + public void setDicValue(String dicValue) { + this.dicValue = dicValue; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java new file mode 100644 index 0000000..827bdce --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java @@ -0,0 +1,41 @@ +package com.rczn.system.domain; + +import com.rczn.domain.BaseBean; +import java.time.LocalDateTime; + +/** + * 字典类型实体类 + * 对应表:sys_dic_type + */ +public class SysDicType extends BaseBean { + + // 字典名称(必填) + private String dicName; + + // 字典编码 + private String dicCode; + + public SysDicType() { + } + + public SysDicType(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + // getter/setter + public String getDicName() { + return dicName; + } + + public void setDicName(String dicName) { + this.dicName = dicName; + } + + public String getDicCode() { + return dicCode; + } + + public void setDicCode(String dicCode) { + this.dicCode = dicCode; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java new file mode 100644 index 0000000..f17fa3a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java @@ -0,0 +1,34 @@ +package com.rczn.system.domain.query; + +public class RolePermissionQuery { + + //角色id + private Integer roleId; + + //权限id + private Integer permissionId; + + public RolePermissionQuery(Integer roleId, Integer permissionId) { + this.roleId = roleId; + this.permissionId = permissionId; + } + + public RolePermissionQuery() { + } + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + public Integer getPermissionId() { + return permissionId; + } + + public void setPermissionId(Integer permissionId) { + this.permissionId = permissionId; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java new file mode 100644 index 0000000..93f27f9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java @@ -0,0 +1,18 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.RolePermission; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface RolePermissionMapper { + + List selectListByRoleId(@Param("roleId") Integer roleId); + + int insert(RolePermission rolePermission); + + int delete(@Param("roleId") Integer roleId, @Param("permissionId") Integer permissionId); + + int deleteByRoleId(@Param("roleId") Integer roleId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java new file mode 100644 index 0000000..52cea18 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java @@ -0,0 +1,39 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.SysDicData; +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface SysDicDataMapper { + + /** + * 新增字典数据 + */ + int insert(SysDicData sysDicData); + + /** + * 修改字典数据 + */ + int update(SysDicData sysDicData); + + /** + * 逻辑删除字典数据 + */ + int deleteById(Long id); + + /** + * 根据ID查询字典数据 + */ + SysDicData selectById(Long id); + + /** + * 分页查询字典数据(参数可选) + */ + List selectPage(SysDicData sysDicData); + + /** + * 根据字典类型ID查询字典数据列表 + */ + List selectByDicId(Integer dicId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java new file mode 100644 index 0000000..ec25b7a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java @@ -0,0 +1,34 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.SysDicType; +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface SysDicTypeMapper { + + /** + * 新增字典类型 + */ + int insert(SysDicType sysDicType); + + /** + * 修改字典类型 + */ + int update(SysDicType sysDicType); + + /** + * 逻辑删除字典类型 + */ + int deleteById(Long id); + + /** + * 根据ID查询字典类型 + */ + SysDicType selectById(Long id); + + /** + * 分页查询字典类型(参数可选) + */ + List selectPage(SysDicType sysDicType); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java new file mode 100644 index 0000000..4b67f65 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java @@ -0,0 +1,52 @@ +package com.rczn.system.mapper; + + +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SysPermissionMapper { + + /** + * 分页查询角色(支持角色名/角色编码模糊查询) + */ + List selectPermissionPage( + @Param("parentId") Integer parentId, + @Param("permissionName") String permissionName); + + /** + * 查询总条数(支持模糊查询条件) + */ + Long selectTotal( + @Param("parentId") Integer parentId, + @Param("permissionName") String permissionName); + + /** + * 查询所有权限(未删除) + */ + List selectPermissionList(); + + /** + * 根据ID查询 + */ + Permission selectPermissionById(Integer id); + + /** + * 新增 + */ + int insertPermission(Permission permission); + + /** + * 修改 + */ + int updatePermission(Permission permission); + + /** + * 逻辑删除 + */ + int deletePermissionById(Integer id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java new file mode 100644 index 0000000..6c175d6 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java @@ -0,0 +1,15 @@ +package com.rczn.system.service; + +import com.rczn.system.domain.RolePermission; +import java.util.List; + +public interface RolePermissionService { + + List selectListByRoleId(Integer roleId); + + void insert(RolePermission rolePermission); + + boolean delete(Integer roleId, Integer permissionId); + + void deleteByRoleId(Integer roleId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java new file mode 100644 index 0000000..a590771 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java @@ -0,0 +1,44 @@ +package com.rczn.system.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicData; + +import java.util.List; + +public interface SysDicDataService { + + /** + * 分页查询字典数据 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, Integer dicId, String dicLabel, String dicValue); + + /** + * 查询字典数据列表 + */ + List selectList(Integer dicId, String dicLabel, String dicValue); + + /** + * 根据ID查询字典数据 + */ + SysDicData selectById(Long id); + + /** + * 根据字典类型ID查询字典数据列表 + */ + List selectByDicId(Integer dicId); + + /** + * 新增字典数据 + */ + Long insert(SysDicData sysDicData); + + /** + * 修改字典数据 + */ + Boolean update(SysDicData sysDicData); + + /** + * 逻辑删除字典数据 + */ + Boolean deleteById(Long id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java new file mode 100644 index 0000000..c04b731 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java @@ -0,0 +1,40 @@ +package com.rczn.system.service; + + +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicType; + +import java.util.List; + +public interface SysDicTypeService { + + /** + * 分页查询字典类型 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, String dicName, String dicCode); + + /** + * 查询字典类型列表 + */ + List selectList( String dicName, String dicCode); + + /** + * 根据ID查询字典类型 + */ + SysDicType selectById(Long id); + + /** + * 新增字典类型 + */ + Long insert(SysDicType sysDicType); + + /** + * 修改字典类型 + */ + Boolean update(SysDicType sysDicType); + + /** + * 逻辑删除字典类型 + */ + Boolean deleteById(Long id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java new file mode 100644 index 0000000..8e5ee0a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java @@ -0,0 +1,26 @@ +package com.rczn.system.service; + +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; + +import java.util.List; + +public interface SysPermissionService { + List getPermissionList(); + //根据父ID查询权限列表: + List getPermissionListByParentId(Integer parentId); + Permission getPermissionById(Integer id); + boolean addPermission(Permission permission); + boolean updatePermission(Permission permission); + boolean deletePermission(Integer id); + + /** + * 1. 分页查询角色(多条件模糊查询) + * @param pageNum + * @param pageSize + * @param permissionName + * @return + */ + PageBean selectRolePage(Integer pageNum, Integer pageSize,Integer parentId, String permissionName); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java new file mode 100644 index 0000000..5a1fb45 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java @@ -0,0 +1,42 @@ +package com.rczn.system.service.impl; + +import com.rczn.system.domain.RolePermission; +import com.rczn.system.mapper.RolePermissionMapper; +import com.rczn.system.service.RolePermissionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +public class RolePermissionServiceImpl implements RolePermissionService { + + @Autowired + RolePermissionMapper rolePermissionMapper; + + @Override + public List selectListByRoleId(Integer roleId) { + return rolePermissionMapper.selectListByRoleId(roleId); + } + + @Override + @Transactional + public void insert(RolePermission rolePermission) { + rolePermission.setCreateTime(LocalDateTime.now()); + rolePermissionMapper.insert(rolePermission); + } + + @Override + @Transactional + public boolean delete(Integer roleId, Integer permissionId) { + return rolePermissionMapper.delete(roleId, permissionId) > 0; + } + + @Override + @Transactional + public void deleteByRoleId(Integer roleId) { + rolePermissionMapper.deleteByRoleId(roleId); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java new file mode 100644 index 0000000..ff69849 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java @@ -0,0 +1,97 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicData; +import com.rczn.system.mapper.SysDicDataMapper; +import com.rczn.system.service.SysDicDataService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.List; + +@Service +public class SysDicDataServiceImpl implements SysDicDataService { + + @Autowired + private SysDicDataMapper sysDicDataMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, Integer dicId, String dicLabel, String dicValue) { + PageHelper.startPage(pageNum, pageSize); + SysDicData query = new SysDicData(); + query.setDicId(dicId); + query.setDicLabel(dicLabel); + query.setDicValue(dicValue); + return new PageInfo<>(sysDicDataMapper.selectPage(query)); + } + + /** + * 查询字典数据列表 + * + * @param dicId + * @param dicLabel + * @param dicValue + */ + @Override + public List selectList(Integer dicId, String dicLabel, String dicValue) { + SysDicData query = new SysDicData(); + query.setDicId(dicId); + query.setDicLabel(dicLabel); + query.setDicValue(dicValue); + return sysDicDataMapper.selectPage(query); + } + + @Override + public SysDicData selectById(Long id) { + return sysDicDataMapper.selectById(id); + } + + @Override + public List selectByDicId(Integer dicId) { + if (dicId == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + return sysDicDataMapper.selectByDicId(dicId); + } + + @Override + public Long insert(SysDicData sysDicData) { + // 校验必填项 + if (sysDicData.getDicId() == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + if (sysDicData.getDicLabel() == null || sysDicData.getDicLabel().trim().isEmpty()) { + throw new IllegalArgumentException("数据标签不能为空"); + } + int count = sysDicDataMapper.insert(sysDicData); + return count > 0 ? sysDicData.getId() : null; + } + + @Override + public Boolean update(SysDicData sysDicData) { + if (sysDicData.getId() == null) { + throw new IllegalArgumentException("字典数据ID不能为空"); + } + // 校验是否存在 + SysDicData exist = sysDicDataMapper.selectById(sysDicData.getId()); + if (exist == null) { + return false; + } + int count = sysDicDataMapper.update(sysDicData); + return count > 0; + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("字典数据ID不能为空"); + } + // 校验是否存在 + SysDicData exist = sysDicDataMapper.selectById(id); + if (exist == null) { + return false; + } + int count = sysDicDataMapper.deleteById(id); + return count > 0; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java new file mode 100644 index 0000000..f9b6625 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java @@ -0,0 +1,84 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicType; +import com.rczn.system.mapper.SysDicTypeMapper; +import com.rczn.system.service.SysDicTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SysDicTypeServiceImpl implements SysDicTypeService { + + @Autowired + private SysDicTypeMapper sysDicTypeMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, String dicName, String dicCode) { + PageHelper.startPage(pageNum, pageSize); + SysDicType query = new SysDicType(); + query.setDicName(dicName); + query.setDicCode(dicCode); + return new PageInfo<>(sysDicTypeMapper.selectPage(query)); + } + + /** + * 查询字典类型列表 + * + * @param dicName + * @param dicCode + */ + @Override + public List selectList(String dicName, String dicCode) { + SysDicType query = new SysDicType(); + query.setDicName(dicName); + query.setDicCode(dicCode); + return sysDicTypeMapper.selectPage(query); + } + + @Override + public SysDicType selectById(Long id) { + return sysDicTypeMapper.selectById(id); + } + + @Override + public Long insert(SysDicType sysDicType) { + // 校验必填项 + if (sysDicType.getDicName() == null || sysDicType.getDicName().trim().isEmpty()) { + throw new IllegalArgumentException("字典名称不能为空"); + } + int count = sysDicTypeMapper.insert(sysDicType); + return count > 0 ? sysDicType.getId() : null; + } + + @Override + public Boolean update(SysDicType sysDicType) { + if (sysDicType.getId() == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + // 校验是否存在 + SysDicType exist = sysDicTypeMapper.selectById(sysDicType.getId()); + if (exist == null) { + return false; + } + int count = sysDicTypeMapper.update(sysDicType); + return count > 0; + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + // 校验是否存在 + SysDicType exist = sysDicTypeMapper.selectById(id); + if (exist == null) { + return false; + } + int count = sysDicTypeMapper.deleteById(id); + return count > 0; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 0000000..22fa1a3 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,140 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import com.rczn.system.mapper.SysPermissionMapper; +import com.rczn.system.service.SysPermissionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysPermissionServiceImpl implements SysPermissionService { + + @Autowired + private SysPermissionMapper sysPermissionMapper; + + @Override + public Permission getPermissionById(Integer id) { + return sysPermissionMapper.selectPermissionById(id); + } + + @Override + public boolean addPermission(Permission permission) { + return sysPermissionMapper.insertPermission(permission) > 0; + } + + @Override + public boolean updatePermission(Permission permission) { + return sysPermissionMapper.updatePermission(permission) > 0; + } + + @Override + public boolean deletePermission(Integer id) { + return sysPermissionMapper.deletePermissionById(id) > 0; + } + + /** + * 1. 分页查询角色(多条件模糊查询) + * + * @param pageNum + * @param pageSize + * @param permissionName + * @return + */ + @Override + public PageBean selectRolePage(Integer pageNum, Integer pageSize,Integer parentId, String permissionName) { + // 1. PageHelper 设置分页参数 + PageHelper.startPage(pageNum, pageSize); + //加一层过滤: + if(parentId == 0){ + parentId = null; + } + // 2. 执行查询 + List permissionList = sysPermissionMapper.selectPermissionPage(parentId,permissionName); + // 3. 查询总条数 + Long total = sysPermissionMapper.selectTotal(parentId,permissionName); + // 4. 封装分页结果 + return new PageBean() {{ + setTotal(total); + setItems(permissionList); + }}; + } + + @Override + public List getPermissionList() { + // 1. 查询所有平级权限 + List allPermissions = sysPermissionMapper.selectPermissionList(); + + // 2. 找到顶层节点(parentId = null 或 0) + List topNodes = new ArrayList<>(); + for (Permission p : allPermissions) { + if (p.getParentId() == null || p.getParentId() == 0) { + topNodes.add(p); + } + } + + // 3. 循环给每个顶层节点设置子节点(递归) + for (Permission node : topNodes) { + node.setChildren(findChildren(node, allPermissions)); + } + + return topNodes; + } + + /*** + * 根据父ID查询权限列表 + * @param parentId + * @return + */ + @Override + public List getPermissionListByParentId(Integer parentId) { + // 1. 查询所有平级权限 + List allPermissions = sysPermissionMapper.selectPermissionList(); + + // 2. 找到顶层节点(parentId = null 或 0) + List topNodes = new ArrayList<>(); + for (Permission p : allPermissions) { + if(parentId == null || parentId == 0){ + if (p.getParentId() == null || p.getParentId() == 0) { + topNodes.add(p); + } + }else { + if (p.getParentId() == parentId) { + topNodes.add(p); + } + } + + } + + // 3. 循环给每个顶层节点设置子节点(递归) + for (Permission node : topNodes) { + node.setChildren(findChildren(node, allPermissions)); + } + + return topNodes; + } + + /** + * 递归查找子节点(最稳妥、最清晰、不会漏) + */ + private List findChildren(Permission parent, List allList) { + List children = new ArrayList<>(); + + for (Permission p : allList) { + // 子节点的 parentId == 父节点 id + if (parent.getId().equals(p.getParentId()==null?0:p.getParentId().longValue())) { + children.add(p); + // 递归给子节点设置孙子节点 + p.setChildren(findChildren(p, allList)); + } + } + + return children; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml new file mode 100644 index 0000000..ba72578 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + id, role_id, permission_id + + + + + + INSERT INTO sys_role_permission (role_id, permission_id) + VALUES (#{roleId}, #{permissionId}) + + + + DELETE FROM sys_role_permission + + + role_id = #{roleId} + + + AND permission_id = #{permissionId} + + + + + + DELETE FROM sys_role_permission + WHERE role_id = #{roleId} + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml new file mode 100644 index 0000000..2ab76dc --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml @@ -0,0 +1,74 @@ + + + + + id, create_by, create_time, update_by, update_time, del_sign, remark + + + + dic_id, dic_label, dic_value + + + + + INSERT INTO sys_dic_data ( + , + create_by, create_time, update_by, update_time, del_sign + ) VALUES ( + #{dicId}, #{dicLabel}, #{dicValue}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + + UPDATE sys_dic_data + + dic_id = #{dicId}, + dic_label = #{dicLabel}, + dic_value = #{dicValue}, + update_by = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE sys_dic_data + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml new file mode 100644 index 0000000..29f9613 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml @@ -0,0 +1,62 @@ + + + + + id, create_by, create_time, update_by, update_time, del_sign, remark + + + + dic_name, dic_code + + + + + INSERT INTO sys_dic_type ( + , + create_by, create_time, update_by, update_time, del_sign + ) VALUES ( + #{dicName}, #{dicCode}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + + UPDATE sys_dic_type + + dic_name = #{dicName}, + dic_code = #{dicCode}, + update_by = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE sys_dic_type + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml new file mode 100644 index 0000000..dfba1f9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_permission + (parent_id, permission_name, permission_code, create_id, remark, del_sign) + VALUES + (#{parentId}, #{permissionName}, #{permissionCode}, #{createId}, #{remark}, 0) + + + + + UPDATE sys_permission + SET + parent_id = #{parentId}, + permission_name = #{permissionName}, + permission_code = #{permissionCode}, + update_id = #{updateId}, + remark = #{remark} + WHERE id = #{id} + + + + + UPDATE sys_permission SET del_sign = 1 WHERE id = #{id} + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java b/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java new file mode 100644 index 0000000..aadd54c --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznAdminApplicationTests { + +// @Test + void contextLoads() { + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java new file mode 100644 index 0000000..cea8853 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java @@ -0,0 +1,28 @@ +package com.rczn.rcznautoplc.cache; + +import java.util.HashMap; +import java.util.Map; + +/** + * 1-功能岛>plc地址 + * 2-动作单元>plc地址 + * 3-参数名字>plc地址 + * 三个映射关系Map表 + */ +public class IsLandActionParamToPlc { + // 1-功能岛>plc地址:key-功能岛id,value-功能岛plc地址 + public static final Map islandToPlc = new HashMap<>(); + + // 2-动作单元>plc地址:key-动作单元id,value-动作单元plc地址 + public static final Map actionToPlc = new HashMap<>(); + + // 3-参数名字>plc地址:key-参数名字,value-参数plc地址 + public static final Map paramToPlc = new HashMap<>(); + + //4-参数id>plc地址:key-参数id,value-参数plc地址 + public static final Map paramIdToPlc = new HashMap<>(); + //更新三种数据的方法 + //获取spring里面bean + //1-功能岛>plc地址 + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java new file mode 100644 index 0000000..8478c95 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java @@ -0,0 +1,110 @@ +package com.rczn.rcznautoplc.cache; + +//样品准备状态 +public class PlcRunStatus { + //定容岛:状态属性: + public static int goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕 + + //plc系统运行状态: + public static int systemPlcRunStatus = 0; //系统准备:0-未准备,1-空闲,2-忙,4异常 + + public static int goodsCount = 0;//样品处理数量 + + public static int goodsCurrentIndex = 0;//当前样品处理索引 + + //404内照射项目默认样品:尿液,液体: + public static String defaultGoodsName = "尿液"; + + public static String defaultGoodsType = "液体"; + + //目标监测物 + public static String defaultGoalDetect = "总氮"; + + public static class PlcRunStatusResponse{ + private int goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕 + + private int systemPlcRunStatus = 0; //系统准备:0-未准备,1-空闲,2-忙,4异常 + + private int goodsCount = 0;//样品处理数量 + + private int goodsCurrentIndex = 0;//当前样品处理索引 + + private String defaultGoodsName = "尿液";//默认样品名称 + + private String defaultGoodsType = "液体";//默认样品类型 + + private String defaultGoalDetect = "总氮";//默认目标监测物 + + public PlcRunStatusResponse() { + + } + + public PlcRunStatusResponse(int goodsScanStatus, int systemPlcRunStatus, int goodsCount, int goodsCurrentIndex, String defaultGoodsName, String defaultGoodsType, String defaultGoalDetect) { + this.goodsScanStatus = goodsScanStatus; + this.systemPlcRunStatus = systemPlcRunStatus; + this.goodsCount = goodsCount; + this.goodsCurrentIndex = goodsCurrentIndex; + this.defaultGoodsName = defaultGoodsName; + this.defaultGoodsType = defaultGoodsType; + this.defaultGoalDetect = defaultGoalDetect; + } + + public int getGoodsScanStatus() { + return goodsScanStatus; + } + + public void setGoodsScanStatus(int goodsScanStatus) { + this.goodsScanStatus = goodsScanStatus; + } + + public int getSystemPlcRunStatus() { + return systemPlcRunStatus; + } + + public void setSystemPlcRunStatus(int systemPlcRunStatus) { + this.systemPlcRunStatus = systemPlcRunStatus; + } + + public int getGoodsCount() { + return goodsCount; + } + + public void setGoodsCount(int goodsCount) { + this.goodsCount = goodsCount; + } + + public int getGoodsCurrentIndex() { + return goodsCurrentIndex; + } + + public void setGoodsCurrentIndex(int goodsCurrentIndex) { + this.goodsCurrentIndex = goodsCurrentIndex; + } + + public String getDefaultGoodsName() { + return defaultGoodsName; + } + + public void setDefaultGoodsName(String defaultGoodsName) { + this.defaultGoodsName = defaultGoodsName; + } + + public String getDefaultGoodsType() { + return defaultGoodsType; + } + + public void setDefaultGoodsType(String defaultGoodsType) { + this.defaultGoodsType = defaultGoodsType; + } + + public String getDefaultGoalDetect() { + return defaultGoalDetect; + } + + public void setDefaultGoalDetect(String defaultGoalDetect) { + this.defaultGoalDetect = defaultGoalDetect; + } + } +} + + diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java new file mode 100644 index 0000000..d2425b5 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java @@ -0,0 +1,17 @@ +package com.rczn.rcznautoplc.cache; + +public class RegisterAddrDic { + + //主PLC:寄存器地址: + public final static int goodsScanRegisterArr = 5000;//样品扫描状态寄存器地址: + + //整体运转状态: + public final static int wholeRunStatusRegisterArr = 1100;//整体运转状态寄存器地址: + + //协议存储地址: + //1-下发plc:样品sop指令协议寄存器地址: + public final static int downProtcolRegisterArr = 2000;//协议存储寄存器地址: + //2-接收plc:处理样品状态数据协议寄存器地址 + public final static int upProtcolRegisterArr = 3000;//协议存储寄存器地址: + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java new file mode 100644 index 0000000..06238d6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java @@ -0,0 +1,120 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.service.ManageLogService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; + +@RestController +@RequestMapping("/manage-log") +@Tag(name = "操作日志管理", description = "操作日志增删改查+分页查询接口") +public class ManageLogController { + + @Autowired + private ManageLogService manageLogService; + + /** + * 分页查询日志 + */ + @GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "分页查询操作日志", description = "支持多条件筛选,空条件自动忽略") + @Parameters({ + @Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY), + @Parameter(name = "logName", description = "日志名称(可选,模糊查询)", required = false, example = "登录操作", in = ParameterIn.QUERY), + @Parameter(name = "logType", description = "日志类型(可选,精准查询)", required = false, example = "LOGIN", in = ParameterIn.QUERY), + @Parameter(name = "createId", description = "创建人ID(可选)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "logWritetimeStart", description = "日志开始时间(可选,格式:yyyy-MM-dd HH:mm:ss)", required = false, example = "2025-01-01 00:00:00", in = ParameterIn.QUERY), + @Parameter(name = "logWritetimeEnd", description = "日志结束时间(可选,格式:yyyy-MM-dd HH:mm:ss)", required = false, example = "2025-12-31 23:59:59", in = ParameterIn.QUERY) + }) + public Result> getLogPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String logName, + @RequestParam(required = false) String logType, + @RequestParam(required = false) Long createId, + @RequestParam(required = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime logWritetimeStart, + @RequestParam(required = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime logWritetimeEnd) { + + // 构建查询条件(空字段自动忽略) + ManageLog query = new ManageLog(); + query.setLogName(logName); + query.setLogType(logType); + query.setCreateId(createId); + // 扩展字段:用于时间范围查询(实体类无需新增字段,MyBatis 支持直接取参) + query.setStartTime(logWritetimeStart); // 实际用 logWritetimeStart,这里仅为传递参数 + query.setEndTime(logWritetimeEnd); + + PageBean pageBean = manageLogService.selectPage(pageNum, pageSize, query); + return Result.success(pageBean); + } + + /** + * 按 ID 查询日志 + */ + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个操作日志", description = "按日志ID查询详情") + public Result getLogById(@PathVariable Long id) { + ManageLog log = manageLogService.selectById(id); + return log != null ? Result.success(log) : Result.error("日志不存在或已删除"); + } + + /** + * 新增操作日志 + */ + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增操作日志", description = "日志名称、类型为必填项,其他字段可选") + public Result addLog(@RequestBody ManageLog manageLog) { + try { + Long logId = manageLogService.insert(manageLog); + return Result.success("日志新增成功"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + /** + * 更新操作日志 + */ + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "更新操作日志", description = "需传入日志ID,其他字段非空则更新") + public Result updateLog(@RequestBody ManageLog manageLog) { + try { + Boolean success = manageLogService.update(manageLog); + return success ? Result.success( "日志更新成功") : Result.error("更新失败(日志不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + /** + * 逻辑删除操作日志 + */ + @DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "删除操作日志", description = "逻辑删除(设置delSign=1,不物理删除)") + public Result deleteLog( + @PathVariable Long id, + @RequestParam(required = false) Long updateId) { + try { + Boolean success = manageLogService.deleteById(id, updateId); + return success ? Result.success("日志删除成功") : Result.error("删除失败(日志不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java new file mode 100644 index 0000000..c0a91b2 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java @@ -0,0 +1,337 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.domain.Result; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.domain.*; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; +import com.rczn.rcznautoplc.service.*; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.rczn.utils.ThreadLocalUtil; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 设备信息 Controller(RESTful API) + */ +@RestController +@RequestMapping("/plc") +@Tag(name = "plc设备控制类", description = "plc设备初始化,查询,控制方法集合") +public class PlcController { + + @Autowired + private PlcService plcService; + + /** + * 设备连接 + */ + @PostMapping(value = "/connect", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "连接设备", description = "连接设备...") + public Result plcConnect( + @ParameterObject + @Schema(description = "plc设备参数") + ModbusConnectObj connectObj) { + ModbusMaster connectorInit; + if(PlcConnectMap.modbusConnectorMap.containsKey(connectObj.getIpAddr())){ + return Result.error("设备连接已经存在!"); + } + try { + + connectorInit = plcService.connectModbus(connectObj); + if(connectorInit != null){ + return Result.success(true); + }else { + return Result.error("设备连接失败!"); + } + + } catch (Exception e) { + return Result.error("设备连接失败!"); + } + } + + /** + * 向plc寄存器写数据: + */ + @PostMapping(value = "/plcWrite", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "连接设备", description = "连接设备...") + public Result plcWrite( + @ParameterObject + @Schema(description = "plc设备参数") + ModbusConnectObj connectObj, + @Parameter + @Schema(description = "寄存器地址", required = true, example = "10000") + @RequestParam int registerAddress, + @Parameter + @Schema(description = "寄存器值", required = true, example = "12345") + @RequestParam int registerValue) { + ModbusMaster connectorInit; + if(PlcConnectMap.modbusConnectorMap.containsKey(connectObj.getIpAddr())){ + connectorInit = PlcConnectMap.modbusConnectorMap.get(connectObj.getIpAddr()); + try { + Modbus4jWriteUtils.writeHoldingRegister(connectorInit,1,registerAddress,registerValue, DataType.TWO_BYTE_INT_UNSIGNED); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + return Result.error("设备连接已经存在!"); + } + try { + connectorInit = plcService.connectModbus(connectObj); + if(connectorInit != null){ + //往地址1000里面写入数据: + Modbus4jWriteUtils.writeHoldingRegister(connectorInit,1,registerAddress,registerValue, DataType.TWO_BYTE_INT_UNSIGNED); + return Result.success(true); + }else { + return Result.error("设备连接失败!"); + } + + } catch (Exception e) { + return Result.error("设备连接失败!"); + } + } + + /** + * 根据ID删除设备(逻辑删除) + */ + @PostMapping(value = "/run") + @Operation(summary = "运行plc", description = "plc设备运行停止") + public Result runPlc( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.startPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据ID删除设备(逻辑删除) + */ + @PostMapping(value = "/pause") + @Operation(summary = "暂停运行plc", description = "暂停运行plc") + public Result pausePlc( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.pausePlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据设备ip地址,停止执行 + */ + @PostMapping(value = "/stop") + @Operation(summary = "停止plc", description = "plc设备运行停止") + public Result stop( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.stopPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,故障复位 + */ + @PostMapping(value = "/resetError") + @Operation(summary = "plc设备复位故障", description = "plc设备复位故障") + public Result resetError( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.resetErrorPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,获取plc设备状态 + */ + @GetMapping(value = "/plcStatus") + @Operation(summary = "plc设备获取状态值", description = "状态值:10-就绪,11-执行中,12-暂停中,19已停止,20-故障中") + public Result plcStatus( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Integer resultValue = plcService.getPlcStatus(ipAddr); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + + /** + * 根据plc ip地址,获取plc设备状态 + */ + @GetMapping(value = "/mastertPlcStatus") + @Operation(summary = "获取主plc状态对象", description = "goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕;//系统准备:0-未准备,1-空闲,2-忙,4异常") + public Result mastertPlcStatus() { + try { + PlcRunStatus.PlcRunStatusResponse response = new PlcRunStatus.PlcRunStatusResponse(); + response.setGoodsScanStatus(PlcRunStatus.goodsScanStatus); + response.setSystemPlcRunStatus(PlcRunStatus.systemPlcRunStatus); + response.setGoodsCount(PlcRunStatus.goodsCount); + response.setGoodsCurrentIndex(PlcRunStatus.goodsCurrentIndex); + response.setDefaultGoodsName(PlcRunStatus.defaultGoodsName); + response.setDefaultGoodsType(PlcRunStatus.defaultGoodsType); + response.setDefaultGoalDetect(PlcRunStatus.defaultGoalDetect); + + return Result.success(response); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,设置plc设备模式: + * 0-手动模式,1-自动模式 + */ + @PostMapping(value = "/setModel") + @Operation(summary = "plc设备设置模式", description = "模式值:0-手动模式,1-自动模式") + public Result setModel( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123", in = ParameterIn.QUERY) + @RequestParam String ipAddr, + @Parameter(name = "model", description = "设备模式值", required = true, example = "0-1", in = ParameterIn.QUERY) + @RequestParam Integer model) { + try { + Boolean resultValue = plcService.setPlcModel(ipAddr,model); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,获取plc设备模式: + * 0-手动模式,1-自动模式 + */ + @GetMapping(value = "/getModel") + @Operation(summary = "plc设备获取模式值", description = "模式值:0-手动模式,1-自动模式") + public Result getModel( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Integer resultValue = plcService.getPlcModel(ipAddr); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 更新设备 + */ + @GetMapping(value = "/getAll", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "获取全部plc连接对象", description = "获取全部plc连接对象") + public Result getPlcAll() { + Map connectorMap = plcService.modbusALlMap(); + return Result.success(connectorMap); + } + + /** + * 根据ID查询设备 + */ + @GetMapping(value = "/getPlcByIp", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "更加ip地址,查询plc连接对象", description = "更加ip地址,查询plc连接对象") + public Result getConnectByIpaddr( + @Parameter(name = "ipAddr", description = "设备IP", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + ModbusMaster connector = plcService.getModbusConnect(ipAddr); + return Result.success(connector); + } + + /** + * 查询所有设备(不分页) + */ + @PostMapping(value = "/doAction", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "调用plc设备执行动作", description = "根据plc设备ip,执行动作") + public Result doAction( + @RequestParam String ip, + @RequestParam String action + ) { + Boolean aBoolean = plcService.doAction(ip, action); + return Result.success(aBoolean); + } + + @Autowired + StepInfoService stepInfoService; + @Autowired + GoodsInfoService goodsInfoService; + + @Autowired + ManageLogService manageLogService; + + @PostMapping(value = "/runFlow") + @Operation(summary = "为样品执行国标" ,description = "为样品执行国标") + public Result doStandGoods( + + @RequestParam String plcIp, + @RequestParam Integer flowId, + @RequestParam List goodsIds + ){ + //根据flowId获取步骤信息表: + StepInfoQuery stepInfo = new StepInfoQuery(); + stepInfo.setFlowId(flowId); + List stepInfoList = stepInfoService.selectList(stepInfo); + //stepInfoList根据StepInfo里面的stepOrder(int)排序 + stepInfoList.sort(Comparator.comparing(StepInfo::getStepOrder)); + //根据goodsIds获取样品信息的 bar_code编码列表: + List goodsInfoList = goodsInfoService.selectByIdList(goodsIds); + List barCodeList = goodsInfoList.stream().map(GoodsInfo::getBarCode).collect(Collectors.toList()); + Boolean aBoolean = plcService.runSopInfoForGoodsList(plcIp,flowId, barCodeList, stepInfoList); + //记录操作样品执行SOP操作日志: + LocalDateTime loginTime = LocalDateTime.now(); + ManageLog info = new ManageLog(); + // ========== 修复开始 ========== + Map mapClaims = ThreadLocalUtil.get(); + UserBusy userBusy = new UserBusy(); + userBusy.setId(Long.valueOf( mapClaims.get("id").toString())); + userBusy.setUserName((String) mapClaims.get("username")); + // ========== 修复结束 ========== + info.setCreateId(userBusy.getId()); + info.setLogName("SOP操作日志"); + info.setLogType("SOP操作日志");//1:登录日志、2:SOP操作日志、3:基础数据操作日志 + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("用户名:").append(userBusy.getUserName()).append(",SOP执行操作时间:").append(loginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setLogContent(stringBuilder.toString()); + info.setCreateTime(loginTime); + manageLogService.insert(info); + + return Result.success(aBoolean); + } + + +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java new file mode 100644 index 0000000..6682c86 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java @@ -0,0 +1,23 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.websocket.WebSocketServer; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/websocket") +@Tag(name = "websocket", description = "websocket接口") +public class WebSocketController { + + @Autowired + private WebSocketServer webSocketServer; + + @RequestMapping("/send/{message}") + public String send(@PathVariable("message") String message){ + webSocketServer.onMessage(message,null); + return "success"; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java new file mode 100644 index 0000000..4b5462e --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java @@ -0,0 +1,65 @@ +package com.rczn.rcznautoplc.domain; + + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + +public class ManageLog extends BaseBean { + private String logName; + + private String logType; + + private LocalDateTime logWritetime; + + private String logContent; + + public ManageLog() { + } + + public ManageLog(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + @Override + public String toString() { + return "ManageLog{" + + "logName='" + logName + '\'' + + ", logType='" + logType + '\'' + + ", logWritetime=" + logWritetime + + ", logContent='" + logContent + '\'' + + '}'; + } + + public String getLogName() { + return logName; + } + + public void setLogName(String logName) { + this.logName = logName; + } + + public String getLogType() { + return logType; + } + + public void setLogType(String logType) { + this.logType = logType; + } + + public LocalDateTime getLogWritetime() { + return logWritetime; + } + + public void setLogWritetime(LocalDateTime logWritetime) { + this.logWritetime = logWritetime; + } + + public String getLogContent() { + return logContent; + } + + public void setLogContent(String logContent) { + this.logContent = logContent; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java new file mode 100644 index 0000000..9091a67 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java @@ -0,0 +1,85 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.github.s7connector.api.S7Connector; +import com.serotonin.modbus4j.ModbusMaster; + +public class ModbusConnectObj { + + /** + * ip地址 + */ + private String ipAddr; + + /** + * 端口号 + */ + private Integer port; + + /** + * 机架号 + */ + private Integer rack; + + /** + * 插槽 + */ + private Integer slot; + + /** + * 是否是主机 + */ + private Boolean host; + + + public ModbusConnectObj(String ipAddr, Integer port, Integer rack, Integer slot,Boolean host) { + this.ipAddr = ipAddr; + this.port = port; + this.rack = rack; + this.slot = slot; + this.host = host; + } + + public ModbusConnectObj() { + } + + public String getIpAddr() { + return ipAddr; + } + + public void setIpAddr(String ipAddr) { + this.ipAddr = ipAddr; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public Integer getRack() { + return rack; + } + + public void setRack(Integer rack) { + this.rack = rack; + } + + public Integer getSlot() { + return slot; + } + + public void setSlot(Integer slot) { + this.slot = slot; + } + + public Boolean getHost() { + return host; + } + + public void setHost(Boolean host) { + this.host = host; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java new file mode 100644 index 0000000..48db0a6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java @@ -0,0 +1,84 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.github.s7connector.api.S7Connector; + +public class PlcConnectObj { + + /** + * ip地址 + */ + private String ipAddr; + + /** + * 端口号 + */ + private Integer port; + + /** + * 机架号 + */ + private Integer rack; + + /** + * 插槽 + */ + private Integer slot; + + /** + * 连接对象 + */ + @JsonBackReference + private S7Connector connector; + + public PlcConnectObj(String ipAddr, Integer port, Integer rack, Integer slot, S7Connector connector) { + this.ipAddr = ipAddr; + this.port = port; + this.rack = rack; + this.slot = slot; + this.connector = connector; + } + + public PlcConnectObj() { + } + + public String getIpAddr() { + return ipAddr; + } + + public void setIpAddr(String ipAddr) { + this.ipAddr = ipAddr; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public Integer getRack() { + return rack; + } + + public void setRack(Integer rack) { + this.rack = rack; + } + + public Integer getSlot() { + return slot; + } + + public void setSlot(Integer slot) { + this.slot = slot; + } + + public S7Connector getConnector() { + return connector; + } + + public void setConnector(S7Connector connector) { + this.connector = connector; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java new file mode 100644 index 0000000..2b67731 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java @@ -0,0 +1,111 @@ +package com.rczn.rcznautoplc.domain; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + +public class UserBusy extends BaseBean { + + private Long id; + private String userName; + + private String password; + + private String salt; + + private String nicke; + + private Boolean sex; // 0-女, 1-男 + + private String emailAddr; + + private String address; + + + public UserBusy() { + } + + public UserBusy(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", password='" + password + '\'' + + ", salt='" + salt + '\'' + + ", nicke='" + nicke + '\'' + + ", sex=" + sex + + ", emailAddr='" + emailAddr + '\'' + + ", address='" + address + '\'' + + '}'; + } + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public String getNicke() { + return nicke; + } + + public void setNicke(String nicke) { + this.nicke = nicke; + } + + public Boolean getSex() { + return sex; + } + + public void setSex(Boolean sex) { + this.sex = sex; + } + + public String getEmailAddr() { + return emailAddr; + } + + public void setEmailAddr(String emailAddr) { + this.emailAddr = emailAddr; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java new file mode 100644 index 0000000..aa74bc1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java @@ -0,0 +1,122 @@ +package com.rczn.rcznautoplc.domain.query; + +public class DevInfoQuery { + + //功能岛外键 + private Integer islandId; + + //设备名称 + private String devName; + + //设备型号 + private String devModel; + + //plc映射地址 + private Integer plcAddr; + + //设备IP地址 + private String ipAddr; + + private Integer port; + + private String protocolType; + + private String company; + + private Integer status; // 0-空闲,1-运行,4-故障 + + private Integer runModel;//0-手动模式,1-自动模式 + + private String devDesc; + + public DevInfoQuery() { + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public String getDevName() { + return devName; + } + + public void setDevName(String devName) { + this.devName = devName; + } + + public String getDevModel() { + return devModel; + } + + public void setDevModel(String devModel) { + this.devModel = devModel; + } + + public Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + public String getIpAddr() { + return ipAddr; + } + + public void setIpAddr(String ipAddr) { + this.ipAddr = ipAddr; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getProtocolType() { + return protocolType; + } + + public void setProtocolType(String protocolType) { + this.protocolType = protocolType; + } + + public String getCompany() { + return company; + } + + public void setCompany(String company) { + this.company = company; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getRunModel() { + return runModel; + } + + public void setRunModel(Integer runModel) { + this.runModel = runModel; + } + + public String getDevDesc() { + return devDesc; + } + + public void setDevDesc(String devDesc) { + this.devDesc = devDesc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java new file mode 100644 index 0000000..a1b4e14 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java @@ -0,0 +1,87 @@ +package com.rczn.rcznautoplc.domain.query; + +public class DevParamQuery { + private String devIds; + + private Integer devId; + + private String paramName; + + private String paramValue; + + private String paramTypeData; + + private String paramUnit; + + private String formType; + + private String paramDesc; + + public DevParamQuery() { + } + + public Integer getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + public String getDevIds() { + return devIds; + } + + public void setDevIds(String devIds) { + this.devIds = devIds; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getParamTypeData() { + return paramTypeData; + } + + public void setParamTypeData(String paramTypeData) { + this.paramTypeData = paramTypeData; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public String getParamDesc() { + return paramDesc; + } + + public void setParamDesc(String paramDesc) { + this.paramDesc = paramDesc; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java new file mode 100644 index 0000000..7e667d7 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java @@ -0,0 +1,75 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.FlowInfo; +import com.rczn.rcznautoplc.domain.IslandInfo; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class GoodsFlowStatusQuery { + private Integer goodsId; + + private Integer flowId; + + private Integer islandId; + + private Integer devId; + + private Integer flowSort; + + private Integer status; // 0-未执行,1-执行,10-通过,11-失败 + + public GoodsFlowStatusQuery() { + } + + + public Integer getGoodsId() { + return goodsId; + } + + public void setGoodsId(Integer goodsId) { + this.goodsId = goodsId; + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getFlowSort() { + return flowSort; + } + + public void setFlowSort(Integer flowSort) { + this.flowSort = flowSort; + } + + public Integer getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java new file mode 100644 index 0000000..cc523d1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java @@ -0,0 +1,125 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + + +public class GoodsInfoQuery extends BaseBean{ + private String goodsName; + + private String goodsType; + + private LocalDateTime incomeTime; + + private String goodFrom; + + private Integer goodBatch; + + private Integer pointNum; + + //目标监测物 + private String goalDetect; + + //条码 + private String barCode; + + //国标id + private Integer flowId; + + private Integer goodsStatus; + + private String desc; + + public GoodsInfoQuery() { + } + + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public String getGoodsType() { + return goodsType; + } + + public void setGoodsType(String goodsType) { + this.goodsType = goodsType; + } + + public LocalDateTime getIncomeTime() { + return incomeTime; + } + + public void setIncomeTime(LocalDateTime incomeTime) { + this.incomeTime = incomeTime; + } + + public String getGoodFrom() { + return goodFrom; + } + + public void setGoodFrom(String goodFrom) { + this.goodFrom = goodFrom; + } + + public Integer getGoodBatch() { + return goodBatch; + } + + public void setGoodBatch(Integer goodBatch) { + this.goodBatch = goodBatch; + } + + public Integer getPointNum() { + return pointNum; + } + + public void setPointNum(Integer pointNum) { + this.pointNum = pointNum; + } + + public String getGoalDetect() { + return goalDetect; + } + + public void setGoalDetect(String goalDetect) { + this.goalDetect = goalDetect; + } + + public String getBarCode() { + return barCode; + } + + public void setBarCode(String barCode) { + this.barCode = barCode; + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + public Integer getGoodsStatus() { + return goodsStatus; + } + + public void setGoodsStatus(Integer goodsStatus) { + this.goodsStatus = goodsStatus; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java new file mode 100644 index 0000000..34d9e1b --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java @@ -0,0 +1,60 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; + + +public class IslandInfoQuery { + private String islandName; + + private String islandCode; + + //plc映射地址 + private Integer plcAddr; + + private String islandLogo; + + private String desc; + + public IslandInfoQuery() { + } + + public String getIslandName() { + return islandName; + } + + public void setIslandName(String islandName) { + this.islandName = islandName; + } + + public String getIslandCode() { + return islandCode; + } + + public void setIslandCode(String islandCode) { + this.islandCode = islandCode; + } + + public Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + public String getIslandLogo() { + return islandLogo; + } + + public void setIslandLogo(String islandLogo) { + this.islandLogo = islandLogo; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java new file mode 100644 index 0000000..6920b16 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java @@ -0,0 +1,84 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.IslandInfo; + +import java.time.LocalDateTime; + +public class IslandParamQuery { + private Integer islandId; + + private Integer stepId; + + private String paramName; + + private String paramType; + + private String paramUnit; + + private String paramValue; + + private String formType; + + public IslandParamQuery() { + } + + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepId() { + return stepId; + } + + public void setStepId(Integer stepId) { + this.stepId = stepId; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java new file mode 100644 index 0000000..164dcba --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java @@ -0,0 +1,118 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.IslandInfo; + +import java.time.LocalDateTime; + +public class StepInfoQuery { + private Integer islandId; + + //设备id + private Integer devId; + private Integer flowId; + + private String paramName; + private String paramType; + private String paramUnit; + private String paramValue; + private String formType; + + private Integer stepOrder; + private String stepName; + + private String stepDesc; + + public StepInfoQuery() { + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + public Integer getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepOrder() { + return stepOrder; + } + + public void setStepOrder(Integer stepOrder) { + this.stepOrder = stepOrder; + } + + public String getStepName() { + return stepName; + } + + public void setStepName(String stepName) { + this.stepName = stepName; + } + + public String getStepDesc() { + return stepDesc; + } + + public void setStepDesc(String stepDesc) { + this.stepDesc = stepDesc; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java new file mode 100644 index 0000000..1300631 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java @@ -0,0 +1,27 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.ManageLog; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper // 标记为 MyBatis Mapper 接口,确保被 Spring 扫描 +public interface ManageLogMapper { + // 新增日志(支持空字段,空字段用数据库默认值) + int insert(ManageLog manageLog); + + // 逻辑删除日志(按 ID,设置 delSign=1) + int deleteById(Long id); + + // 更新日志(仅更新非空字段,空字段不更新) + int update(ManageLog manageLog); + + // 按 ID 查询日志(仅查未删除数据) + ManageLog selectById(Long id); + + // 分页查询日志(支持按字段筛选,空字段忽略条件) + List selectPage(ManageLog manageLog); + + // 查询分页总数(与分页查询条件一致) + Long selectTotal(ManageLog manageLog); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java new file mode 100644 index 0000000..7302508 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java @@ -0,0 +1,21 @@ +package com.rczn.rcznautoplc.service; + +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.ManageLog; + +public interface ManageLogService { + // 新增日志 + Long insert(ManageLog manageLog); + + // 逻辑删除日志 + Boolean deleteById(Long id, Long updateId); + + // 更新日志(仅更新非空字段) + Boolean update(ManageLog manageLog); + + // 按 ID 查询日志 + ManageLog selectById(Long id); + + // 分页查询日志(支持多条件筛选) + PageBean selectPage(Integer pageNum, Integer pageSize, ManageLog manageLog); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java new file mode 100644 index 0000000..e6d1bde --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java @@ -0,0 +1,125 @@ +package com.rczn.rcznautoplc.service; + +import com.github.s7connector.api.S7Connector; +import com.rczn.rcznautoplc.domain.ModbusConnectObj; +import com.rczn.rcznautoplc.domain.PlcConnectObj; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; + +import java.util.List; +import java.util.Map; + +public interface PlcService { + /** + * 连接plc设备 + * @param connectObj- + * @return + */ + PlcConnectObj connect(PlcConnectObj connectObj); + + /** + * 连接modbus设备 + * @param connectObj- + * @return + */ + ModbusMaster connectModbus(ModbusConnectObj connectObj) throws ModbusInitException, ModbusTransportException; + + /** + * 启动plc设备 + * @param ipAddr- + * @return + */ + Boolean startPlc(String ipAddr); + + /** + * plc设备暂停运行 + * @param ipAddr- + * @return + */ + Boolean pausePlc(String ipAddr); + + /** + * plc设备故障复位 + * @param ipAddr- + * @return + */ + Boolean resetErrorPlc(String ipAddr); + + /** + * 根据ip地址获取plc设备状态值 + * 0-未连接,1-连接,11-执行,12-暂停,19暂停,20-故障复位 + * @param ipAddr + * @return + */ + Integer getPlcStatus(String ipAddr); + + /** + * 根据ip地址设置plc设备模式 + * 0-手动,1-自动 + * @param ipAddr + * @return + */ + Boolean setPlcModel(String ipAddr,Integer modelValue); + + /** + * 根据ip地址获取plc设备模式值 + * 0-手动,1-自动 + * @param ipAddr + * @return + */ + Integer getPlcModel(String ipAddr); + + /** + * 根据ip地址获取modbus连接设备 + * + * @param ipAddr + * @return + */ + public ModbusMaster getModbusConnect(String ipAddr); + + /** + * 根据ip地址获取plc设备 + * @param ipAddr + * @return + */ + S7Connector getPlc(String ipAddr); + + /** + * 获取全部plc连接对象 + * @return + */ + Map plcALlMap(); + + /** + * 获取全部plc连接对象 + * + * @return + */ + public Map modbusALlMap(); + /** + * 执行plc动作 + * @param ipAddr + * @param action + * @return + */ + Boolean doAction(String ipAddr,String action); + + /** + * 停止plc运行: + * @param ipAddr + * @return + */ + Boolean stopPlc(String ipAddr); + + /** + * 执行sop信息 + * @param sopId + * @param barCodeList + * @param stepInfoList + * @return + */ + Boolean runSopInfoForGoodsList(String plcIp, Integer sopId, List barCodeList,List stepInfoList); +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java new file mode 100644 index 0000000..da73bba --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java @@ -0,0 +1,85 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.mapper.ManageLogMapper; +import com.rczn.rcznautoplc.service.ManageLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +public class ManageLogServiceImpl implements ManageLogService { + + @Autowired + private ManageLogMapper manageLogMapper; + + @Override + public Long insert(ManageLog manageLog) { + // 校验必填字段(日志名称和类型为必填) + Assert.notNull(manageLog.getLogName(), "日志名称不能为空"); + Assert.notNull(manageLog.getLogType(), "日志类型不能为空"); + + //补充日志时间 + if (manageLog.getLogWritetime() == null) { + manageLog.setLogWritetime(LocalDateTime.now()); + } +// TODO 补充日志创建人信息 +// manageLog.setCreateId(null); + manageLog.setCreateTime(LocalDateTime.now()); + int rows = manageLogMapper.insert(manageLog); + return rows > 0 ? manageLog.getId() : null; + } + + @Override + public Boolean deleteById(Long id, Long updateId) { + Assert.notNull(id, "日志ID不能为空"); + int rows = manageLogMapper.deleteById(id); + return rows > 0; + } + + @Override + public Boolean update(ManageLog manageLog) { + Assert.notNull(manageLog.getId(), "日志ID不能为空"); + //如果更新时间为空,则自动更新 + if (manageLog.getUpdateTime() == null) { + manageLog.setUpdateTime(LocalDateTime.now()); + } +// TODO 补充日志更新人信息 + // manageLog.setUpdateId(null); + int rows = manageLogMapper.update(manageLog); + return rows > 0; + } + + @Override + public ManageLog selectById(Long id) { + Assert.notNull(id, "日志ID不能为空"); + return manageLogMapper.selectById(id); + } + + @Override + public PageBean selectPage(Integer pageNum, Integer pageSize, ManageLog manageLog) { + // 校验分页参数 + Assert.notNull(pageNum, "页码不能为空"); + Assert.notNull(pageSize, "每页条数不能为空"); + Assert.isTrue(pageNum > 0, "页码必须大于0"); + Assert.isTrue(pageSize > 0 && pageSize <= 100000, "每页条数必须在1-10000之间"); + + // PageHelper 分页(自动拦截查询,添加 LIMIT 条件) + PageHelper.startPage(pageNum, pageSize); + List logList = manageLogMapper.selectPage(manageLog); + Page page = (Page) logList; + + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(page.getTotal()); + pageBean.setItems(page.getResult()); + + // 封装PageBean返回 + return pageBean; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java new file mode 100644 index 0000000..da7d539 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java @@ -0,0 +1,499 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.rczn.ModbusCmdConst; +import com.rczn.modbus.Modbus4jUtils; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.plc_common.S7ConnectorPLC; +import com.rczn.rcznautoplc.cache.IsLandActionParamToPlc; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.cache.RegisterAddrDic; +import com.rczn.rcznautoplc.domain.*; +import com.rczn.rcznautoplc.domain.query.DevInfoQuery; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; +import com.rczn.rcznautoplc.domain.query.IslandInfoQuery; +import com.rczn.rcznautoplc.service.DevInfoService; +import com.rczn.rcznautoplc.service.DevParamService; +import com.rczn.rcznautoplc.service.IslandInfoService; +import com.rczn.rcznautoplc.service.PlcService; +import com.rczn.rcznautoplc.utils.PlcCommonProtcolUtil; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.ByteBuffer; +import java.nio.ShortBuffer; +import java.util.*; + + +@Service +public class PlcServiceImpl implements PlcService { + + // 核心:创建log对象(private static final,名称固定为log) + private static final Logger log = LoggerFactory.getLogger(PlcServiceImpl.class); + // Log log = LogFactory.getLog(PlcServiceImpl.class); + /** + * 连接plc设备 + * + * @param connectObj - + * @return + */ + @Override + public PlcConnectObj connect(PlcConnectObj connectObj) { + S7ConnectorPLC plc = new S7ConnectorPLC(); +// S7Connector connector = plc.initConnect(connectObj.getIpAddr(), connectObj.getPort(), connectObj.getRack(), connectObj.getSlot()); + S7Connector connector = S7ConnectorFactory.buildTCPConnector().build(); + + connectObj.setConnector(connector); + PlcConnectMap.plcConnectorMap.put(connectObj.getIpAddr(),connector); + return connectObj; + } + + /** + * 连接modbus设备 + * + * @param connectObj - + * @return + */ + @Override + public ModbusMaster connectModbus(ModbusConnectObj connectObj) throws ModbusInitException, ModbusTransportException { + //初始化modbus连接对象 + ModbusMaster modbusMaster = Modbus4jUtils.getAndTestMaster(connectObj.getIpAddr(), connectObj.getPort()); + //以ip地址为键值保存连接对象modbusMaster + PlcConnectMap.modbusConnectorMap.put(connectObj.getIpAddr(),modbusMaster); + if(connectObj.getHost()){ + PlcConnectMap.masterModbusConnector = modbusMaster; + } + return modbusMaster; + } + + + /** + * 启动plc设备 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean startPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); + +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_run); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + + return false; + } + + /** + * plc设备暂停运行 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean pausePlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_pause); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * plc设备故障复位 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean resetErrorPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_ready); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 根据ip地址获取plc设备状态值 + * 0-未连接,1-连接,10-就绪,11-执行,12-暂停,19暂停,20-故障复位 + * + * @param ipAddr + * @return + */ + @Override + public Integer getPlcStatus(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Number number = Modbus4jUtils.readHoldingRegister(modbusMaster, 1, 1, DataType.TWO_BYTE_INT_UNSIGNED); + return number.intValue(); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return -1; + } + + /** + * 根据ip地址设置plc设备模式 + * 0-手动,1-自动 + * + * @param ipAddr + * @param modelValue + * @return + */ + @Override + public Boolean setPlcModel(String ipAddr, Integer modelValue) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,0,(short) modelValue.intValue()); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 根据ip地址获取plc设备模式值 + * 0-手动,1-自动 + * + * @param ipAddr + * @return + */ + @Override + public Integer getPlcModel(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Number number = Modbus4jUtils.readHoldingRegister(modbusMaster, 1, 0, DataType.TWO_BYTE_INT_UNSIGNED); + if(number.intValue() != 0 && number.intValue()!=1){ + number = 0; + } + return number.intValue(); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return -1; + } + + /** + * 根据ip地址获取plc设备 + * + * @param ipAddr + * @return + */ + @Override + public S7Connector getPlc(String ipAddr) { + return PlcConnectMap.plcConnectorMap.get(ipAddr); + } + + /** + * 根据ip地址获取modbus连接设备 + * + * @param ipAddr + * @return + */ + @Override + public ModbusMaster getModbusConnect(String ipAddr) { + return PlcConnectMap.modbusConnectorMap.get(ipAddr); + } + + /** + * 获取全部plc连接对象 + * + * @return + */ + @Override + public Map plcALlMap() { + return PlcConnectMap.plcConnectorMap; + } + + /** + * 获取全部plc连接对象 + * + * @return + */ + @Override + public Map modbusALlMap() { + return PlcConnectMap.modbusConnectorMap; + } + + /** + * 执行plc动作 + * + * @param ipAddr + * @param action + * @return + */ + @Override + public Boolean doAction(String ipAddr, String action) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = new byte[5]; +// connector.write(DaveArea.DB,1,1,cmdBytes); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_run); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 停止plc运行: + * + * @param ipAddr + * @return + */ + @Override + public Boolean stopPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = new byte[5]; +// connector.write(DaveArea.DB,1,1,cmdBytes); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_stop); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + @Autowired + IslandInfoService islandInfoService; + @Autowired + DevInfoService devInfoService; + @Autowired + DevParamService devParamService; + /** + * 执行sop信息 + * + * @param sopId + * @param barCodeList + * @param stepInfoList + * @return + */ + @Override + public Boolean runSopInfoForGoodsList(String plcIp,Integer sopId, List barCodeList, List stepInfoList) { + // 1. 空值校验:提前拦截null,避免线程内空指针 + if (barCodeList == null || barCodeList.isEmpty() || stepInfoList == null || stepInfoList.isEmpty()) { + log.warn("样品编码列表或步骤信息列表为空,无需执行PLC动作"); + return false; + } + //更新一次功能岛、动作单元、参数对应plc映射地址缓存: + List islandInfos = islandInfoService.selectList(new IslandInfoQuery()); + IsLandActionParamToPlc.islandToPlc.clear(); + + for (int i = 0; i < islandInfos.size(); i++) { + IslandInfo islandInfo = islandInfos.get(i); + IsLandActionParamToPlc.islandToPlc.put(islandInfo.getId().intValue(),islandInfo.getPlcAddr()); + } + List devInfos = devInfoService.getDevInfoList(new DevInfoQuery()); + IsLandActionParamToPlc.actionToPlc.clear(); + + for (int i = 0; i < devInfos.size(); i++) { + DevInfo devInfo = devInfos.get(i); + IsLandActionParamToPlc.actionToPlc.put(devInfo.getId().intValue(),devInfo.getPlcAddr()); + } + + List devParams = devParamService.selectList(new DevParamQuery()); + IsLandActionParamToPlc.paramToPlc.clear(); + IsLandActionParamToPlc.paramIdToPlc.clear(); + + for (int i = 0; i < devParams.size(); i++) { + DevParam devParam = devParams.get(i); + IsLandActionParamToPlc.paramToPlc.put(devParam.getParamName(),devParam.getPlcAddr()); + IsLandActionParamToPlc.paramIdToPlc.put(devParam.getId().intValue(),devParam.getPlcAddr()); + } + + //为stepInfoList排序,根据StepInfo的step_order(int)字段 + stepInfoList.sort(Comparator.comparingInt(StepInfo::getStepOrder)); + + // 2. 深拷贝集合:避免线程共享导致的并发修改问题 + List barCodeListCopy = new ArrayList<>(barCodeList); + List stepInfoListCopy = new ArrayList<>(stepInfoList); + // 若StepInfo是自定义对象,需保证深拷贝(如果是浅拷贝,对象属性仍会共享) + // stepInfoListCopy = stepInfoList.stream().map(step -> 深拷贝StepInfo).collect(Collectors.toList()); + + // 3. 启动线程执行分组逻辑 + new Thread(() -> { + try { + runSopInfoForGroup(plcIp,sopId,barCodeListCopy, stepInfoListCopy); + } catch (Exception e) { + // 4. 捕获线程内异常:避免线程静默失败 + log.error("执行PLC分组任务失败", e); + } + }, "Sop-PLC-Thread-" + sopId).start(); // 给线程命名,便于日志排查 + + return true; + } + + private void runSopInfoForGroup(String plcIp,Integer sopId,List barCodeList, List stepInfoList) throws InterruptedException { + //更新:plc状态中的当前处理样品数量: + PlcRunStatus.goodsCount = barCodeList.size(); + PlcRunStatus.goodsCurrentIndex = 0; + // 5. 实现8个一组的分组逻辑(核心业务补充) + int groupSize = 8; + for (int i = 0; i < barCodeList.size(); i += groupSize) { + // 截取8个一组的子列表(最后一组可能不足8个) + int end = Math.min(i + groupSize, barCodeList.size()); + List subBarCodeList = barCodeList.subList(i, end); + + //先判断PLC状态: + while (true){ + if(PlcRunStatus.systemPlcRunStatus == 1){ + // 按分组执行PLC动作(核心业务逻辑) + executePlcActionByGroup(plcIp,sopId,subBarCodeList, stepInfoList); + //更新样品处理数量索引: + PlcRunStatus.goodsCurrentIndex += subBarCodeList.size(); + break; + } + } + + //暂停2.2秒,获取状态 + Thread.sleep(2200); + //获取PLC整体状态: + while (true){ + if(PlcRunStatus.systemPlcRunStatus == 1){ + //如果空闲 + break; + } + } + + } + } + + // 补充:按分组执行PLC动作的核心方法 + private void executePlcActionByGroup(String plcIp,Integer sopId,List subBarCodeList, List stepInfoList) { + // 根据样品编码获取PLC设备 + // 根据步骤信息执行PLC动作 + log.info("执行PLC分组任务,当前分组样品编码:{}", subBarCodeList); + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(plcIp); + if(modbusMaster!=null){ + int startAddr = RegisterAddrDic.downProtcolRegisterArr; + //获取样品+sop序列协议 + List sopProtcol = PlcCommonProtcolUtil.getSopProtcol(sopId, subBarCodeList, stepInfoList); + //将协议写入PLC + ByteBuffer sopBuff = ByteBuffer.allocate(sopProtcol.size()); + for (byte b1: + sopProtcol) { + sopBuff.put(b1); + } + ShortBuffer sopBuffShort = sopBuff.asShortBuffer(); + try { + Modbus4jWriteUtils.writeRegisters(modbusMaster,1,startAddr, sopBuffShort.array()); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + }else { + throw new RuntimeException("未找到对应的modbusMaster"); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java new file mode 100644 index 0000000..3082848 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java @@ -0,0 +1,159 @@ +package com.rczn.rcznautoplc.task; + +import com.rczn.modbus.Modbus4jUtils; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.rcznautoplc.cache.RegisterAddrDic; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.service.GoodsFlowStatusService; +import com.rczn.rcznautoplc.service.GoodsInfoService; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.utils.PlcCommonProtcolUtil; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Component +public class PlcTask { + Log log = LogFactory.getLog(PlcTask.class); + + //样品状态service + @Autowired + GoodsFlowStatusService goodsFlowStatusService; + + //定时任务,每2秒执行一次:Cron 表达式支持 6 位(秒 分 时 日 月 周)或 7 位(秒 分 时 日 月 周 年) + @Scheduled(cron = "0/2 * * * * ?") + public void statusMonitor() throws ModbusInitException, ModbusTransportException, ErrorResponseException { + log.info("plc 设备状态监控."); + //判断是否有plc连接设备, + if(PlcConnectMap.masterModbusConnector != null ){ + log.info("plc 主设备状态监控开始..."); + //遍历连接对象 + ModbusMaster connector = PlcConnectMap.masterModbusConnector; + //1-读取功能岛状态: + //1-1:sop中第一个功能岛,定容岛>10000(十进制):样品是否扫描完毕-0-1:0-未扫描完毕,1-扫描完毕 + Number scanReadyStatusNum = Modbus4jUtils.readHoldingRegister(connector, 1, 5000, DataType.TWO_BYTE_INT_UNSIGNED); + PlcRunStatus.goodsScanStatus = scanReadyStatusNum.intValue(); + + //判断如果扫描完成,获取样品编码数据,保存数据库,修改plc寄存器状态值和修改索引状态: + if(PlcRunStatus.goodsScanStatus == 1){ + getGoodsInfoFromPlc( connector, PlcRunStatus.goodsScanStatus); + } + //查看plc的状态返回寄存器:(开头:cc cc-有返回状态数据) + Number goodsStatusStart = Modbus4jUtils.readHoldingRegister(connector, 1, RegisterAddrDic.upProtcolRegisterArr, DataType.TWO_BYTE_INT_UNSIGNED); + if(goodsStatusStart.intValue() == 0xcccc){ + //2-读取状态数据长度值 + Number goodsStatusLength = Modbus4jUtils.readHoldingRegister(connector, 1, RegisterAddrDic.upProtcolRegisterArr+1, DataType.TWO_BYTE_INT_UNSIGNED); + //3-读取状态数据 + Number[] goodsStatusArr = Modbus4jUtils.readHoldingRegisters(connector, 1, RegisterAddrDic.upProtcolRegisterArr, goodsStatusLength.intValue()/2+4, DataType.TWO_BYTE_INT_UNSIGNED); + //4-解析样品状态数据:把number数组数据转正List + List goodsStatusByteList = new ArrayList<>(); + for (Number goodsStatusNum:goodsStatusArr + ) { + goodsStatusByteList.add((byte) (goodsStatusNum.intValue()>>8)); + goodsStatusByteList.add((byte) (goodsStatusNum.intValue()&0xff)); + } + List list = PlcCommonProtcolUtil.pareseProtcolStatus(goodsStatusByteList); + //5-插入数据库样品状态: + for (GoodsFlowStatus goodsFlowStatus:list + ) { + goodsFlowStatusService.insert(goodsFlowStatus); + } + + //6-清空寄存器数据: + Modbus4jWriteUtils.writeRegisters(connector,1,RegisterAddrDic.upProtcolRegisterArr, new short[goodsStatusLength.intValue()/2+4]); + } + + + //2-读取整个系统sop执行后状态:0-未准备,1-空闲,2-忙,4-异常 + Number sopRunStatus = Modbus4jUtils.readHoldingRegister(connector, 1, 5500, DataType.TWO_BYTE_INT_UNSIGNED); + PlcRunStatus.systemPlcRunStatus = sopRunStatus.intValue(); + + }else { + log.info("plc 主设备未连接."); + } + } + + @Autowired + GoodsInfoService goodsInfoService; + + //任务:样品编码扫描完毕,读取 + /** + * 异步执行样品信息读取(单独线程) + * @Async("plcAsyncExecutor") 指定使用自定义的PLC专用线程池 + */ + @Async("plcAsyncExecutor") + public void getGoodsInfoFromPlc(ModbusMaster connector,int goodsScanStatus) { + try { + log.info("异步读取样品信息开始,线程名:" + Thread.currentThread().getName()); + //10001-10032:32个槽位放置样品: + //一个寄存器返回两个字节:是两个样品索引地址: + Number[] goodsIndexStatus = Modbus4jUtils.readHoldingRegisters(connector,1, 5001,16,DataType.TWO_BYTE_INT_UNSIGNED); + List goodsIndexNumList = new ArrayList<>(); + for (Number goodsIndexNum:goodsIndexStatus + ) { + //一个寄存器返回值分成两个样品状态值: + int registerStatus = goodsIndexNum.intValue(); + goodsIndexNumList.add(registerStatus>>8); + goodsIndexNumList.add(registerStatus&0xff); + } + +// List goodsInfoList = new ArrayList<>(); + //当前时间: + LocalDateTime localDateTime = LocalDateTime.now(); + //样品编码地址:10033-10048;10049-10063; + for (int i = 0; i < goodsIndexNumList.size(); i++) { + int goodsIndexNum = goodsIndexNumList.get(i); + if (goodsIndexNum == 1) { + Number[] goodsCodeNumTemp = Modbus4jUtils.readHoldingRegisters(connector, 1, 10018 + i * 16,16, DataType.TWO_BYTE_INT_UNSIGNED); + StringBuilder goodCodeNumStr = new StringBuilder(); + for (Number goodsIndexNumTemp:goodsCodeNumTemp){ + goodCodeNumStr.append(goodsIndexNumTemp.intValue()>>8); + goodCodeNumStr.append(goodsIndexNumTemp.intValue()&0xff); + } + GoodsInfo goodsInfo = new GoodsInfo(); + goodsInfo.setBarCode(goodCodeNumStr.toString()); + goodsInfo.setPointNum(i+1); + goodsInfo.setGoodsName(PlcRunStatus.defaultGoodsName); + goodsInfo.setGoodsType(PlcRunStatus.defaultGoodsType); + goodsInfo.setGoalDetect(PlcRunStatus.defaultGoalDetect); + goodsInfo.setIncomeTime(localDateTime); + goodsInfo.setCreateTime(LocalDateTime.now()); + +// goodsInfoList.add(goodsInfo); + //获取的样品对象,保存到数据库, + goodsInfoService.insert(goodsInfo); + log.info("样品编码:" + goodCodeNumStr.toString() + ",样品索引:" + goodsIndexNum); + } + } + + //修改寄存器样品索引值: + //10001-10032:16个寄存器,每个寄存器两个样品状态值,修改样品索引值为:0 + short[] goodsRegisterValues = new short[16]; + Modbus4jWriteUtils.writeRegisters(connector,1, 10001,goodsRegisterValues); + //修改10000寄存器的值为:0 + Modbus4jWriteUtils.writeHoldingRegister(connector,1, 10000,0,DataType.TWO_BYTE_INT_UNSIGNED); + + // 此处可添加:保存数据到数据库、修改寄存器状态等业务逻辑 + log.info("异步读取样品信息完成"); + + } catch (ModbusInitException | ModbusTransportException | ErrorResponseException e) { + // 捕获异步线程中的异常并记录日志(异步方法异常不会自动抛出到主线程) + log.error("异步读取样品信息失败", e); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java new file mode 100644 index 0000000..3e382c8 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java @@ -0,0 +1,282 @@ +package com.rczn.rcznautoplc.utils; + +import com.rczn.rcznautoplc.cache.IsLandActionParamToPlc; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import com.rczn.rcznautoplc.service.GoodsInfoService; +import com.rczn.utils.BeanFactoryUtils; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.*; + +public class PlcCommonProtcolUtil { +// 样品SOP执行指令 开始字节(2) 总字节长度(2) SOP id号(4) 样品数量(1) 样品地址(16) 样品地址(16) 样品地址(16) ... 功能岛PLC(2) 动作PLC地址(2) 参数PLC地址(2) 参数值(2) ... 结束码 +// CC CC 0011 11223344 16 0 1 2 AA+01 BB+01 CC+01 0011 EEEE + public static List getSopProtcol(Integer sopId,List subBarCodeList, List stepInfoList) { + List protcolByteList = new ArrayList<>(); + + Byte[] startByte = {(byte) 0xcc,(byte) 0xcc}; + for (int i = 0; i < startByte.length; i++) { + protcolByteList.add(startByte[i]); + } + + //后面修正数据 + byte[] dataLength = new byte[2]; + for (int i = 0; i < dataLength.length; i++) { + protcolByteList.add(dataLength[i]); + } + + // sop id + byte[] sopIdByte = new byte[4]; + sopIdByte[0] = (byte) (sopId >> 24); + sopIdByte[1] = (byte) (sopId >> 16); + sopIdByte[2] = (byte) (sopId >> 8); + sopIdByte[3] = (byte) sopId.intValue(); + for (int i = 0; i < sopIdByte.length; i++) { + protcolByteList.add(sopIdByte[i]); + } + + //样品数量 + byte sampleNum = (byte) subBarCodeList.size(); + protcolByteList.add(sampleNum); + + //把样品地址写入协议字符串列表 + for (int i = 0; i < subBarCodeList.size(); i++) { + String subBarCode = subBarCodeList.get(i); + //subBarCode是一系列数字字符串,转成16个10进制数字(需要兼容subBarCode长度超过或少于16的情况) + byte[] sampleAddress = new byte[16]; + for (int j = 0; j < subBarCode.length() && j < sampleAddress.length; j++) { + sampleAddress[j] = (byte) Integer.parseInt(subBarCode.substring(j, j + 1)); + } + + for (int j = 0; j < sampleAddress.length; j++) { + protcolByteList.add(sampleAddress[j]); + } + } + //stepInfoList列表按照StepInfo对象里面的Integer islandId属性 + // 属性里面有stepOrder,计算出有多少个连续的不同islandId属性值 + //第一个stepInfo的islandId + StepInfo stepInfo_0 = stepInfoList.get(0); + // 1-第一个功能岛plc + Integer islandPlcIntV = IsLandActionParamToPlc.islandToPlc.get(stepInfo_0.getIslandId()); + byte[] islandPlc_0 = new byte[2]; + islandPlc_0[0] = (byte) 0xaa; + islandPlc_0[1] = (byte) islandPlcIntV.intValue(); + + for (int i = 0; i < islandPlc_0.length; i++) { + protcolByteList.add(islandPlc_0[i]); + } + //第一个动作单元plc + Integer actionPlcIntV = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_0 = new byte[2]; + actionPlc_0[0] = (byte) 0xbb; + actionPlc_0[1] = (byte) actionPlcIntV.intValue(); + for (int i = 0; i < actionPlc_0.length; i++) { + protcolByteList.add(actionPlc_0[i]); + } + //第一个参数单元plc + Integer paramPlcIntV = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_0 = new byte[2]; + paramPlc_0[0] = (byte) 0xcc; + paramPlc_0[1] = (byte) paramPlcIntV.intValue(); + for (int i = 0; i < paramPlc_0.length; i++) { + protcolByteList.add(paramPlc_0[i]); + } + //第一个参数值 + int paramValueInt = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_0 = new byte[2]; + paramValue_0[0] = (byte) (paramValueInt>>8); + paramValue_0[1] = (byte) paramValueInt; + + for (int i = 0; i < paramValue_0.length; i++) { + protcolByteList.add(paramValue_0[i]); + } + + for (int i = 1; i < stepInfoList.size(); i++) { + // isLandId:1 order:1 => isLandId:1 order:2 => isLandId:2 order:3 => isLandId:2 order:4 => isLandId:3 order:5 + StepInfo stepInfo = stepInfoList.get(i); + //判断是否更换功能岛 + if (stepInfo.getIslandId() != stepInfo_0.getIslandId()) { + // 1-第一个功能岛plc + Integer islandPlcIntV_1 = IsLandActionParamToPlc.islandToPlc.get(stepInfo_0.getIslandId()); + byte[] islandPlc_1 = new byte[2]; + islandPlc_1[0] = (byte) 0xaa; + islandPlc_1[1] = (byte) islandPlcIntV_1.intValue(); + + for (int j = 0; j < islandPlc_1.length; j++) { + protcolByteList.add(islandPlc_1[j]); + } + + //第一个动作单元plc + Integer actionPlcIntV_1 = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_1 = new byte[2]; + actionPlc_1[0] = (byte) 0xbb; + actionPlc_1[1] = (byte) actionPlcIntV_1.intValue(); + for (int j = 0; j < actionPlc_1.length; j++) { + protcolByteList.add(actionPlc_1[j]); + } + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + + + }else if(stepInfo.getDevId()!= stepInfo_0.getDevId()){ + //判断是否更换动作单元 + //第一个动作单元plc + Integer actionPlcIntV_1 = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_1 = new byte[2]; + actionPlc_1[0] = (byte) 0xbb; + actionPlc_1[1] = (byte) actionPlcIntV_1.intValue(); + for (int j = 0; j < actionPlc_1.length; j++) { + protcolByteList.add(actionPlc_1[j]); + } + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + }else { + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + } + stepInfo_0 = stepInfo; + } + + int dataLengthInt = protcolByteList.size(); + protcolByteList.set(2, (byte) (dataLengthInt>>8)); + protcolByteList.set(3, (byte) dataLengthInt); + + byte[] endByte = {(byte) 0xee, (byte) 0xee}; + protcolByteList.add(endByte[0]); + protcolByteList.add(endByte[1]); + + return protcolByteList; + } + + +// 样品处理状态返回指令 开始字节(2) 总字节长度(2) SOP id号(4) 样品数量(4) 样品地址(4) 功能岛PLC(1) 动作PLC地址(1) 参数PLC地址(1) 检测值(2) 样品地址(4) 功能岛PLC(1) 动作PLC地址(1) 参数PLC地址(1) 检测值(2) ... crc校验 结束码 +// CCCC 0011 11223344 16 0 1 1 1 0011 1 1 1 1 0011 XX EEEE + public static List pareseProtcolStatus(List protcolByteList) { + //获取样品数据,整理处理Map对象,key:bar_code,value:goodsId + GoodsInfoService goodsInfoService = BeanFactoryUtils.getBean(GoodsInfoService.class); + List goodsInfoList = goodsInfoService.selectList(new GoodsInfoQuery()); + Map goodsInfoCodeIDMap = new HashMap<>(); + for (GoodsInfo goodsInfo : goodsInfoList) { + goodsInfoCodeIDMap.put(goodsInfo.getBarCode(), goodsInfo.getId()); + } + + List goodsFlowStatusList = new ArrayList<>(); + + //sop id值: + StringBuilder sopIdSb = new StringBuilder(); + for (int i = 0; i < 4; i++) { + Byte sopByte = protcolByteList.get(3 + i); + sopIdSb.append(sopByte.intValue()); + } + Integer sopId = Integer.parseInt(sopIdSb.toString()); + + byte goodsCount = protcolByteList.get(7); + for (int i = 0; i < goodsCount; i++) { + //样品扫描编码地址 + StringBuilder goodsAddressSb = new StringBuilder(); + for (int j = 0; j < 16; j++){ + Byte addByte = protcolByteList.get(8 + i * 16 + j); + goodsAddressSb.append(addByte.intValue()); + } + //功能岛PLC地址 + byte isLandPlc = protcolByteList.get(8 + (i+1) * 16); + //动作单元plc地址 + byte actionPlc = protcolByteList.get(8 + (i+1) * 16 + 1); + //参数plc地址 + byte paramPlc = protcolByteList.get(8 + (i+1) * 16 + 2); + //检测值 + byte[] checkValue = new byte[2]; + for (int j = 0; j < checkValue.length; j++) { + checkValue[j] = protcolByteList.get(8 + (i+1) * 16 + 3 + j); + } + + int checkValueInt = ByteBuffer.wrap(checkValue).order(ByteOrder.LITTLE_ENDIAN).getShort(); + + GoodsFlowStatus flowStatus = new GoodsFlowStatus(); + Long goodsId = goodsInfoCodeIDMap.get(goodsAddressSb.toString()); + flowStatus.setGoodsId(goodsId.intValue()); + flowStatus.setFlowId(sopId); + for (Integer isLandId : + IsLandActionParamToPlc.islandToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.islandToPlc.get(isLandId); + if (plcValue == isLandPlc) { + flowStatus.setIslandId(isLandId); + break; + } + } + for (Integer actionId : + IsLandActionParamToPlc.actionToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.actionToPlc.get(actionId); + if (plcValue == actionPlc) { + flowStatus.setDevId(actionId); + break; + } + } + + for (Integer paramId: + IsLandActionParamToPlc.paramIdToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.paramIdToPlc.get(paramId); + if (plcValue == paramPlc) { + flowStatus.setFlowSort(paramId); + break; + } + } + + flowStatus.setStatus(checkValueInt); + + //保存样品状态数据: + goodsFlowStatusList.add(flowStatus); + } + + return goodsFlowStatusList; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java new file mode 100644 index 0000000..605cd98 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java @@ -0,0 +1,24 @@ +package com.rczn.rcznautoplc.utils; + +import com.github.s7connector.api.S7Connector; +import com.rczn.rcznautoplc.domain.DevInfo; +import com.serotonin.modbus4j.ModbusMaster; + +import java.util.HashMap; +import java.util.Map; + +public class PlcConnectMap { + + //PLC设备map对象:key:ip,value:设备 + public static Map plcDevMap = new HashMap<>(); + + //plc连接对象缓存: + public static Map plcConnectorMap = new HashMap<>(); + + //Modbus连接对象缓存: + public static Map modbusConnectorMap = new HashMap<>(); + + //主plc modbus连接对象: + public static ModbusMaster masterModbusConnector = null; + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml new file mode 100644 index 0000000..fbfd66a --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml @@ -0,0 +1,175 @@ + + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + log_name, log_type, log_writetime, log_content + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_manage_log ( + + + log_name, + log_type, + log_writetime, + log_content, + + create_id, + create_time, + update_id, + update_time, + del_sign, + remark, + + ) VALUES ( + + + #{logName}, + #{logType}, + #{logWritetime}, + #{logContent}, + + #{createId}, + #{createTime}, + #{updateId}, + #{updateTime}, + #{delSign}, + #{remark}, + + ) + + + + + UPDATE sys_manage_log + + + log_name = #{logName}, + log_type = #{logType}, + log_writetime = #{logWritetime}, + log_content = #{logContent}, + + update_id = #{updateId}, + remark = #{remark}, + del_sign = #{delSign}, + + update_time = NOW() + + + WHERE id = #{id} + AND del_sign = 0 + + + + + UPDATE sys_manage_log + SET + del_sign = 1, + update_time = NOW(), + update_id = #{updateId} + WHERE id = #{id} + AND del_sign = 0 + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java b/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java new file mode 100644 index 0000000..d230135 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn.rcznautoplc; + +import org.testng.annotations.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznAutoplcApplicationTests { + +// @Test + void contextLoads() { + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java new file mode 100644 index 0000000..f27034e --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java @@ -0,0 +1,23 @@ +package com.rczn; + +/** + * modbus 指令常量enum + */ +public class ModbusCmdConst { + //下面是指令值: + //就绪 + public static final int plc_ready = 10; + //运行 + public static final int plc_run = 11; + //暂停 + public static final int plc_pause = 12; + //停止 + public static final int plc_stop = 10; + //故障复位 + public static final int plc_reset_error = 20; + //修改模式 + public static final int plc_set_model = 0; + //参数读取: + public static final int plc_read_param = 18; + // +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java new file mode 100644 index 0000000..870604d --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java @@ -0,0 +1,40 @@ +package com.rczn.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 异步线程池配置(用于PLC数据读取的异步执行) + */ +@Configuration +@EnableAsync //开启异步任务 +public class AsyncThreadPoolConfig { + + /** + * 定义PLC专用线程池 + */ + @Bean(name = "plcAsyncExecutor") + public Executor plcAsyncExecutor(){ + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + // 核心线程数(根据业务调整) + executor.setCorePoolSize(5); + // 最大线程数 + executor.setMaxPoolSize(10); + // 队列容量 + executor.setQueueCapacity(20); + // 线程名前缀(便于日志排查) + executor.setThreadNamePrefix("PLC-Async-"); + // 线程空闲超时时间 + executor.setKeepAliveSeconds(60); + // 拒绝策略:队列满时由调用线程处理(避免任务丢失) + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 初始化线程池 + executor.initialize(); + return executor; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java new file mode 100644 index 0000000..abeba08 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java @@ -0,0 +1,14 @@ +package com.rczn.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +@Configuration +public class WebSocketConfig { + + @Bean + public ServerEndpointExporter serverEndpointExporter(){ + return new ServerEndpointExporter(); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java new file mode 100644 index 0000000..15f9a19 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java @@ -0,0 +1,16 @@ +package com.rczn.exception; + +import com.rczn.domain.Result; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalException { + + @ExceptionHandler(Exception.class) + public Result handleException(Exception e){ + e.printStackTrace(); + return Result.error(StringUtils.hasLength(e.getMessage())? e.getMessage() : "系统异常"); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java new file mode 100644 index 0000000..8af87df --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java @@ -0,0 +1,380 @@ +package com.rczn.modbus; + +import com.serotonin.modbus4j.BatchRead; +import com.serotonin.modbus4j.BatchResults; +import com.serotonin.modbus4j.ModbusFactory; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.serotonin.modbus4j.locator.BaseLocator; +import com.serotonin.modbus4j.msg.ReadInputRegistersResponse; + +import java.util.Map; + +/** + * modbus通讯工具类,采用modbus4j实现 + * + * @author lxq + * @dependencies modbus4j-3.0.3.jar + * @website https://github.com/infiniteautomation/modbus4j + */ +public class Modbus4jUtils { + /** + * 工厂。 + */ + static ModbusFactory modbusFactory; + static { + if (modbusFactory == null) { + modbusFactory = new ModbusFactory(); + } + } + + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster() throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost("localhost"); + params.setPort(502); + + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.setTimeout(3000); + master.setRetries(1); + master.init(); + + return master; + } + + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster(String ipAddr,Integer port) throws ModbusInitException { + IpParameters params = new IpParameters(); +// params.setHost("localhost"); + params.setHost(ipAddr); +// params.setPort(502); + params.setPort(port); + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.setTimeout(3000); + master.setRetries(1); + master.init(); + + return master; + } + + /** + * 获取和测试Master对象 + * @param ip + * @param port + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getAndTestMaster(String ip, Integer port) + throws ModbusInitException { + + ModbusMaster master = getMaster(ip, port); + + try { + // 随便读一个确定存在的寄存器 + BaseLocator locator = + BaseLocator.holdingRegister(1, 0, DataType.TWO_BYTE_INT_SIGNED); + + Number value = master.getValue(locator);// ⭐ 真正触发 TCP 连接 + System.out.println("value:"+value); + } catch (Exception e) { + master.destroy(); + throw new RuntimeException("PLC 连接失败:" + ip + ":" + port, e); + } + + return master; + } + + /** + * 读取[01 Coil Status 0x]类型 开关数据 + * + * @param slaveId + * slaveId + * @param offset + * 位置 + * @return 读取值 + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Boolean readCoilStatus(ModbusMaster modbusMaster,int slaveId, int offset) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 01 Coil Status + BaseLocator loc = BaseLocator.coilStatus(slaveId, offset); + Boolean value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[02 Input Status 1x]类型 开关数据 + * + * @param slaveId + * @param offset + * @return + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static Boolean readInputStatus(ModbusMaster modbusMaster,int slaveId, int offset) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 02 Input Status + BaseLocator loc = BaseLocator.inputStatus(slaveId, offset); + Boolean value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[03 Holding Register类型 2x]模拟量数据 + * + * @param slaveId + * slave Id + * @param offset + * 位置 + * @param dataType + * 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Number readHoldingRegister(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 03 Holding Register类型数据读取 + BaseLocator loc = BaseLocator.holdingRegister(slaveId, offset, dataType); + Number value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[04 Input Registers 3x]类型 模拟量数据 + * + * @param modbusMaster + * modbusMaster modbus连接对象 + * @param slaveId + * slaveId 设备号 + * @param offset + * 位置 + * @param dataType + * 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return 返回结果 + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Number readInputRegisters(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 04 Input Registers类型数据读取 + BaseLocator loc = BaseLocator.inputRegister(slaveId, offset, dataType); + Number value = modbusMaster.getValue(loc); + return value; + } + + /** + * 批量读取使用方法 + * + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static BatchResults batchRead(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { + + BatchRead batch = new BatchRead(); + + batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT)); + batch.addLocator(1, BaseLocator.inputStatus(1, 0)); + + batch.setContiguousRequests(false); + BatchResults results = modbusMaster.send(batch); + System.out.println(results.getValue(0)); + System.out.println(results.getValue(1)); + return results; + } + + /** + * 连续读取多个 Holding Register + */ + public static Number[] readHoldingRegisters( + ModbusMaster master, + int slaveId, + int startOffset, + int count, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + Number[] values = new Number[count]; + + for (int i = 0; i < count; i++) { + BaseLocator locator = + BaseLocator.holdingRegister(slaveId, startOffset + i, dataType); + + values[i] = master.getValue(locator); + } + + return values; + } + + /** + * 连续读取多个 Input Register + */ + public static Number[] readInputRegistersBatch( + ModbusMaster master, + int slaveId, + int startOffset, + int count, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + Number[] values = new Number[count]; + + for (int i = 0; i < count; i++) { + BaseLocator locator = + BaseLocator.inputRegister(slaveId, startOffset + i, dataType); + + values[i] = master.getValue(locator); + } + + return values; + } + + /** + * 批量读取多个 Holding Register(高性能) + */ + public static BatchResults batchReadHoldingRegisters( + ModbusMaster master, + int slaveId, + int[] offsets, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + BatchRead batch = new BatchRead<>(); + + for (int i = 0; i < offsets.length; i++) { + batch.addLocator(i, + BaseLocator.holdingRegister(slaveId, offsets[i], dataType)); + } + + batch.setContiguousRequests(true); // 连续优化 + return master.send(batch); + } + + /** + * 混合批量读取 + */ + public static BatchResults batchReadMixed( + ModbusMaster master, + int slaveId) + throws ModbusTransportException, ErrorResponseException { + + BatchRead batch = new BatchRead<>(); + + batch.addLocator(0, + BaseLocator.holdingRegister(slaveId, 0, DataType.FOUR_BYTE_FLOAT)); + + batch.addLocator(1, + BaseLocator.holdingRegister(slaveId, 2, DataType.TWO_BYTE_INT_SIGNED)); + + batch.addLocator(2, + BaseLocator.coilStatus(slaveId, 0)); + + batch.setContiguousRequests(false); + + return master.send(batch); + } + + + public static void close(ModbusMaster master) { + if (master != null) { + master.destroy(); + } + } + + public static void main(String[] args) { + try { + ModbusMaster master = getMaster("192.178.111.123", 501); + + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + /** + * 测试 + * + * @param args + */ + public static void main1(String[] args) { + try { + ModbusMaster modbusMaster = getMaster(); + // 01测试 +// Boolean v011 = readCoilStatus(modbusMaster,1, 0); +// Boolean v012 = readCoilStatus(modbusMaster,1, 1); +// Boolean v013 = readCoilStatus(modbusMaster,1, 6); +// System.out.println("v011:" + v011); +// System.out.println("v012:" + v012); +// System.out.println("v013:" + v013); +// // 02测试 +// Boolean v021 = readInputStatus(modbusMaster,1, 0); +// Boolean v022 = readInputStatus(modbusMaster,1, 1); +// Boolean v023 = readInputStatus(modbusMaster,1, 2); +// System.out.println("v021:" + v021); +// System.out.println("v022:" + v022); +// System.out.println("v023:" + v023); +// +// // 03测试 +// Number v031 = readHoldingRegister(modbusMaster,1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float +// Number v032 = readHoldingRegister(modbusMaster,1, 3, DataType.FOUR_BYTE_FLOAT);// 同上 +// System.out.println("v031:" + v031); +// System.out.println("v032:" + v032); + + // 04测试 +// Number v041 = readInputRegisters(modbusMaster,1, 0, DataType.FOUR_BYTE_FLOAT);// + Number v041 = readInputRegisters(modbusMaster,1, 0, DataType.FOUR_BYTE_INT_UNSIGNED);// + Number v042 = readInputRegisters(modbusMaster,1, 2, DataType.FOUR_BYTE_FLOAT);// + System.out.println("v041:" + v041); + System.out.println("v042:" + v042); + + Number vff = readHoldingRegister(modbusMaster,1,0,DataType.TWO_BYTE_INT_SIGNED); + System.out.println("vff:" + vff); + Number vff2 = readHoldingRegister(modbusMaster,1,2,DataType.TWO_BYTE_INT_SIGNED); + System.out.println("vff2:" + vff2); + // 批量读取 +// batchRead(); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java new file mode 100644 index 0000000..ff16e21 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java @@ -0,0 +1,247 @@ +package com.rczn.modbus; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.serotonin.modbus4j.ModbusFactory; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.serotonin.modbus4j.locator.BaseLocator; +import com.serotonin.modbus4j.msg.ModbusResponse; +import com.serotonin.modbus4j.msg.WriteCoilRequest; +import com.serotonin.modbus4j.msg.WriteCoilResponse; +import com.serotonin.modbus4j.msg.WriteCoilsRequest; +import com.serotonin.modbus4j.msg.WriteCoilsResponse; +import com.serotonin.modbus4j.msg.WriteRegisterRequest; +import com.serotonin.modbus4j.msg.WriteRegisterResponse; +import com.serotonin.modbus4j.msg.WriteRegistersRequest; + +/** + * modbus4j写入数据 + * + * @author xq + * + */ +public class Modbus4jWriteUtils { + static Log log = LogFactory.getLog(Modbus4jWriteUtils.class); + /** + * 工厂。 + */ + static ModbusFactory modbusFactory; + static { + if (modbusFactory == null) { + modbusFactory = new ModbusFactory(); + } + } + + /** + * 获取tcpMaster + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster() throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost("localhost"); + params.setPort(502); + + ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false); + tcpMaster.init(); + + return tcpMaster; + } + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster(String ipAddr,Integer port) throws ModbusInitException { + IpParameters params = new IpParameters(); +// params.setHost("localhost"); + params.setHost(ipAddr); +// params.setPort(502); + params.setPort(port); + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.init(); + + return master; + } + + /** + * 写 [01 Coil Status(0x)]写一个 function ID = 5 + * + * @param slaveId + * slave的ID + * @param writeOffset + * 位置 + * @param writeValue + * 值 + * @return 是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeCoil(ModbusMaster tcpMaster,int slaveId, int writeOffset, boolean writeValue) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求 + WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); + // 发送请求并获取响应对象 + WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); + if (response.isException()) { + return false; + } else { + return true; + } + } + + /** + * 写[01 Coil Status(0x)] 写多个 function ID = 15 + * + * @param slaveId + * slaveId + * @param startOffset + * 开始位置 + * @param bdata + * 写入的数据 + * @return 是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeCoils(ModbusMaster tcpMaster,int slaveId, int startOffset, boolean[] bdata) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求 + WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); + // 发送请求并获取响应对象 + WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); + if (response.isException()) { + return false; + } else { + return true; + } + + } + + /*** + * 写[03 Holding Register(4x)] 写一个 function ID = 6 + * + * @param slaveId + * @param writeOffset + * @param writeValue + * @return + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeRegister(ModbusMaster tcpMaster,int slaveId, int writeOffset, short writeValue) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求对象 + WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); + WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); + if (response.isException()) { + log.error(response.getExceptionMessage()); + return false; + } else { + return true; + } + + } + + /** + * + * 写入[03 Holding Register(4x)]写多个 function ID=16 + * + * @param slaveId + * modbus的slaveID + * @param startOffset + * 起始位置偏移量值 + * @param sdata + * 写入的数据 + * @return 返回是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeRegisters(ModbusMaster tcpMaster,int slaveId, int startOffset, short[] sdata) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求对象 + WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); + // 发送请求并获取响应对象 + ModbusResponse response = tcpMaster.send(request); + if (response.isException()) { + log.error(response.getExceptionMessage()); + return false; + } else { + return true; + } + } + + /** + * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) + * + * @param slaveId + * @param offset + * @param value + * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long + * @param dataType + * ,com.serotonin.modbus4j.code.DataType + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static void writeHoldingRegister(ModbusMaster tcpMaster,int slaveId, int offset, Number value, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 类型 + BaseLocator locator = BaseLocator.holdingRegister(slaveId, offset, dataType); + tcpMaster.setValue(locator, value); + } + + public static void main1(String[] args) { + try { + ModbusMaster modbusMaster = getMaster(); + //@formatter:off + // 测试01 +// boolean t01 = writeCoil(1, 0, true); +// System.out.println("T01:" + t01); + + // 测试02 +// boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); +// System.out.println("T02:" + t02); + + // 测试03 +// short v = -3; +// boolean t03 = writeRegister(1, 0, v); +// System.out.println("T03:" + t03); + // 测试04 +// boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); +// System.out.println("t04:" + t04); + + writeRegister(modbusMaster,1,2,(short) 3); + //写模拟量 + writeHoldingRegister(modbusMaster,1,0, 999, DataType.TWO_BYTE_INT_SIGNED); + + //@formatter:on + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java new file mode 100644 index 0000000..a5056e0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java @@ -0,0 +1,56 @@ +package com.rczn.plc; + + +import com.github.s7connector.api.annotation.S7Variable; +import com.github.s7connector.impl.utils.S7Type; +import lombok.Data; + +@Data +public class PLCData { + + /** + * type是这个点位在PLC中设置的类型,源码会解析其长度; + * byteOffset对应PLC偏移量中的整数部分; + * bitOffset指偏移量的小数部分,bitOffset指第几个bit. + * byteOffset和bitOffset 也可理解为返回的byte[]中第byteOffset到bitOffset + */ + @S7Variable(type= S7Type.BOOL,byteOffset = 0,bitOffset = 0) + public Boolean data10;//bool型的值不要用private + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 1) + public Boolean data11; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 2) + public Boolean data12; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 3) + public Boolean data13; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 4) + public Boolean data14; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 5) + public Boolean data15; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 6) + public Boolean data16; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 7) + public Boolean data17; + + @S7Variable(type=S7Type.BYTE,byteOffset = 1,bitOffset = 0) + public Byte dataB1; + + @S7Variable(type=S7Type.STRING,byteOffset = 2,bitOffset = 0) + public String dataS1; + + @S7Variable(type=S7Type.STRING,byteOffset = 258,bitOffset = 40) + public String dataS2; + + @S7Variable(type=S7Type.STRING,byteOffset = 514,bitOffset = 40) + public String dataS3; + + @S7Variable(type=S7Type.STRING,byteOffset = 770) + public String dataS4; + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java new file mode 100644 index 0000000..f583fad --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java @@ -0,0 +1,102 @@ +package com.rczn.plc; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.impl.serializer.converter.StringConverter; + +import java.util.Scanner; + + +/** + * @author 木春 + * @className S7PlcClient.java + * @Form no + * @Description ToDo + * @createTime 2022 年 11 月 18 日 21 21:40:49 + **/ +public class S7PlcClient { + public static void main(String[] args) throws InterruptedException { + + //初始化 创建一个链接对象 + S7Connector connector = + S7ConnectorFactory + .buildTCPConnector() + .withHost("192.168.0.105") // + .withRack(0) //架机号 可选 + .withSlot(1) //插槽号 可选 + .build(); + +// 写数据线程 + new Thread(new Runnable() { + @Override + public void run() { + java_write_plc(connector);//写数据 + } + }).start(); + +// 读数据线程 + new Thread(new Runnable() { + @Override + public void run() { + java_read_plc(connector);//调用读取数据方法 + } + }).start(); + + } + + //读取数据 + public static void java_read_plc(S7Connector connector) { + /* 读取数据方法*/ + byte[] PlcData = null; + String str = null; + String str1 = null; + StringConverter converter = null; + String extract1 = null; + //循环读取 + while (true) { + PlcData = connector.read( + DaveArea.DB, //选择区块 + 1, // 区块编号 + 255, //长度 + 260); //偏移地址 + + converter = new StringConverter();//字符串转换 + + //将读取到的数据转换成字符串类型 读取到的数据转换后 + extract1 = converter.extract(String.class, PlcData, 0, 0); + //比对两次数据是否一样 不一样就打印 + if (!(extract1.equals(str1))) { + System.out.println(" "); + System.out.println("接收plc的数据为 = " + extract1); + str1 = extract1; + //plc发送 qu 就结束退出程序 + if (extract1.equals("qu")) { + break; + } + } + } + } + + //发送数据 + public static void java_write_plc(S7Connector connector) { + while (true) { + /*发送数据*/ + String data = null; +// byte[] bytes = null; + String input = null; + Scanner sc = new Scanner(System.in); + System.out.print("请输入要发送的数据: "); + input = sc.nextLine(); + + String data_Baotou = " ";//数据包头 两个空格 + String data_tail = " ";//包尾 六个空格 + data = data_Baotou + input + data_tail;//发送的数据 + byte[] bytes = new byte[input.length()]; + bytes = data.getBytes();//转字节 + System.out.println("发送的字节长度 = " + bytes.length);//发送的字节长度 + connector.write(DaveArea.DB, 1, 4, bytes);//写入到 DB1 偏移量为4的变量 + System.out.println("发送的数据为 = " + data); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java new file mode 100644 index 0000000..35460dd --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java @@ -0,0 +1,131 @@ +package com.rczn.plc; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.S7Serializer; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.api.factory.S7SerializerFactory; + +import java.io.IOException; + +public class S7PlcCommun { + + + /** + * 初始化PLC连接 + */ + public S7Connector initConnect(){ + //PLC地址 + String ipAddress = "192.168.1.2"; + //默认端口 + Integer port = 102; + S7Connector s7Connector = S7ConnectorFactory + .buildTCPConnector() + .withHost(ipAddress) + .withPort(port) + .withTimeout(10000) //连接超时时间 + .withRack(0) + .withSlot(1) + .build(); + S7Serializer s7Serializer2L = S7SerializerFactory.buildSerializer(s7Connector); + return s7Connector; + + } + + /** + * 读取PLC中的数据 + * + **/ + public void readPlcData() { + + S7Connector s7Connector = initConnect(); + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB地址,若plc中是DB1000,则填1000 + //第三个参数:数据长度, <=plc中两个偏移量的间隔,当前偏移量为1000,下一个地址偏移量为1100,则长度可填 0-1000; + //第四个参数:偏移量 + byte[] barcodeByte = s7Connector.read(DaveArea.DB, 1000, 2, 0); + //由于当前PLC地址中保存的数据类型是字符串类型,所以直接将byte[] 转成string即可; + String barcode =byteToHex(barcodeByte); + System.out.println(barcode); + try { + s7Connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * byte数组转hex + * @param bytes + * @return + */ + public static String byteToHex(byte[] bytes){ + String strHex = ""; + StringBuilder sb = new StringBuilder(""); + for (int n = 0; n < bytes.length; n++) { + strHex = Integer.toHexString(bytes[n] & 0xFF); + sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0 + } + return sb.toString().trim(); + } + + /** + * 向PLC中写数据 + * + **/ + public void writePlcData() { + + S7Connector s7Connector = initConnect(); + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[],由于plc中地址的数据类型是word,所以写入的数据必须是4位的16进制数据 + s7Connector.write(DaveArea.DB,1000, 4,hexStringToBytes("0001")); + + try { + s7Connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 将16进制字符串转成二进制数组 + * @param hexString + * @return + */ + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + /** + * 将单个16进制字符转换为对应的字节值(核心补充方法) + * @param c 16进制字符(0-9、A-F) + * @return 对应的字节值(0-15) + */ + private static byte charToByte(char c) { + // 0-9 对应 48-57 + if (c >= '0' && c <= '9') { + return (byte) (c - '0'); + } + // A-F 对应 65-70 + else if (c >= 'A' && c <= 'F') { + return (byte) (c - 'A' + 10); + } + // 非法字符抛出异常(避免静默错误) + else { + throw new IllegalArgumentException("非法的16进制字符:" + c); + } + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java new file mode 100644 index 0000000..bf51222 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java @@ -0,0 +1,220 @@ +package com.rczn.plc_common; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.impl.serializer.converter.BitConverter; +import com.github.s7connector.impl.serializer.converter.IntegerConverter; +import com.github.s7connector.impl.serializer.converter.RealConverter; +import com.github.s7connector.impl.serializer.converter.StringConverter; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class S7ConnectorPLC { + public S7Connector initConnect(String ipAddress,int port,int rack,int slot) { + //默认端口 +// 创建与PLC的链接 + S7Connector connector = S7ConnectorFactory.buildTCPConnector() + .withHost(ipAddress) + .withPort(port) + .withRack(0) // 架机号 可选,建议选择,可能会报错 + .withSlot(2) // 插槽号 可选,建议选择,可能会报错 + .build(); + return connector; + } + + public static void main1(String[] args) { + S7ConnectorPLC s7ConnectorPLC = new S7ConnectorPLC(); + S7Connector connector = s7ConnectorPLC.initConnect("192.168.110.123", 102, 0, 2); +// s7ConnectorPLC.Java_To_write(connector); + s7ConnectorPLC.Cyclic_readT(connector); + } + + //Int类型的封装类 用来转义 + private static IntegerConverter intCon = new IntegerConverter(); + //String... + private static StringConverter strCon = new StringConverter(); + //Boolean... + private static BitConverter boolCon = new BitConverter(); + //real实数浮点... + private static RealConverter realCon = new RealConverter(); + + //获取到的数据存储 + public boolean in_bool = false;//bool + public Integer in_int = null;//int + public String in_String = "";//string + public double in_real = 0.0;//real + + public void Cyclic_read(S7Connector connector) { + + byte[] PlcData = null; + //读取bool型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 1, // 数据值长度 boolean长度1 + 0); // 开始位置偏移量 + Boolean extract_bool = boolCon.extract(Boolean.class, PlcData, 0, 0);//接收转换的数值 + in_bool = extract_bool;//赋值给全局变量 + +// 读取整型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 2, // 数据值长度 int长度2 + 2); // 开始位置 偏移量 + Integer extract_int = intCon.extract(Integer.class, PlcData, 0, 0); + in_int = extract_int; + +// 读取字符串型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 16, // 数据值长度 String最小3 随值长度增加 + 4); // 开始位置偏移量 + String extract_string = strCon.extract(String.class, PlcData, 0, 0); + in_String = extract_string; + +// 读取小数型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 4, // 数据值长度 double长度4 + 260); //偏移量 + Double num1 = realCon.extract(Double.class, PlcData, 0, 0); + /* BigDecimal bd1 = new BigDecimal(num1); + System.out.println("转换real浮点= " + bd1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());*/ + in_real = num1; + + try { + connector.close();//关闭链接 + } catch (IOException e) { + e.printStackTrace(); + } + + } + public void Cyclic_readT(S7Connector connector) { + + byte[] PlcData = null; + //读取bool型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 1, // 数据值长度 boolean长度1 + 0); // 开始位置偏移量 + Boolean extract_bool = boolCon.extract(Boolean.class, PlcData, 0, 0);//接收转换的数值 + in_bool = extract_bool;//赋值给全局变量 + +// 读取整型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 2, // 数据值长度 int长度2 + 2); // 开始位置 偏移量 + Integer extract_int = intCon.extract(Integer.class, PlcData, 0, 0); + in_int = extract_int; + +// 读取字符串型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 16, // 数据值长度 String最小3 随值长度增加 + 4); // 开始位置偏移量 + String extract_string = strCon.extract(String.class, PlcData, 0, 0); + in_String = extract_string; + +// 读取小数型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 4, // 数据值长度 double长度4 + 260); //偏移量 + Double num1 = realCon.extract(Double.class, PlcData, 0, 0); + /* BigDecimal bd1 = new BigDecimal(num1); + System.out.println("转换real浮点= " + bd1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());*/ + in_real = num1; + + try { + connector.close();//关闭链接 + } catch (IOException e) { + e.printStackTrace(); + } + + } + public void Java_To_write(S7Connector connector) { + byte[] bytes = null; + + boolean out_boolen = true; +// bytes = S7Type.BOOL; +// connector.write(DaveArea.DB, 5, 264, bytes); + +// 向plc中写int整型数据 +// 向PLC中写短整型(2字节,对应PLC INT类型)数据 + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + short out_int = 15; + bytes = ByteBuffer.allocate(2).putShort(out_int).array(); + connector.write(DaveArea.DB, 5, 266, bytes); + +// 向PLC中写整型(4字节,对应PLC DINT类型)数据 + int data=15; + bytes = ByteBuffer.allocate(4).putInt(data).array(); + connector.write(DaveArea.DB,5, 528,bytes); + + +// 写入字符串 + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] ,总长度为10的话,有效数据只能是10-8,第一位代表总长,第二位,代表有效数据字节 + String out_string = "helloPlc"; + int writeStrLength = 10;//地址块大小 + byte[] writeBytes = new byte[writeStrLength]; + writeBytes[0] = (byte) writeStrLength;//写入本字符串块总宽度 + out_string = out_string.trim();//清除掉两边的空串 + int availableEffectCharLength = 0;//有效字符数控制 + if (out_string.length() > writeStrLength - 2) {//>writeStrLength-2 截断到最大有效数据位 + availableEffectCharLength = writeStrLength - 2; + + } else {//<=writeStrLength-2 + availableEffectCharLength = out_string.length(); + } + writeBytes[1] = (byte) availableEffectCharLength;//写入有效字节数 + byte[] strBytes = out_string.getBytes(StandardCharsets.US_ASCII); + for (int i = 0; i < availableEffectCharLength; i++) { + writeBytes[i + 2] = strBytes[i]; + } + connector.write(DaveArea.DB, 5, 268, writeBytes); + + + /** + * 写入PLC中的浮点型数据 + * java float : plc Real 4 字节 + * java double : plc LReal 8 字节 + **/ + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + float out_real= 5.54F; + bytes = ByteBuffer.allocate(4).putFloat(out_real).array(); + connector.write(DaveArea.DB,5, 524,bytes); + + /** + * 写入PLC中的浮点型LREAL(java中是double)数据 + * java float : plc Real 4 字节 + * java double : plc LReal 8 字节 + **/ + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + float out_Lreal= 15.56F; + bytes = ByteBuffer.allocate(8).putDouble(out_Lreal).array(); + connector.write(DaveArea.DB,5, 532,bytes); + + + try { + connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java new file mode 100644 index 0000000..70aa3c0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java @@ -0,0 +1,22 @@ +package com.rczn.task; + +import java.time.LocalDateTime; + +public class TestCrc { + public static void main(String[] args) throws CloneNotSupportedException { + LocalDateTime localDateTime = LocalDateTime.now(); + Video v1 = new Video("123", localDateTime); + Video v2 = (Video) v1.clone(); + + System.out.println(v1); + System.out.println(v2); + System.out.println("==================================="); + + localDateTime.minusDays(10); + v1.setName("vvvvvv"); + + System.out.println(v1); + System.out.println(v2); + System.out.println("===============12312312312===================="); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java new file mode 100644 index 0000000..6c93bc0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java @@ -0,0 +1,17 @@ +package com.rczn.task; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class TestTask { + Log log = LogFactory.getLog(TestTask.class); + + @Scheduled(cron = "0 0/30 * * * ?") + public void test() { + System.out.println("This is a test task."); + log.info("This is a test task."); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java new file mode 100644 index 0000000..2914449 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java @@ -0,0 +1,46 @@ +package com.rczn.task; + +import java.time.LocalDateTime; + +public class Video implements Cloneable{ + private String name; + private LocalDateTime createTime; + + public Video() { + + } + + public Video(String name, LocalDateTime createTime) { + this.name = name; + this.createTime = createTime; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public String toString() { + return "Video{" + + "name='" + name + '\'' + + ", createTime=" + createTime + + '}'; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java new file mode 100644 index 0000000..b9cb240 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java @@ -0,0 +1,22 @@ +package com.rczn.utils; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; + +@Component +public class BeanFactoryUtils implements BeanFactoryPostProcessor { + + private static ConfigurableListableBeanFactory beanFactory; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { + BeanFactoryUtils.beanFactory = factory; + } + + // 获取Bean + public static T getBean(Class clazz) { + return beanFactory.getBean(clazz); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java new file mode 100644 index 0000000..8fde0d5 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java @@ -0,0 +1,75 @@ +package com.rczn.websocket; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; + +@Component +@ServerEndpoint("/websocket/{userId}") +public class WebSocketServer { + Log log = LogFactory.getLog(WebSocketServer.class); + + //springboot自带json转换器 + private static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + //存放每个连接对象 + private static CopyOnWriteArraySet webSockets = new CopyOnWriteArraySet<>(); + private Session session; + private Long userId; + + /** + * 连接建立成功调用的方法 + * @param session + * @param userId + */ + @OnOpen + public void onOpen(Session session, @PathParam("userId") Long userId) { + this.session = session; + this.userId = userId; + webSockets.add(this); + log.info("有新连接加入!当前在线人数为" + webSockets.size()); + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose(){ + webSockets.remove(this); + log.info("有连接关闭!当前在线人数为" + webSockets.size()); + } + + /** + * 收到客户端消息后调用的方法 + * @OnMessage + * @param message 客户端发送过来的消息 + * @param session + */ + @OnMessage + public void onMessage(String message,Session session){ + log.info("收到来自客户端的消息:" + message); + } + + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误:"+error.getStackTrace()); + } + + /** + * 发送消息 + * @param message + * @throws IOException + */ + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java b/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java new file mode 100644 index 0000000..66dc009 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn.rczncommon; + +//import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznCommonApplicationTests { + +// @Test + void contextLoads() { + } + +}