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/.idea/workspace.xml b/rc_autoplc_backend/.idea/workspace.xml
index 590182f..636571d 100644
--- a/rc_autoplc_backend/.idea/workspace.xml
+++ b/rc_autoplc_backend/.idea/workspace.xml
@@ -4,81 +4,21 @@
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -121,29 +61,29 @@
- {
+ "keyToString": {
+ "RequestMappingsPanelOrder0": "0",
+ "RequestMappingsPanelOrder1": "1",
+ "RequestMappingsPanelWidth0": "75",
+ "RequestMappingsPanelWidth1": "75",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "WebServerToolWindowFactoryState": "false",
+ "last_opened_file_path": "D:/java-work/融创智能PLC后台系统/RCZN-bs-program/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "project.structure.last.edited": "SDKs",
+ "project.structure.proportion": "0.0",
+ "project.structure.side.proportion": "0.2",
+ "settings.editor.selected.configurable": "ai.codegeex.plugin.settings.ApplicationConfigurable",
+ "spring.configuration.checksum": "23e183287596c71f060f4e02bc43279b",
+ "ts.external.directory.path": "D:\\JetBrains\\IntelliJ IDEA 2023.1.7\\plugins\\javascript-impl\\jsLanguageServicesImpl\\external",
+ "vue.rearranger.settings.migration": "true"
}
-}]]>
+}
@@ -280,7 +220,11 @@
-
+
+
+
+
+
@@ -354,7 +298,15 @@
1777533044176
-
+
+
+ 1777533903758
+
+
+
+ 1777533903758
+
+
@@ -409,7 +361,8 @@
-
+
+
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/controller/UserController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java
index 126a663..7a0ff11 100644
--- a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java
+++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java
@@ -8,7 +8,10 @@ import com.rczn.rcznautoplc.domain.RecordInfo;
import com.rczn.rcznautoplc.service.ManageLogService;
import com.rczn.rcznautoplc.service.RecordInfoService;
import com.rczn.system.domain.Permission;
+import com.rczn.system.domain.Role;
import com.rczn.system.domain.User;
+import com.rczn.system.domain.UserRole;
+import com.rczn.system.service.UserRoleService;
import com.rczn.system.service.UserService;
import com.rczn.utils.JwtUtil;
import com.rczn.utils.Md5Util;
@@ -17,6 +20,7 @@ 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 io.swagger.v3.oas.models.security.SecurityScheme;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -174,6 +178,8 @@ public class UserController {
@Autowired
ManageLogService manageLogService;
+ @Autowired
+ UserRoleService userRoleService;
@PostMapping("/login")
@Operation(summary = "用户登录接口",description = "根据用户名和密码登录,返回JWT Token")
@@ -222,13 +228,23 @@ public class UserController {
Map claims = new HashMap<>();
claims.put("id", user.getId());
claims.put("username", user.getUserName());
+ //获取角色列表:
+ List roles = userRoleService.selectByRoleId(user.getId().intValue());
+ List roleIdList = roles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
+
//获取权限列表:
List permissions = userService.findUserPermissions(user.getId());
List permissionList = permissions.stream().map(Permission::getPermissionCode).collect(Collectors.toList());
- claims.put("permissions", permissionList);
String jwtToken = JwtUtil.genToken(claims);
+
+ LoginRequest request = new LoginRequest();
+ request.setToken(jwtToken);
+ request.setPermissions(permissionList);
+ request.setRoles(roleIdList);
+ request.setUsername(username);
+
//密码正确,返回成功信息
- return Result.success(jwtToken);
+ return Result.success(request);
} else {
//密码错误,返回错误信息
return Result.error("密码错误!");
@@ -236,4 +252,59 @@ public class UserController {
}
}
+ class LoginRequest {
+ //用户名
+ private String username;
+ //token
+ private String token;
+
+ //角色列表
+ private List roles;
+ //权限列表
+ private List permissions;
+
+ public LoginRequest(String username, String token, List roles, List permissions) {
+ this.username = username;
+ this.token = token;
+ this.roles = roles;
+ this.permissions = permissions;
+ }
+
+ public LoginRequest() {
+
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public List getRoles() {
+ return roles;
+ }
+
+ public void setRoles(List roles) {
+ this.roles = roles;
+ }
+
+ public List getPermissions() {
+ return permissions;
+ }
+
+ public void setPermissions(List permissions) {
+ this.permissions = permissions;
+ }
+ }
+
}
\ 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..81fa8cb
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java
@@ -0,0 +1,336 @@
+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/RecordDealController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/RecordDealController.java
new file mode 100644
index 0000000..8d10b05
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/RecordDealController.java
@@ -0,0 +1,89 @@
+package com.rczn.rcznautoplc.controller;
+
+import com.github.pagehelper.PageInfo;
+import com.rczn.domain.Result;
+import com.rczn.rcznautoplc.domain.RecordDeal;
+import com.rczn.rcznautoplc.service.RecordDealService;
+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.*;
+
+@RestController
+@RequestMapping("/recordDeal")
+@Tag(name = "异常处理记录管理", description = "异常处理记录增删改查+分页接口")
+public class RecordDealController {
+
+ @Autowired
+ private RecordDealService recordDealService;
+
+ @GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(summary = "分页查询异常处理记录", description = "支持异常名称、类型、关联异常ID查询")
+ @Parameters({
+ @Parameter(name = "pageNum", required = true, example = "1", in = ParameterIn.QUERY),
+ @Parameter(name = "pageSize", required = true, example = "10", in = ParameterIn.QUERY),
+ @Parameter(name = "recordId", description = "关联异常ID", required = false, in = ParameterIn.QUERY),
+ @Parameter(name = "recordName", description = "异常名称(模糊)", required = false, in = ParameterIn.QUERY),
+ @Parameter(name = "recordType", description = "类型 1设备2样品3操作", required = false, in = ParameterIn.QUERY)
+ })
+ public Result listPage(
+ @RequestParam Integer pageNum,
+ @RequestParam Integer pageSize,
+ @RequestParam(required = false) Integer recordId,
+ @RequestParam(required = false) String recordName,
+ @RequestParam(required = false) Integer recordType) {
+ RecordDeal param = new RecordDeal();
+ param.setRecordId(recordId);
+ param.setRecordName(recordName);
+ param.setRecordType(recordType);
+ PageInfo page = recordDealService.selectPage(pageNum, pageSize, param);
+ return Result.success(page);
+ }
+
+ @GetMapping("/listByRecordId/{recordId}")
+ @Operation(summary = "根据异常ID查询处理记录")
+ public Result listByRecordId(@PathVariable Integer recordId) {
+ return Result.success(recordDealService.selectByRecordId(recordId));
+ }
+
+ @GetMapping("/getById/{id}")
+ @Operation(summary = "根据ID查询详情")
+ public Result getById(@PathVariable Long id) {
+ RecordDeal deal = recordDealService.selectById(id);
+ return deal != null ? Result.success(deal) : Result.error("记录不存在");
+ }
+
+ @PostMapping("/add")
+ @Operation(summary = "新增异常处理记录")
+ public Result add(@RequestBody RecordDeal recordDeal) {
+ try {
+ return Result.success(recordDealService.insert(recordDeal));
+ } catch (IllegalArgumentException e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "修改异常处理记录")
+ public Result update(@RequestBody RecordDeal recordDeal) {
+ try {
+ return Result.success(recordDealService.update(recordDeal));
+ } catch (IllegalArgumentException e) {
+ return Result.error(e.getMessage());
+ }
+ }
+
+ @DeleteMapping("/del/{id}")
+ @Operation(summary = "删除处理记录(逻辑删除)")
+ public Result delete(@PathVariable Long id) {
+ try {
+ return Result.success(recordDealService.deleteById(id));
+ } catch (IllegalArgumentException e) {
+ return Result.error(e.getMessage());
+ }
+ }
+}
\ 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/DevInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java
index bd1a36a..e252b4d 100644
--- a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java
@@ -29,7 +29,7 @@ public class DevInfo extends BaseBean {
private String company;
- private Integer status; // 0-空闲,1-运行,4-故障
+ private Integer status; //1:在线空闲 0:离线 2:忙碌 5:故障
private Integer runModel;//0-手动模式,1-自动模式
diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java
index 3c965dc..b6d1f57 100644
--- a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java
@@ -15,6 +15,9 @@ public class IslandInfo extends BaseBean {
private String islandLogo;
+ //1:在线空闲 0:离线 2:忙碌 5:故障
+ private Integer status;
+
private String desc;
public IslandInfo() {
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/RecordDeal.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordDeal.java
new file mode 100644
index 0000000..857446a
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordDeal.java
@@ -0,0 +1,60 @@
+package com.rczn.rcznautoplc.domain;
+
+import com.rczn.domain.BaseBean;
+import java.time.LocalDateTime;
+
+/**
+ * 异常处理记录表
+ */
+public class RecordDeal extends BaseBean {
+
+ private Integer recordId; // 异常记录表ID
+ private String dealContent; // 处理内容
+ private String recordName; // 异常名称
+ private Integer recordType; // 异常类型 1-设备异常 2-样品异常 3-操作异常
+
+ public RecordDeal() {
+ }
+
+ public RecordDeal(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime,
+ boolean delSign, String remark, Integer recordId, String dealContent,
+ String recordName, Integer recordType) {
+ super(id, createId, createTime, updateId, updateTime, delSign, remark);
+ this.recordId = recordId;
+ this.dealContent = dealContent;
+ this.recordName = recordName;
+ this.recordType = recordType;
+ }
+
+ public Integer getRecordId() {
+ return recordId;
+ }
+
+ public void setRecordId(Integer recordId) {
+ this.recordId = recordId;
+ }
+
+ public String getDealContent() {
+ return dealContent;
+ }
+
+ public void setDealContent(String dealContent) {
+ this.dealContent = dealContent;
+ }
+
+ public String getRecordName() {
+ return recordName;
+ }
+
+ public void setRecordName(String recordName) {
+ this.recordName = recordName;
+ }
+
+ public Integer getRecordType() {
+ return recordType;
+ }
+
+ public void setRecordType(Integer recordType) {
+ this.recordType = recordType;
+ }
+}
\ No newline at end of file
diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java
index 043e333..81dca27 100644
--- a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java
@@ -5,6 +5,11 @@ import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class RecordInfo extends BaseBean {
+
+ private Integer islandId;//关联对应功能岛ID
+
+ private Integer devId;//关联对应设备ID
+
private String recordName;
private Integer recordType; // 1-设备异常,2-样品异常,3-操作异常
@@ -16,8 +21,31 @@ public class RecordInfo extends BaseBean {
public RecordInfo() {
}
- public RecordInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
+ public RecordInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark, Integer islandId, Integer devId,
+ String recordName, Integer recordType, Boolean recordStatus, String recordContent) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
+ this.islandId = islandId;
+ this.devId = devId;
+ this.recordName = recordName;
+ this.recordType = recordType;
+ this.recordStatus = recordStatus;
+ this.recordContent = recordContent;
+ }
+
+ public Integer getIslandId() {
+ return islandId;
+ }
+
+ public void setIslandId(Integer islandId) {
+ this.islandId = islandId;
+ }
+
+ public Integer getDevId() {
+ return devId;
+ }
+
+ public void setDevId(Integer devId) {
+ this.devId = devId;
}
public String getRecordName() {
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/mapper/RecordDealMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/RecordDealMapper.java
new file mode 100644
index 0000000..d10011d
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/RecordDealMapper.java
@@ -0,0 +1,40 @@
+package com.rczn.rcznautoplc.mapper;
+
+import com.rczn.rcznautoplc.domain.RecordDeal;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+@Mapper
+public interface RecordDealMapper {
+
+ /**
+ * 新增
+ */
+ Long insert(RecordDeal recordDeal);
+
+ /**
+ * 修改
+ */
+ Boolean update(RecordDeal recordDeal);
+
+ /**
+ * 逻辑删除
+ */
+ Boolean deleteById(@Param("id") Long id);
+
+ /**
+ * 根据ID查询
+ */
+ RecordDeal selectById(@Param("id") Long id);
+
+ /**
+ * 分页条件查询
+ */
+ List selectPage(RecordDeal recordDeal);
+
+ /**
+ * 根据异常记录ID查询
+ */
+ List selectByRecordId(@Param("recordId") Integer recordId);
+}
\ 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/RecordDealService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/RecordDealService.java
new file mode 100644
index 0000000..ee22cb2
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/RecordDealService.java
@@ -0,0 +1,20 @@
+package com.rczn.rcznautoplc.service;
+
+import com.github.pagehelper.PageInfo;
+import com.rczn.rcznautoplc.domain.RecordDeal;
+import java.util.List;
+
+public interface RecordDealService {
+
+ PageInfo selectPage(Integer pageNum, Integer pageSize, RecordDeal recordDeal);
+
+ RecordDeal selectById(Long id);
+
+ List selectByRecordId(Integer recordId);
+
+ Long insert(RecordDeal recordDeal);
+
+ Boolean update(RecordDeal recordDeal);
+
+ Boolean deleteById(Long id);
+}
\ No newline at end of file
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/service/impl/RecordDealServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/RecordDealServiceImpl.java
new file mode 100644
index 0000000..277dcad
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/RecordDealServiceImpl.java
@@ -0,0 +1,67 @@
+package com.rczn.rcznautoplc.service.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.rczn.rcznautoplc.domain.RecordDeal;
+import com.rczn.rcznautoplc.mapper.RecordDealMapper;
+import com.rczn.rcznautoplc.service.RecordDealService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import java.util.List;
+
+@Service
+public class RecordDealServiceImpl implements RecordDealService {
+
+ @Autowired
+ private RecordDealMapper recordDealMapper;
+
+ @Override
+ public PageInfo selectPage(Integer pageNum, Integer pageSize, RecordDeal recordDeal) {
+ PageHelper.startPage(pageNum, pageSize);
+ List list = recordDealMapper.selectPage(recordDeal);
+ return new PageInfo<>(list);
+ }
+
+ @Override
+ public RecordDeal selectById(Long id) {
+ if (id == null) {
+ throw new IllegalArgumentException("ID不能为空");
+ }
+ return recordDealMapper.selectById(id);
+ }
+
+ @Override
+ public List selectByRecordId(Integer recordId) {
+ if (recordId == null) {
+ throw new IllegalArgumentException("异常记录ID不能为空");
+ }
+ return recordDealMapper.selectByRecordId(recordId);
+ }
+
+ @Override
+ public Long insert(RecordDeal recordDeal) {
+ if (recordDeal.getRecordId() == null) {
+ throw new IllegalArgumentException("异常记录ID不能为空");
+ }
+ if (recordDeal.getDealContent() == null || recordDeal.getDealContent().trim().isEmpty()) {
+ throw new IllegalArgumentException("处理内容不能为空");
+ }
+ return recordDealMapper.insert(recordDeal);
+ }
+
+ @Override
+ public Boolean update(RecordDeal recordDeal) {
+ if (recordDeal.getId() == null) {
+ throw new IllegalArgumentException("ID不能为空");
+ }
+ return recordDealMapper.update(recordDeal);
+ }
+
+ @Override
+ public Boolean deleteById(Long id) {
+ if (id == null) {
+ throw new IllegalArgumentException("ID不能为空");
+ }
+ return recordDealMapper.deleteById(id);
+ }
+}
\ No newline at end of file
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/main/resources/com/rczn/rcznautoplc/mapper/RecordDealMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordDealMapper.xml
new file mode 100644
index 0000000..02754fa
--- /dev/null
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordDealMapper.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+ id, create_id, create_time, update_id, update_time, del_sign, remark
+
+
+
+
+ record_id, deal_content, record_name, record_type
+
+
+
+
+ INSERT INTO tb_record_deal (
+ ,
+ create_id, create_time, update_id, update_time, del_sign
+ ) VALUES (
+ #{recordId}, #{dealContent}, #{recordName}, #{recordType},
+ #{createId}, NOW(), #{updateId}, NOW(), 0
+ )
+
+
+
+
+ UPDATE tb_record_deal
+
+ record_id = #{recordId},
+ deal_content = #{dealContent},
+ record_name = #{recordName},
+ record_type = #{recordType},
+ update_id = #{updateId},
+ update_time = NOW()
+
+ WHERE id = #{id} AND del_sign = 0
+
+
+
+
+ UPDATE tb_record_deal
+ 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-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml
index 827f0c1..cd40ffd 100644
--- a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml
+++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml
@@ -6,14 +6,14 @@
- record_name, record_type, record_status, record_content
+ island_id, dev_id, record_name, record_type, record_status, record_content
INSERT INTO tb_record_info (
,
create_id, create_time, update_id, update_time, del_sign
- ) VALUES (
+ ) VALUES (#{islandId}, #{devId},
#{recordName}, #{recordType}, #{recordStatus}, #{recordContent},
#{createId}, NOW(), #{updateId}, NOW(), 0
)
@@ -22,6 +22,8 @@
UPDATE tb_record_info
+ island_id = #{islandId},
+ dev_id = #{devId},
record_name = #{recordName},
record_type = #{recordType},
record_status = #{recordStatus},
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/utils/JwtUtil.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java
index 082a819..fc57887 100644
--- a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java
+++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java
@@ -28,7 +28,7 @@ public class JwtUtil {
}
public static void main(String[] args) {
- String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsicGVybWlzc2lvbnMiOlsiMTExMSIsIjIyMiIsIjU1NSJdLCJpZCI6MywidXNlcm5hbWUiOiJzdHJpbmcifSwiZXhwIjoxNzc2NzE2NzAyfQ.ynjs9Ys0CxoZjRstjz3mjr3c6NYMFiV3MmTGQYpJmKQ";//genToken(null);
+ String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsicGVybWlzc2lvbnMiOlsic3lzIiwiZGF0YSIsInRiIiwic3lzOnVzZXIiLCJzeXM6cm9sZSIsInN5czpwZXJtaXNzaW9uIiwic3lzOmRlcGFydG1lbnQiLCJzeXM6bWFuYWdlbG9nIiwiZGF0YTpwbGMiLCJkYXRhOmRldnBhcmFtIiwiZGF0YTpkZXYiLCJkYXRhOmlzbGFuZCIsImRhdGE6c29wIiwidGI6Z29vZGNvbnRyb2wiLCJ0Yjpnb29kcmVjb3JkIiwic3lzOnVzZXI6YWRkIiwic3lzOnVzZXI6dXBkIiwic3lzOnVzZXI6ZGVsIiwic3lzOnVzZXI6dXNlcnJvbGUiLCJzeXM6cm9sZTphZGQiLCJzeXM6cm9sZTp1cGQiLCJzeXM6cm9sZTpkZWwiLCJzeXM6cm9sZTpyb2xlcGVybWlzc2lvbiIsInN5czpwZXJtaXNzaW9uOmFkZCIsInN5czpwZXJtaXNzaW9uOnVwZCIsInN5czpwZXJtaXNzaW9uOmRlbCIsInN5czpkZXBhcnRtZW50OmFkZCIsInN5czpkZXBhcnRtZW50OnVwZCIsInN5czpkZXBhcnRtZW50OmRlbCIsInN5czptYW5hZ2Vsb2c6ZGV0YWlsIiwiZGF0YTpwbGM6YWRkIiwiZGF0YTpwbGM6dXBkIiwiZGF0YTpwbGM6ZGVsIiwiZGF0YTpkZXZwYXJhbTphZGQiLCJkYXRhOmRldnBhcmFtOnVwZCIsImRhdGE6ZGV2cGFyYW06ZGVsIiwiZGF0YTpkZXZwYXJhbTpyYW5nZSIsImRhdGE6ZGV2cGFyYW06c2VsZWN0IiwiZGF0YTpkZXY6YWRkIiwiZGF0YTpkZXY6dXBkIiwiZGF0YTpkZXY6ZGVsIiwiZGF0YTpkZXY6c2V0cGFyYW1ldGVycyIsImRhdGE6aXNsYW5kOmFkZCIsImRhdGE6aXNsYW5kOnVwZCIsImRhdGE6aXNsYW5kOmRlbCIsImRhdGE6c29wOmFkZCIsImRhdGE6c29wOmNsZWFyIiwiZGF0YTpzb3A6c2F2ZSIsInRiOmdvb2Rjb250cm9sOmNob29zZVNPUCIsInRiOmdvb2Rjb250cm9sOnVwZFNPUCIsInRiOmdvb2Rjb250cm9sOnZpZXdTT1AiLCJ0Yjpnb29kY29udHJvbDp1cGQiLCJ0Yjpnb29kY29udHJvbDpkZWwiLCJ0Yjpnb29kY29udHJvbDptb2RlbCIsInRiOmdvb2Rjb250cm9sOmNvbm5lY3Rpb24iLCJ0Yjpnb29kY29udHJvbDpleGVjdXRlIiwidGI6Z29vZGNvbnRyb2w6c3RvcCIsInRiOmdvb2Rjb250cm9sOnJlc2V0IiwidGI6Z29vZHJlY29yZDpkZXRhaWwiXSwiaWQiOjEsInVzZXJuYW1lIjoiYWRtaW4ifSwiZXhwIjoxNzc4MDc5OTM0fQ.L1SbAL7Vjzjrl7WjggVQXHlNuaYDXWgvvK3H5a0D5bY";//genToken(null);
System.out.println(token);
Map claims = parseToken(token);
System.out.println(claims);
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() {
+ }
+
+}