正在显示
29 个修改的文件
包含
1505 行增加
和
71 行删除
| @@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
| 8 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 9 | import org.springframework.util.AntPathMatcher; | 9 | import org.springframework.util.AntPathMatcher; |
| 10 | import org.springframework.util.StreamUtils; | 10 | import org.springframework.util.StreamUtils; |
| 11 | +import org.springframework.web.util.ContentCachingRequestWrapper; | ||
| 11 | 12 | ||
| 12 | import javax.servlet.*; | 13 | import javax.servlet.*; |
| 13 | import javax.servlet.annotation.WebFilter; | 14 | import javax.servlet.annotation.WebFilter; |
| @@ -41,7 +42,7 @@ public class HttpServletRequestReplacedFilter implements Filter { | @@ -41,7 +42,7 @@ public class HttpServletRequestReplacedFilter implements Filter { | ||
| 41 | public void doFilter(ServletRequest request, ServletResponse response, | 42 | public void doFilter(ServletRequest request, ServletResponse response, |
| 42 | FilterChain chain) throws IOException, ServletException { | 43 | FilterChain chain) throws IOException, ServletException { |
| 43 | 44 | ||
| 44 | - RequestReaderHttpServletRequestWrapper requestWrapper = null; | 45 | + ContentCachingRequestWrapper requestWrapper = null; |
| 45 | if (request instanceof HttpServletRequest) { | 46 | if (request instanceof HttpServletRequest) { |
| 46 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; | 47 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; |
| 47 | //解决Invalid character found in method name的问题 | 48 | //解决Invalid character found in method name的问题 |
| @@ -56,8 +57,8 @@ public class HttpServletRequestReplacedFilter implements Filter { | @@ -56,8 +57,8 @@ public class HttpServletRequestReplacedFilter implements Filter { | ||
| 56 | 57 | ||
| 57 | if (!match(httpServletRequest.getRequestURI().toString())) | 58 | if (!match(httpServletRequest.getRequestURI().toString())) |
| 58 | { | 59 | { |
| 59 | - requestWrapper = new RequestReaderHttpServletRequestWrapper(httpServletRequest); | ||
| 60 | - printLog(httpServletRequest,requestWrapper.getBody()); | 60 | + requestWrapper = new ContentCachingRequestWrapper(httpServletRequest); |
| 61 | + printLog(requestWrapper); | ||
| 61 | } | 62 | } |
| 62 | } | 63 | } |
| 63 | //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。 | 64 | //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。 |
| @@ -69,29 +70,40 @@ public class HttpServletRequestReplacedFilter implements Filter { | @@ -69,29 +70,40 @@ public class HttpServletRequestReplacedFilter implements Filter { | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | } | 72 | } |
| 73 | + private boolean isMultipart(HttpServletRequest request) { | ||
| 74 | + String contentType = request.getContentType(); | ||
| 75 | + return contentType != null && contentType.startsWith("multipart/"); | ||
| 76 | + } | ||
| 72 | @Override | 77 | @Override |
| 73 | public void destroy() { | 78 | public void destroy() { |
| 74 | } | 79 | } |
| 75 | 80 | ||
| 76 | - private void printLog(HttpServletRequest httpServletRequest,byte[] bodyBytes) throws UnsupportedEncodingException { | ||
| 77 | - logger.info("---------------------开始进入"+httpServletRequest.getRequestURL().toString()+"登录拦截----------------------------"); | ||
| 78 | - Map<String,Object> map = new HashMap<>(); | ||
| 79 | - map.put("parameterValue",httpServletRequest.getParameterMap()); | 81 | + private void printLog(ContentCachingRequestWrapper request) throws IOException { |
| 82 | + logger.info("------ 请求 URL: {} ------", request.getRequestURL()); | ||
| 83 | + | ||
| 84 | + Map<String, Object> map = new HashMap<>(); | ||
| 80 | 85 | ||
| 81 | - // 打印请求头信息 | ||
| 82 | - Map<String,Object> headermap = new HashMap<>(); | ||
| 83 | - Enumeration<String> headerNames = httpServletRequest.getHeaderNames(); | 86 | + // headers |
| 87 | + Map<String, Object> headerMap = new HashMap<>(); | ||
| 88 | + Enumeration<String> headerNames = request.getHeaderNames(); | ||
| 84 | while (headerNames.hasMoreElements()) { | 89 | while (headerNames.hasMoreElements()) { |
| 85 | - String headerName = headerNames.nextElement(); | ||
| 86 | - String headerValue = httpServletRequest.getHeader(headerName); | ||
| 87 | - headermap.put(headerName, headerValue); | 90 | + String h = headerNames.nextElement(); |
| 91 | + headerMap.put(h, request.getHeader(h)); | ||
| 92 | + } | ||
| 93 | + map.put("header", headerMap); | ||
| 94 | + | ||
| 95 | + // params | ||
| 96 | + map.put("parameterValue", request.getParameterMap()); | ||
| 97 | + | ||
| 98 | + // ★ multipart 请求不能提前读取,否则破坏文件上传 | ||
| 99 | + if (!isMultipart(request)) { | ||
| 100 | + // body | ||
| 101 | + String body = new String(request.getContentAsByteArray(), | ||
| 102 | + request.getCharacterEncoding() == null ? "UTF-8" : request.getCharacterEncoding()); | ||
| 103 | + map.put("body", body); | ||
| 88 | } | 104 | } |
| 89 | - map.put("header",headermap); | ||
| 90 | 105 | ||
| 91 | - //获取请求body | ||
| 92 | - String body = new String(bodyBytes, httpServletRequest.getCharacterEncoding()); | ||
| 93 | - map.put("body",body); | ||
| 94 | - logger.info("---------------------参数:"+ GsonConstructor.get().toJson(map)+"----------------------------"); | 106 | + logger.info("------ 参数:{} ------", GsonConstructor.get().toJson(map)); |
| 95 | } | 107 | } |
| 96 | 108 | ||
| 97 | // 设置排除路径 | 109 | // 设置排除路径 |
lh-jar/lh-jar-device-service/src/main/java/com/zhonglai/luhui/device/domain/IotProductPlcDevice.java
0 → 100644
| 1 | +package com.zhonglai.luhui.device.domain; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | + | ||
| 6 | +@ApiModel("流水鱼plc设备") | ||
| 7 | +public class IotProductPlcDevice { | ||
| 8 | + @ApiModelProperty(value="主键") | ||
| 9 | + private Integer id; | ||
| 10 | + @ApiModelProperty(value="名称") | ||
| 11 | + private String name; | ||
| 12 | + @ApiModelProperty(value="可分配编号") | ||
| 13 | + private String numbers; | ||
| 14 | + @ApiModelProperty(value="标识符") | ||
| 15 | + private String identifier; | ||
| 16 | + | ||
| 17 | + public String getIdentifier() { | ||
| 18 | + return identifier; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + public void setIdentifier(String identifier) { | ||
| 22 | + this.identifier = identifier; | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + public Integer getId() { | ||
| 26 | + return id; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + public void setId(Integer id) { | ||
| 30 | + this.id = id; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + public String getName() { | ||
| 34 | + return name; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + public void setName(String name) { | ||
| 38 | + this.name = name; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + public String getNumbers() { | ||
| 42 | + return numbers; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + public void setNumbers(String numbers) { | ||
| 46 | + this.numbers = numbers; | ||
| 47 | + } | ||
| 48 | +} |
| @@ -59,5 +59,6 @@ public interface UserTerminalGroupRelationMapper | @@ -59,5 +59,6 @@ public interface UserTerminalGroupRelationMapper | ||
| 59 | */ | 59 | */ |
| 60 | public int deleteUserTerminalGroupRelationByIds(Integer[] ids); | 60 | public int deleteUserTerminalGroupRelationByIds(Integer[] ids); |
| 61 | 61 | ||
| 62 | + public int deleteUserTerminalGroupRelationByTerminalIds(String[] ids); | ||
| 62 | List<UserTerminalGroupRelation> selectListByTerminalIds(String[] iot_terminal_ids); | 63 | List<UserTerminalGroupRelation> selectListByTerminalIds(String[] iot_terminal_ids); |
| 63 | } | 64 | } |
| @@ -51,7 +51,7 @@ public interface IUserTerminalGroupRelationService | @@ -51,7 +51,7 @@ public interface IUserTerminalGroupRelationService | ||
| 51 | * @return 结果 | 51 | * @return 结果 |
| 52 | */ | 52 | */ |
| 53 | public int deleteUserTerminalGroupRelationByIds(Integer[] ids); | 53 | public int deleteUserTerminalGroupRelationByIds(Integer[] ids); |
| 54 | - | 54 | + public int deleteUserTerminalGroupRelationByTerminalIds(String[] ids); |
| 55 | /** | 55 | /** |
| 56 | * 删除终端分组关系信息 | 56 | * 删除终端分组关系信息 |
| 57 | * | 57 | * |
| @@ -96,6 +96,11 @@ public class UserTerminalGroupRelationServiceImpl implements IUserTerminalGroupR | @@ -96,6 +96,11 @@ public class UserTerminalGroupRelationServiceImpl implements IUserTerminalGroupR | ||
| 96 | return userTerminalGroupRelationMapper.deleteUserTerminalGroupRelationByIds(ids); | 96 | return userTerminalGroupRelationMapper.deleteUserTerminalGroupRelationByIds(ids); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | + public int deleteUserTerminalGroupRelationByTerminalIds(String[] ids) | ||
| 100 | + { | ||
| 101 | + return userTerminalGroupRelationMapper.deleteUserTerminalGroupRelationByTerminalIds(ids); | ||
| 102 | + } | ||
| 103 | + | ||
| 99 | /** | 104 | /** |
| 100 | * 删除终端分组关系信息 | 105 | * 删除终端分组关系信息 |
| 101 | * | 106 | * |
| @@ -40,11 +40,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | @@ -40,11 +40,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
| 40 | <if test="create_time != null">create_time,</if> | 40 | <if test="create_time != null">create_time,</if> |
| 41 | <if test="name != null">name,</if> | 41 | <if test="name != null">name,</if> |
| 42 | <if test="user_info_id != null">user_info_id,</if> | 42 | <if test="user_info_id != null">user_info_id,</if> |
| 43 | + <if test="group_type != null">group_type,</if> | ||
| 43 | </trim> | 44 | </trim> |
| 44 | <trim prefix="values (" suffix=")" suffixOverrides=","> | 45 | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| 45 | <if test="create_time != null">#{create_time},</if> | 46 | <if test="create_time != null">#{create_time},</if> |
| 46 | <if test="name != null">#{name},</if> | 47 | <if test="name != null">#{name},</if> |
| 47 | <if test="user_info_id != null">#{user_info_id},</if> | 48 | <if test="user_info_id != null">#{user_info_id},</if> |
| 49 | + <if test="group_type != null">#{group_type},</if> | ||
| 48 | </trim> | 50 | </trim> |
| 49 | </insert> | 51 | </insert> |
| 50 | 52 | ||
| @@ -54,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | @@ -54,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
| 54 | <if test="create_time != null">create_time = #{create_time},</if> | 56 | <if test="create_time != null">create_time = #{create_time},</if> |
| 55 | <if test="name != null">name = #{name},</if> | 57 | <if test="name != null">name = #{name},</if> |
| 56 | <if test="user_info_id != null">user_info_id = #{user_info_id},</if> | 58 | <if test="user_info_id != null">user_info_id = #{user_info_id},</if> |
| 59 | + <if test="group_type != null">group_type = #{group_type},</if> | ||
| 57 | </trim> | 60 | </trim> |
| 58 | where id = #{id} | 61 | where id = #{id} |
| 59 | </update> | 62 | </update> |
| @@ -79,6 +79,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | @@ -79,6 +79,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
| 79 | </foreach> | 79 | </foreach> |
| 80 | </delete> | 80 | </delete> |
| 81 | 81 | ||
| 82 | + <delete id="deleteUserTerminalGroupRelationByTerminalIds" parameterType="String"> | ||
| 83 | + delete from user_terminal_group_relation where iot_terminal_id in | ||
| 84 | + <foreach item="id" collection="array" open="(" separator="," close=")"> | ||
| 85 | + #{id} | ||
| 86 | + </foreach> | ||
| 87 | + </delete> | ||
| 88 | + | ||
| 82 | <select id="selectListByTerminalIds" parameterType="String" resultMap="UserTerminalGroupRelationResult"> | 89 | <select id="selectListByTerminalIds" parameterType="String" resultMap="UserTerminalGroupRelationResult"> |
| 83 | select * from `user_terminal_group_relation` where iot_terminal_id in | 90 | select * from `user_terminal_group_relation` where iot_terminal_id in |
| 84 | <foreach item="id" collection="array" open="(" separator="," close=")"> | 91 | <foreach item="id" collection="array" open="(" separator="," close=")"> |
| 1 | package com.zhonglai.luhui.admin.controller.iot; | 1 | package com.zhonglai.luhui.admin.controller.iot; |
| 2 | 2 | ||
| 3 | +import java.io.IOException; | ||
| 3 | import java.util.HashMap; | 4 | import java.util.HashMap; |
| 4 | import java.util.List; | 5 | import java.util.List; |
| 5 | import java.util.Map; | 6 | import java.util.Map; |
| 7 | +import javax.servlet.http.HttpServletRequest; | ||
| 6 | import javax.servlet.http.HttpServletResponse; | 8 | import javax.servlet.http.HttpServletResponse; |
| 7 | 9 | ||
| 10 | +import cn.hutool.http.HttpRequest; | ||
| 11 | +import cn.hutool.http.HttpResponse; | ||
| 12 | +import cn.hutool.http.HttpUtil; | ||
| 13 | +import cn.hutool.json.JSONObject; | ||
| 14 | +import com.alibaba.fastjson.JSON; | ||
| 15 | +import com.alibaba.fastjson.JSONArray; | ||
| 8 | import com.google.gson.JsonObject; | 16 | import com.google.gson.JsonObject; |
| 17 | +import com.ruoyi.system.domain.entity.SysUser; | ||
| 9 | import com.zhonglai.luhui.action.BaseController; | 18 | import com.zhonglai.luhui.action.BaseController; |
| 19 | +import com.zhonglai.luhui.admin.dto.MNPLCPointEntity; | ||
| 10 | import com.zhonglai.luhui.dao.service.PublicService; | 20 | import com.zhonglai.luhui.dao.service.PublicService; |
| 11 | import com.zhonglai.luhui.device.domain.IotDevice; | 21 | import com.zhonglai.luhui.device.domain.IotDevice; |
| 12 | import com.zhonglai.luhui.security.utils.SecurityUtils; | 22 | import com.zhonglai.luhui.security.utils.SecurityUtils; |
| 13 | import com.zhonglai.luhui.sys.utils.ExcelUtil; | 23 | import com.zhonglai.luhui.sys.utils.ExcelUtil; |
| 14 | import io.swagger.annotations.Api; | 24 | import io.swagger.annotations.Api; |
| 25 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 15 | import io.swagger.annotations.ApiOperation; | 26 | import io.swagger.annotations.ApiOperation; |
| 27 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 28 | +import io.swagger.v3.oas.annotations.enums.ParameterIn; | ||
| 29 | +import org.springframework.http.MediaType; | ||
| 16 | import org.springframework.security.access.prepost.PreAuthorize; | 30 | import org.springframework.security.access.prepost.PreAuthorize; |
| 17 | import org.springframework.beans.factory.annotation.Autowired; | 31 | import org.springframework.beans.factory.annotation.Autowired; |
| 18 | import org.springframework.transaction.annotation.Transactional; | 32 | import org.springframework.transaction.annotation.Transactional; |
| 19 | -import org.springframework.web.bind.annotation.GetMapping; | ||
| 20 | -import org.springframework.web.bind.annotation.PostMapping; | ||
| 21 | -import org.springframework.web.bind.annotation.PutMapping; | ||
| 22 | -import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 23 | -import org.springframework.web.bind.annotation.PathVariable; | ||
| 24 | -import org.springframework.web.bind.annotation.RequestBody; | ||
| 25 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
| 26 | -import org.springframework.web.bind.annotation.RestController; | 33 | +import org.springframework.web.bind.annotation.*; |
| 27 | import com.ruoyi.common.annotation.Log; | 34 | import com.ruoyi.common.annotation.Log; |
| 28 | import com.ruoyi.common.core.domain.AjaxResult; | 35 | import com.ruoyi.common.core.domain.AjaxResult; |
| 29 | import com.ruoyi.common.enums.BusinessType; | 36 | import com.ruoyi.common.enums.BusinessType; |
| 30 | import com.zhonglai.luhui.device.domain.IotProduct; | 37 | import com.zhonglai.luhui.device.domain.IotProduct; |
| 31 | import com.zhonglai.luhui.device.service.IIotProductService; | 38 | import com.zhonglai.luhui.device.service.IIotProductService; |
| 32 | import com.ruoyi.common.core.page.TableDataInfo; | 39 | import com.ruoyi.common.core.page.TableDataInfo; |
| 40 | +import org.springframework.web.multipart.MultipartFile; | ||
| 33 | 41 | ||
| 34 | /** | 42 | /** |
| 35 | * 产品Controller | 43 | * 产品Controller |
| @@ -136,4 +144,99 @@ public class IotProductController extends BaseController | @@ -136,4 +144,99 @@ public class IotProductController extends BaseController | ||
| 136 | return toAjax(IotProductService.deleteIotProductByIds(ids)); | 144 | return toAjax(IotProductService.deleteIotProductByIds(ids)); |
| 137 | } | 145 | } |
| 138 | 146 | ||
| 139 | -} | 147 | + @ApiOperation("导入明牛变量表") |
| 148 | + @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile", dataTypeClass = MultipartFile.class) | ||
| 149 | + @PostMapping(value = "/importMNVariableData") | ||
| 150 | + public AjaxResult importMNVariableData(@RequestParam(value = "file") MultipartFile file) throws Exception { | ||
| 151 | + // 检查文件是否为空,防止 NullPointerException | ||
| 152 | + if (file == null || file.isEmpty()) { | ||
| 153 | + return AjaxResult.error("上传的文件不能为空"); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + ExcelUtil<MNPLCPointEntity> util = new ExcelUtil<>(MNPLCPointEntity.class); | ||
| 157 | + List<MNPLCPointEntity> mnplcPointEntityList = util.importExcel(file.getInputStream()); | ||
| 158 | + if(null != mnplcPointEntityList && mnplcPointEntityList.size() !=0 ) | ||
| 159 | + { | ||
| 160 | + StringBuffer stringBuffer = new StringBuffer("变量名称\t变量描述"); | ||
| 161 | + for (MNPLCPointEntity mnplcPointEntity:mnplcPointEntityList) | ||
| 162 | + { | ||
| 163 | + stringBuffer.append("\n"); | ||
| 164 | + stringBuffer.append(mnplcPointEntity.getVariableName()); | ||
| 165 | + stringBuffer.append("\t"); | ||
| 166 | + stringBuffer.append(mnplcPointEntity.getVariableDescription()); | ||
| 167 | + } | ||
| 168 | + StringBuffer prompt = new StringBuffer("任务说明:\n" + | ||
| 169 | + "你将收到一个包含\"变量名称\"和\"变量描述\"的表格。你的任务是:\n" + | ||
| 170 | + "\n" + | ||
| 171 | + "1. **识别设备**:从变量描述中提取所有设备名称。设备名称可能出现在变量描述中,如\"漩涡风机001\",\"蛋分射流泵1\",\"系统控制柜01\"等。\n" + | ||
| 172 | + "2. **归类属性**:将每个变量名称归类到对应的设备下,作为该设备的属性。注意:\n" + | ||
| 173 | + " - 同一设备可能有多个变量名称。\n" + | ||
| 174 | + " - 变量名称与变量描述之间的对应关系通过描述中的设备名称识别。\n" + | ||
| 175 | + " - 如果变量描述中没有明确设备名称,将这些变量统一归类到\"网关数据\"下。\n" + | ||
| 176 | + "3. **生成 JSON**:最终输出为 JSON 格式的字符串,要求:\n" + | ||
| 177 | + " - JSON 为数组,每个元素是一个对象,键是设备名称,值是该设备的属性数组,用英文逗号分隔。\n" + | ||
| 178 | + " - 示例:\n" + | ||
| 179 | + " [\n" + | ||
| 180 | + " {\n" + | ||
| 181 | + " \"系统控制柜01\": \"SYS_AUTO_01,SYS_01_ALARM_RESET\"\n" + | ||
| 182 | + " },\n" + | ||
| 183 | + " {\n" + | ||
| 184 | + " \"漩涡风机001\": \"C001_RUN,C001_ALARM,C001_QT\"\n" + | ||
| 185 | + " },\n" + | ||
| 186 | + " {\n" + | ||
| 187 | + " \"网关数据\": \"SYS_NH,1-LSL,2-LSL,...\"\n" + | ||
| 188 | + " }\n" + | ||
| 189 | + " ]\n" + | ||
| 190 | + "4. **额外要求**:\n" + | ||
| 191 | + " - 输出只包含 JSON 字符串,不需要其他解释或文字。\n" + | ||
| 192 | + " - 保持设备和属性的顺序与原表格中出现的顺序一致。\n" + | ||
| 193 | + "\n" + | ||
| 194 | + "表格数据如下:\n" ); | ||
| 195 | + prompt.append(stringBuffer); | ||
| 196 | + prompt.append("\n"); | ||
| 197 | + | ||
| 198 | + HttpRequest httpRequest = HttpUtil.createPost("https://api.deepseek.com/v1/chat/completions"); | ||
| 199 | + httpRequest.header("Content-Type", "application/json"); | ||
| 200 | + httpRequest.header("Authorization", "Bearer sk-bf4107d81fa842eb85f3e3abfa6348ae"); | ||
| 201 | + JSONObject data = new JSONObject(); | ||
| 202 | + data.put("model", "deepseek-chat"); | ||
| 203 | + | ||
| 204 | + JSONArray messages = new JSONArray(); | ||
| 205 | + messages.add(new JSONObject() | ||
| 206 | + .put("role", "system") | ||
| 207 | + .put("content", "你是一个专业的数据处理专家,请将表格中的数据处理为JSON格式。") | ||
| 208 | + ); | ||
| 209 | + messages.add(new JSONObject() | ||
| 210 | + .put("role", "user") | ||
| 211 | + .put("content", prompt.toString()) | ||
| 212 | + ); | ||
| 213 | + | ||
| 214 | + data.put("messages", messages); | ||
| 215 | + data.put("stream", false); | ||
| 216 | + | ||
| 217 | + String requestBody = data.toString(); // 自动为你处理所有转义 | ||
| 218 | + HttpResponse response = httpRequest.body(requestBody).execute(); | ||
| 219 | + | ||
| 220 | + // 修复空指针异常:增加对 response 对象的 null 检查 | ||
| 221 | + if(response != null) { | ||
| 222 | + if(response.isOk()) | ||
| 223 | + { | ||
| 224 | + String body = response.body(); | ||
| 225 | + if (body.indexOf("content")>0) | ||
| 226 | + { | ||
| 227 | + JSONArray jsonArray = JSON.parseObject(body).getJSONArray("choices").getJSONObject(0).getJSONObject("message").getJSONArray("content"); | ||
| 228 | + if (jsonArray != null && jsonArray.size() > 0) | ||
| 229 | + { | ||
| 230 | + | ||
| 231 | + } | ||
| 232 | + } | ||
| 233 | + return AjaxResult.success(body); | ||
| 234 | + } | ||
| 235 | + return AjaxResult.error(response.getStatus(), response.body()); | ||
| 236 | + } else { | ||
| 237 | + return AjaxResult.error("请求失败,无法连接到AI服务"); | ||
| 238 | + } | ||
| 239 | + } | ||
| 240 | + return AjaxResult.success(mnplcPointEntityList); | ||
| 241 | + } | ||
| 242 | +} |
| 1 | +package com.zhonglai.luhui.admin.dto; | ||
| 2 | + | ||
| 3 | +import com.ruoyi.common.annotation.Excel; | ||
| 4 | + | ||
| 5 | +public class MNPLCPointEntity { | ||
| 6 | + @Excel(name = "变量ID") | ||
| 7 | + private Integer variableId; // 变量ID | ||
| 8 | + @Excel(name = "变量名称") | ||
| 9 | + private String variableName; // 变量名称 | ||
| 10 | + @Excel(name = "所属分组") | ||
| 11 | + private String groupName; // 所属分组 | ||
| 12 | + @Excel(name = "地址类型") | ||
| 13 | + private String addressType; // 地址类型 | ||
| 14 | + @Excel(name = "地址偏移") | ||
| 15 | + private String addressOffset; // 地址偏移 | ||
| 16 | + @Excel(name = "地址类型2") | ||
| 17 | + private String addressType2; // 地址类型2 | ||
| 18 | + @Excel(name = "地址偏移2") | ||
| 19 | + private String addressOffset2; // 地址偏移2 | ||
| 20 | + @Excel(name = "数据类型") | ||
| 21 | + private String dataType; // 数据类型 | ||
| 22 | + @Excel(name = "数据精度") | ||
| 23 | + private Integer dataPrecision; // 数据精度 | ||
| 24 | + @Excel(name = "字符串长度") | ||
| 25 | + private Integer stringLength; // 字符串长度 | ||
| 26 | + @Excel(name = "字符串编码") | ||
| 27 | + private String stringEncoding; // 字符串编码 | ||
| 28 | + @Excel(name = "线性换算") | ||
| 29 | + private String linearConversion; // 线性换算 | ||
| 30 | + @Excel(name = "输入最小值") | ||
| 31 | + private String inputMin; // 输入最小值 | ||
| 32 | + @Excel(name = "输入最大值") | ||
| 33 | + private String inputMax; // 输入最大值 | ||
| 34 | + @Excel(name = "输出最小值") | ||
| 35 | + private String outputMin; // 输出最小值 | ||
| 36 | + @Excel(name = "输出最大值") | ||
| 37 | + private String outputMax; // 输出最大值 | ||
| 38 | + @Excel(name = "输出数据类型") | ||
| 39 | + private String outputDataType; // 输出数据类型 | ||
| 40 | + @Excel(name = "安全类别") | ||
| 41 | + private String safetyCategory; // 安全类别 | ||
| 42 | + @Excel(name = "读写状态") | ||
| 43 | + private String readWriteStatus; // 读写状态 | ||
| 44 | + @Excel(name = "单位") | ||
| 45 | + private String unit; // 单位 | ||
| 46 | + @Excel(name = "是否启动有效范围") | ||
| 47 | + private String enableRange; // 是否启动有效范围 | ||
| 48 | + @Excel(name = "最大值") | ||
| 49 | + private String maxValue; // 最大值 | ||
| 50 | + @Excel(name = "最小值") | ||
| 51 | + private String minValue; // 最小值 | ||
| 52 | + @Excel(name = "所属设备") | ||
| 53 | + private String deviceName; // 所属设备 | ||
| 54 | + @Excel(name = "变量描述") | ||
| 55 | + private String variableDescription; // 变量描述 | ||
| 56 | + @Excel(name = "变量控制优先级") | ||
| 57 | + private Integer controlPriority; // 变量控制优先级 | ||
| 58 | + | ||
| 59 | + public Integer getVariableId() { | ||
| 60 | + return variableId; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public void setVariableId(Integer variableId) { | ||
| 64 | + this.variableId = variableId; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + public String getVariableName() { | ||
| 68 | + return variableName; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + public void setVariableName(String variableName) { | ||
| 72 | + this.variableName = variableName; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + public String getGroupName() { | ||
| 76 | + return groupName; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + public void setGroupName(String groupName) { | ||
| 80 | + this.groupName = groupName; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + public String getAddressType() { | ||
| 84 | + return addressType; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + public void setAddressType(String addressType) { | ||
| 88 | + this.addressType = addressType; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + public String getAddressOffset() { | ||
| 92 | + return addressOffset; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + public void setAddressOffset(String addressOffset) { | ||
| 96 | + this.addressOffset = addressOffset; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + public String getAddressType2() { | ||
| 100 | + return addressType2; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + public void setAddressType2(String addressType2) { | ||
| 104 | + this.addressType2 = addressType2; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + public String getAddressOffset2() { | ||
| 108 | + return addressOffset2; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + public void setAddressOffset2(String addressOffset2) { | ||
| 112 | + this.addressOffset2 = addressOffset2; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + public String getDataType() { | ||
| 116 | + return dataType; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + public void setDataType(String dataType) { | ||
| 120 | + this.dataType = dataType; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + public Integer getDataPrecision() { | ||
| 124 | + return dataPrecision; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + public void setDataPrecision(Integer dataPrecision) { | ||
| 128 | + this.dataPrecision = dataPrecision; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + public Integer getStringLength() { | ||
| 132 | + return stringLength; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + public void setStringLength(Integer stringLength) { | ||
| 136 | + this.stringLength = stringLength; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + public String getStringEncoding() { | ||
| 140 | + return stringEncoding; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + public void setStringEncoding(String stringEncoding) { | ||
| 144 | + this.stringEncoding = stringEncoding; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + public String getLinearConversion() { | ||
| 148 | + return linearConversion; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + public void setLinearConversion(String linearConversion) { | ||
| 152 | + this.linearConversion = linearConversion; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + public String getInputMin() { | ||
| 156 | + return inputMin; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + public void setInputMin(String inputMin) { | ||
| 160 | + this.inputMin = inputMin; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + public String getInputMax() { | ||
| 164 | + return inputMax; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + public void setInputMax(String inputMax) { | ||
| 168 | + this.inputMax = inputMax; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + public String getOutputMin() { | ||
| 172 | + return outputMin; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + public void setOutputMin(String outputMin) { | ||
| 176 | + this.outputMin = outputMin; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + public String getOutputMax() { | ||
| 180 | + return outputMax; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + public void setOutputMax(String outputMax) { | ||
| 184 | + this.outputMax = outputMax; | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + public String getOutputDataType() { | ||
| 188 | + return outputDataType; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + public void setOutputDataType(String outputDataType) { | ||
| 192 | + this.outputDataType = outputDataType; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + public String getSafetyCategory() { | ||
| 196 | + return safetyCategory; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + public void setSafetyCategory(String safetyCategory) { | ||
| 200 | + this.safetyCategory = safetyCategory; | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + public String getReadWriteStatus() { | ||
| 204 | + return readWriteStatus; | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + public void setReadWriteStatus(String readWriteStatus) { | ||
| 208 | + this.readWriteStatus = readWriteStatus; | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + public String getUnit() { | ||
| 212 | + return unit; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + public void setUnit(String unit) { | ||
| 216 | + this.unit = unit; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + public String getEnableRange() { | ||
| 220 | + return enableRange; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + public void setEnableRange(String enableRange) { | ||
| 224 | + this.enableRange = enableRange; | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + public String getMaxValue() { | ||
| 228 | + return maxValue; | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + public void setMaxValue(String maxValue) { | ||
| 232 | + this.maxValue = maxValue; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + public String getMinValue() { | ||
| 236 | + return minValue; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + public void setMinValue(String minValue) { | ||
| 240 | + this.minValue = minValue; | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + public String getDeviceName() { | ||
| 244 | + return deviceName; | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + public void setDeviceName(String deviceName) { | ||
| 248 | + this.deviceName = deviceName; | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + public String getVariableDescription() { | ||
| 252 | + return variableDescription; | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + public void setVariableDescription(String variableDescription) { | ||
| 256 | + this.variableDescription = variableDescription; | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + public Integer getControlPriority() { | ||
| 260 | + return controlPriority; | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + public void setControlPriority(Integer controlPriority) { | ||
| 264 | + this.controlPriority = controlPriority; | ||
| 265 | + } | ||
| 266 | +} |
lh-modules/lh-admin/src/main/java/com/zhonglai/luhui/admin/service/MNPLCPointAnalysisService.java
0 → 100644
| 1 | +package com.zhonglai.luhui.admin.service; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 4 | +import com.zhonglai.luhui.admin.dto.MNPLCPointEntity; | ||
| 5 | +import com.zhonglai.luhui.sys.utils.ExcelUtil; | ||
| 6 | +import org.apache.poi.ss.usermodel.Row; | ||
| 7 | +import org.apache.poi.ss.usermodel.Sheet; | ||
| 8 | +import org.apache.poi.ss.usermodel.Workbook; | ||
| 9 | +import org.apache.poi.ss.usermodel.WorkbookFactory; | ||
| 10 | + | ||
| 11 | +import java.io.File; | ||
| 12 | +import java.io.FileInputStream; | ||
| 13 | +import java.util.*; | ||
| 14 | +import java.util.regex.Matcher; | ||
| 15 | +import java.util.regex.Pattern; | ||
| 16 | + | ||
| 17 | +public class MNPLCPointAnalysisService { | ||
| 18 | + // 工控常用属性词(可继续扩展) | ||
| 19 | + public static final List<String> ATTR_WORDS = Arrays.asList( | ||
| 20 | + "运行","故障","报警","告警","信号","远程","控制","允许","模式","切换", | ||
| 21 | + "启停","启动","停止","反馈","设定","设置", | ||
| 22 | + "高限","低限","上限","下限","高","低", | ||
| 23 | + "水温","电流","功率","频率","状态","位置" | ||
| 24 | + ); | ||
| 25 | + | ||
| 26 | + // 从变量描述里提取设备名 | ||
| 27 | + public static String extractFromDesc(String desc) { | ||
| 28 | + | ||
| 29 | + for (String key : ATTR_WORDS) { | ||
| 30 | + int index = desc.indexOf(key); | ||
| 31 | + if (index > 0) { | ||
| 32 | + return desc.substring(0, index); // 设备名部分 | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + return desc; // 未匹配到属性词,整体视为设备名 | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + // 从变量名称中提取序号,如 LL003 → 3 | ||
| 39 | + public static String extractNumberFromVarName(String varName) { | ||
| 40 | + Matcher m = Pattern.compile("(\\d+)").matcher(varName); | ||
| 41 | + if (m.find()) { | ||
| 42 | + return m.group(1); | ||
| 43 | + } | ||
| 44 | + return ""; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + // 最终设备名融合逻辑(描述 + 名称) | ||
| 48 | + public static String getDeviceName(String varName, String desc) { | ||
| 49 | + String nameFromDesc = extractFromDesc(desc).trim(); | ||
| 50 | + String numberFromName = extractNumberFromVarName(varName); | ||
| 51 | + | ||
| 52 | + // 如果描述中不含序号,但名称中有 → 补上 | ||
| 53 | + if (!nameFromDesc.matches(".*\\d+.*") && !numberFromName.isEmpty()) { | ||
| 54 | + return nameFromDesc + numberFromName; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + return nameFromDesc; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public static List<MNPLCPointEntity> read(String file) throws Exception { | ||
| 61 | + ExcelUtil<MNPLCPointEntity> util = new ExcelUtil<>(MNPLCPointEntity.class); | ||
| 62 | + List<MNPLCPointEntity> mnplcPointEntityList = util.importExcel(new FileInputStream(file)); | ||
| 63 | + return mnplcPointEntityList; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public static void main(String[] args) throws Exception { | ||
| 67 | + | ||
| 68 | + String file1 = "E:\\work\\idea\\Luhui\\lh-modules\\lh-device-protocol-parser\\lh-device-protocol-agreement\\lh-device-mn-plc\\src\\main\\resources\\变量.xlsx"; | ||
| 69 | + String file2 = "E:\\work\\idea\\Luhui\\lh-modules\\lh-device-protocol-parser\\lh-device-protocol-agreement\\lh-device-mn-plc\\src\\main\\resources\\常德水槽变量.xlsx"; | ||
| 70 | + | ||
| 71 | + // 合并两张表 | ||
| 72 | + List<MNPLCPointEntity> rows = new ArrayList<>(); | ||
| 73 | + rows.addAll(read(file1)); | ||
| 74 | + rows.addAll(read(file2)); | ||
| 75 | + | ||
| 76 | + // 设备 → 点位列表 | ||
| 77 | + Map<String, List<String>> deviceMap = new LinkedHashMap<>(); | ||
| 78 | + | ||
| 79 | + for (MNPLCPointEntity row : rows) { | ||
| 80 | + String varName = row.getVariableName(); | ||
| 81 | + String desc = row.getVariableDescription(); | ||
| 82 | + | ||
| 83 | + // 自动识别设备名 | ||
| 84 | + String deviceName = getDeviceName(varName, desc); | ||
| 85 | + | ||
| 86 | + deviceMap | ||
| 87 | + .computeIfAbsent(deviceName, k -> new ArrayList<>()) | ||
| 88 | + .add(varName); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + // 生成目标格式 | ||
| 92 | + List<Map<String, String>> result = new ArrayList<>(); | ||
| 93 | + | ||
| 94 | + for (Map.Entry<String,List<String>> e : deviceMap.entrySet()) { | ||
| 95 | + Map<String,String> item = new LinkedHashMap<>(); | ||
| 96 | + String device = e.getKey(); | ||
| 97 | + String vars = String.join(",", e.getValue()); | ||
| 98 | + item.put(device, vars); | ||
| 99 | + result.add(item); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + // 输出 JSON | ||
| 103 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 104 | + String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result); | ||
| 105 | + System.out.println(json); | ||
| 106 | + } | ||
| 107 | +} |
lh-modules/lh-api/src/main/java/com/zhonglai/luhui/api/controller/dto/AddIotTerminalRelationDto.java
| @@ -8,27 +8,18 @@ import java.util.List; | @@ -8,27 +8,18 @@ import java.util.List; | ||
| 8 | 8 | ||
| 9 | @ApiModel("通过终端新增终端分组关系") | 9 | @ApiModel("通过终端新增终端分组关系") |
| 10 | public class AddIotTerminalRelationDto { | 10 | public class AddIotTerminalRelationDto { |
| 11 | - @ApiModelProperty("设备id") | ||
| 12 | - private String deviceId; | ||
| 13 | - @ApiModelProperty("分组类型") | ||
| 14 | - private String groupType; | 11 | + @ApiModelProperty("分组id") |
| 12 | + private Integer groupId; | ||
| 13 | + | ||
| 15 | @ApiModelProperty("终端列表") | 14 | @ApiModelProperty("终端列表") |
| 16 | private List<IotTerminal> iotTerminalList; | 15 | private List<IotTerminal> iotTerminalList; |
| 17 | 16 | ||
| 18 | - public String getDeviceId() { | ||
| 19 | - return deviceId; | ||
| 20 | - } | ||
| 21 | - | ||
| 22 | - public void setDeviceId(String deviceId) { | ||
| 23 | - this.deviceId = deviceId; | ||
| 24 | - } | ||
| 25 | - | ||
| 26 | - public String getGroupType() { | ||
| 27 | - return groupType; | 17 | + public Integer getGroupId() { |
| 18 | + return groupId; | ||
| 28 | } | 19 | } |
| 29 | 20 | ||
| 30 | - public void setGroupType(String groupType) { | ||
| 31 | - this.groupType = groupType; | 21 | + public void setGroupId(Integer groupId) { |
| 22 | + this.groupId = groupId; | ||
| 32 | } | 23 | } |
| 33 | 24 | ||
| 34 | public List<IotTerminal> getIotTerminalList() { | 25 | public List<IotTerminal> getIotTerminalList() { |
| 1 | package com.zhonglai.luhui.api.controller.user; | 1 | package com.zhonglai.luhui.api.controller.user; |
| 2 | 2 | ||
| 3 | import java.util.List; | 3 | import java.util.List; |
| 4 | +import java.util.Map; | ||
| 4 | 5 | ||
| 5 | import com.ruoyi.common.utils.DateUtils; | 6 | import com.ruoyi.common.utils.DateUtils; |
| 7 | +import com.ruoyi.common.utils.StringUtils; | ||
| 6 | import com.zhonglai.luhui.action.BaseController; | 8 | import com.zhonglai.luhui.action.BaseController; |
| 7 | import com.zhonglai.luhui.dao.service.PublicService; | 9 | import com.zhonglai.luhui.dao.service.PublicService; |
| 8 | import com.zhonglai.luhui.device.service.IUserTerminalGroupService; | 10 | import com.zhonglai.luhui.device.service.IUserTerminalGroupService; |
| @@ -55,6 +57,35 @@ public class UserTerminalGroupController extends BaseController | @@ -55,6 +57,35 @@ public class UserTerminalGroupController extends BaseController | ||
| 55 | return getDataTable(list); | 57 | return getDataTable(list); |
| 56 | } | 58 | } |
| 57 | 59 | ||
| 60 | + @ApiOperation("查询终端分组列表带统计") | ||
| 61 | + @ApiImplicitParam(value = "分组类型",name = "group_type") | ||
| 62 | + @GetMapping("/listCount") | ||
| 63 | + public AjaxResult listCount(String group_type) | ||
| 64 | + { | ||
| 65 | + String typeStr = ""; | ||
| 66 | + if(StringUtils.isNotEmpty(group_type)) | ||
| 67 | + { | ||
| 68 | + typeStr += " and( 1=2"; | ||
| 69 | + for (String type : group_type.split(",")) | ||
| 70 | + { | ||
| 71 | + typeStr+=" OR utg.`group_type` LIKE '%|"+type+"|%'"; | ||
| 72 | + } | ||
| 73 | + typeStr +=")"; | ||
| 74 | + } | ||
| 75 | + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT \n" + | ||
| 76 | + " utg.id AS group_id,\n" + | ||
| 77 | + " utg.name AS group_name,\n" + | ||
| 78 | + " COUNT(CASE WHEN it.online = 3 THEN 1 END) AS online_count,\n" + | ||
| 79 | + " COUNT(CASE WHEN it.online = 4 THEN 1 END) AS offline_count,\n" + | ||
| 80 | + " COUNT(utgr.iot_terminal_id) AS total_devices\n" + | ||
| 81 | + "FROM user_terminal_group utg\n" + | ||
| 82 | + "LEFT JOIN user_terminal_group_relation utgr ON utg.id = utgr.iot_terminal_group_id\n" + | ||
| 83 | + "LEFT JOIN iot_terminal it ON utgr.iot_terminal_id = it.id\n" + | ||
| 84 | + "WHERE utg.user_info_id = "+SecurityUtils.getUserId()+typeStr+" \n" + | ||
| 85 | + "GROUP BY utg.id, utg.name\n" + | ||
| 86 | + "ORDER BY utg.id"); | ||
| 87 | + return AjaxResult.success(list); | ||
| 88 | + } | ||
| 58 | 89 | ||
| 59 | /** | 90 | /** |
| 60 | * 获取终端分组详细信息 | 91 | * 获取终端分组详细信息 |
| @@ -94,9 +94,9 @@ public class UserTerminalGroupRelationController extends BaseController | @@ -94,9 +94,9 @@ public class UserTerminalGroupRelationController extends BaseController | ||
| 94 | } | 94 | } |
| 95 | if (null != product_id) | 95 | if (null != product_id) |
| 96 | { | 96 | { |
| 97 | - stringBuffer.append(" AND b.product_id="+product_id); | 97 | + stringBuffer.append(" AND b.product_id="+product_id); |
| 98 | } | 98 | } |
| 99 | - List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT b.*,a.id group_id FROM `user_terminal_group_relation` a LEFT JOIN `iot_terminal` b ON a.`iot_terminal_id`=b.`id` WHERE a.user_info_id="+SecurityUtils.getUserId().intValue()+stringBuffer); | 99 | + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT b.*,a.id group_id,c.`things_model_value` host_things_model_value,c.`things_model_config` host_things_model_config FROM `user_terminal_group_relation` a LEFT JOIN `iot_terminal` b ON a.`iot_terminal_id`=b.`id` LEFT JOIN `iot_device` c ON b.`device_id`=c.`client_id` WHERE a.user_info_id="+SecurityUtils.getUserId().intValue()+stringBuffer); |
| 100 | return AjaxResult.success(list); | 100 | return AjaxResult.success(list); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| @@ -189,11 +189,11 @@ public class UserTerminalGroupRelationController extends BaseController | @@ -189,11 +189,11 @@ public class UserTerminalGroupRelationController extends BaseController | ||
| 189 | @Transactional | 189 | @Transactional |
| 190 | @Log(title = "终端分组关系", businessType = BusinessType.DELETE) | 190 | @Log(title = "终端分组关系", businessType = BusinessType.DELETE) |
| 191 | @DeleteMapping("/{ids}") | 191 | @DeleteMapping("/{ids}") |
| 192 | - public AjaxResult remove(@PathVariable Integer[] ids) | 192 | + public AjaxResult remove(@PathVariable String[] ids) |
| 193 | { | 193 | { |
| 194 | String idss = "'"+Arrays.toString(ids).replace(",","','")+"'"; | 194 | String idss = "'"+Arrays.toString(ids).replace(",","','")+"'"; |
| 195 | publicService.updateBySql("UPDATE `iot_terminal` SET user_info_id=null WHERE id IN("+idss+")"); | 195 | publicService.updateBySql("UPDATE `iot_terminal` SET user_info_id=null WHERE id IN("+idss+")"); |
| 196 | - return toAjax(userTerminalGroupRelationService.deleteUserTerminalGroupRelationByIds(ids)); | 196 | + return toAjax(userTerminalGroupRelationService.deleteUserTerminalGroupRelationByTerminalIds(ids)); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | @ApiOperation("统计用户设备") | 199 | @ApiOperation("统计用户设备") |
| @@ -240,37 +240,47 @@ public class UserTerminalGroupRelationController extends BaseController | @@ -240,37 +240,47 @@ public class UserTerminalGroupRelationController extends BaseController | ||
| 240 | public AjaxResult addIotTerminalRelation(@RequestBody AddIotTerminalRelationDto addIotTerminalRelationDto) | 240 | public AjaxResult addIotTerminalRelation(@RequestBody AddIotTerminalRelationDto addIotTerminalRelationDto) |
| 241 | { | 241 | { |
| 242 | Integer userid = SecurityUtils.getUserId().intValue(); | 242 | Integer userid = SecurityUtils.getUserId().intValue(); |
| 243 | - String deviceId = addIotTerminalRelationDto.getDeviceId(); | ||
| 244 | - IotDevice iotDevice = iotDeviceService.selectIotDeviceByClient_id(deviceId); | ||
| 245 | - List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT a.* FROM `user_terminal_group` a LEFT JOIN `user_terminal_group_relation` b ON a.`id`=b.`iot_terminal_group_id` LEFT JOIN `iot_terminal` c ON c.`id`=b.`iot_terminal_id` WHERE c.`device_id`='"+deviceId+"'"); | ||
| 246 | - Integer groupId = null; | ||
| 247 | - String grouName = null; | ||
| 248 | - if (null != list && list.size()>0) | 243 | + UserTerminalGroup userTerminalGroup = userTerminalGroupService.selectUserTerminalGroupById(addIotTerminalRelationDto.getGroupId()); |
| 244 | + if(null == userTerminalGroup) | ||
| 249 | { | 245 | { |
| 250 | - groupId = (Integer) list.get(0).get("id"); | ||
| 251 | - grouName = (String) list.get(0).get("name"); | ||
| 252 | - }else{ | ||
| 253 | - UserTerminalGroup userTerminalGroup = new UserTerminalGroup(); | ||
| 254 | - userTerminalGroup.setUser_info_id(userid); | ||
| 255 | - userTerminalGroup.setName(iotDevice.getName()); | ||
| 256 | - userTerminalGroup.setCreate_time(DateUtils.getNowTimeMilly()); | ||
| 257 | - userTerminalGroup.setGroup_type(addIotTerminalRelationDto.getGroupType()); | ||
| 258 | - userTerminalGroupService.insertUserTerminalGroup(userTerminalGroup); | ||
| 259 | - groupId = userTerminalGroup.getId(); | ||
| 260 | - grouName = userTerminalGroup.getName(); | 246 | + return AjaxResult.error("请选择正确的分组"); |
| 261 | } | 247 | } |
| 248 | + if(userid - userTerminalGroup.getUser_info_id()!=0) | ||
| 249 | + { | ||
| 250 | + return AjaxResult.error("该分组不属于你"); | ||
| 251 | + } | ||
| 252 | + List<UserTerminalGroupRelation> list = new ArrayList<>(); | ||
| 253 | + String ids = ""; | ||
| 262 | for (IotTerminal iotTerminal:addIotTerminalRelationDto.getIotTerminalList()) | 254 | for (IotTerminal iotTerminal:addIotTerminalRelationDto.getIotTerminalList()) |
| 263 | { | 255 | { |
| 256 | + if(!"".equals(ids)) | ||
| 257 | + { | ||
| 258 | + ids += ","; | ||
| 259 | + } | ||
| 260 | + ids += "'"+iotTerminal.getId()+"'"; | ||
| 261 | + | ||
| 264 | iotTerminalService.updateIotTerminal(iotTerminal); | 262 | iotTerminalService.updateIotTerminal(iotTerminal); |
| 263 | + | ||
| 265 | UserTerminalGroupRelation userTerminalGroupRelation = new UserTerminalGroupRelation(); | 264 | UserTerminalGroupRelation userTerminalGroupRelation = new UserTerminalGroupRelation(); |
| 266 | userTerminalGroupRelation.setIot_terminal_id(iotTerminal.getId()); | 265 | userTerminalGroupRelation.setIot_terminal_id(iotTerminal.getId()); |
| 267 | - userTerminalGroupRelation.setIot_terminal_group_id(groupId); | 266 | + userTerminalGroupRelation.setIot_terminal_group_id(addIotTerminalRelationDto.getGroupId()); |
| 268 | userTerminalGroupRelation.setUser_info_id(userid); | 267 | userTerminalGroupRelation.setUser_info_id(userid); |
| 269 | userTerminalGroupRelation.setCreate_time(DateUtils.getNowTimeMilly()); | 268 | userTerminalGroupRelation.setCreate_time(DateUtils.getNowTimeMilly()); |
| 270 | - userTerminalGroupRelation.setIot_terminal_group_name(grouName); | 269 | + userTerminalGroupRelation.setIot_terminal_group_name(userTerminalGroup.getName()); |
| 271 | userTerminalGroupRelation.setProduct_id(iotTerminal.getProduct_id()); | 270 | userTerminalGroupRelation.setProduct_id(iotTerminal.getProduct_id()); |
| 272 | - userTerminalGroupRelationService.insertUserTerminalGroupRelation(userTerminalGroupRelation); | 271 | + list.add(userTerminalGroupRelation); |
| 272 | + } | ||
| 273 | + List<Map<String,Object>> userIdlist = publicService.getObjectListBySQL("SELECT user_info_id,device_id FROM `iot_terminal` WHERE device_id IN(SELECT device_id FROM `iot_terminal` WHERE id IN("+ids+"))"); | ||
| 274 | + if(null != userIdlist && userIdlist.size() >0) | ||
| 275 | + { | ||
| 276 | + for (Map<String,Object> map:userIdlist) | ||
| 277 | + { | ||
| 278 | + if(null != map.get("user_info_id") && !String.valueOf(map.get("user_info_id")).equals(String.valueOf(userid))) | ||
| 279 | + { | ||
| 280 | + return AjaxResult.error("设备"+map.get("device_id")+"已被其他人绑定"); | ||
| 281 | + } | ||
| 282 | + } | ||
| 273 | } | 283 | } |
| 274 | - return toAjax(1); | 284 | + return toAjax(publicService.insertAll(list)); |
| 275 | } | 285 | } |
| 276 | } | 286 | } |
lh-modules/lh-device-protocol-parser/lh-device-protocol-agreement/lh-device-mn-plc/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-device-protocol-agreement</artifactId> | ||
| 9 | + <version>1.0-SNAPSHOT</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-device-mn-plc</artifactId> | ||
| 13 | + | ||
| 14 | + <description> | ||
| 15 | + 解析明牛plc上传的数据 | ||
| 16 | + </description> | ||
| 17 | + | ||
| 18 | + <properties> | ||
| 19 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 20 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 21 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 22 | + </properties> | ||
| 23 | + | ||
| 24 | + <dependencies> | ||
| 25 | + <dependency> | ||
| 26 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 27 | + <artifactId>lh-device-protocol-factory</artifactId> | ||
| 28 | + </dependency> | ||
| 29 | + </dependencies> | ||
| 30 | +</project> |
| 1 | +package com.zhonglai.luhui.device.protocol.mnplc.analysis; | ||
| 2 | + | ||
| 3 | +import com.google.gson.JsonElement; | ||
| 4 | +import com.google.gson.JsonObject; | ||
| 5 | +import com.google.gson.JsonPrimitive; | ||
| 6 | +import com.ruoyi.common.utils.GsonConstructor; | ||
| 7 | +import com.ruoyi.common.utils.StringUtils; | ||
| 8 | +import com.zhonglai.luhui.device.analysis.comm.clien.ClienConnection; | ||
| 9 | +import com.zhonglai.luhui.device.analysis.comm.clien.impl.ClienConnectionImpl; | ||
| 10 | +import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto; | ||
| 11 | +import com.zhonglai.luhui.device.analysis.comm.factory.Topic; | ||
| 12 | +import com.zhonglai.luhui.device.analysis.dto.MessageCode; | ||
| 13 | +import com.zhonglai.luhui.device.analysis.util.TopicUtil; | ||
| 14 | +import com.zhonglai.luhui.device.domain.IotProductPayloadModelNumber; | ||
| 15 | +import com.zhonglai.luhui.device.domain.IotProductPlcDevice; | ||
| 16 | +import com.zhonglai.luhui.device.protocol.factory.analysis.ProtocolParserFactory; | ||
| 17 | +import com.zhonglai.luhui.device.protocol.factory.analysis.topic.Online; | ||
| 18 | +import com.zhonglai.luhui.device.protocol.factory.config.DeviceCach; | ||
| 19 | +import com.zhonglai.luhui.device.protocol.factory.config.PLCDeviceChannelRelationConfig; | ||
| 20 | +import com.zhonglai.luhui.device.protocol.factory.config.ProductPayloadModelNumberCach; | ||
| 21 | +import com.zhonglai.luhui.device.protocol.factory.control.DeviceCommandListenService; | ||
| 22 | +import com.zhonglai.luhui.device.protocol.factory.dto.AnalysisResult; | ||
| 23 | +import com.zhonglai.luhui.device.protocol.factory.dto.ParserDeviceHostDto; | ||
| 24 | +import com.zhonglai.luhui.device.protocol.mnplc.analysis.topic.AddPost; | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +public class MNPLCProtocolParserFactoryImpl implements ProtocolParserFactory { | ||
| 28 | + private static final String topicModel = "/{{roleid}}/{{username}}/{{clientid}}/{{payloadtype}}/{{topicType}}"; | ||
| 29 | + @Override | ||
| 30 | + public Topic analysisTopic(String topicStr) { | ||
| 31 | + Topic topic = TopicUtil.initTopicFromModelStr(topicStr,topicModel); | ||
| 32 | + return topic; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public AnalysisResult analysisPayload(Topic topic, byte[] payload) { | ||
| 37 | + ParserDeviceHostDto parserDeviceHostDto = DeviceCach.getDeviceHost(topic.getClientid()); | ||
| 38 | + | ||
| 39 | + switch (topic.getTopicType()) | ||
| 40 | + { | ||
| 41 | + case "online": | ||
| 42 | + return new Online().analysisPayload(payload); | ||
| 43 | + case "ONLINE": | ||
| 44 | + return new Online().analysisPayload(payload); | ||
| 45 | + case "ADD_POST": | ||
| 46 | + return new AddPost().analysisPayload(toformatPayLoad(parserDeviceHostDto,GsonConstructor.get().fromJson(new String(payload),JsonObject.class))); | ||
| 47 | + case "PUT_REQ": | ||
| 48 | + JsonObject data = null; | ||
| 49 | + | ||
| 50 | + | ||
| 51 | + if(DeviceCommandListenService.hasClienConnection(topic.getClientid())) | ||
| 52 | + { | ||
| 53 | + ClienConnection clienConnection = DeviceCommandListenService.getClienConnection(topic.getClientid()); | ||
| 54 | + if(null != clienConnection && clienConnection instanceof ClienConnectionImpl) | ||
| 55 | + { | ||
| 56 | + ClienConnectionImpl clienConnectionImpl = (ClienConnectionImpl) clienConnection; | ||
| 57 | + if(null != clienConnectionImpl.getCommd()) | ||
| 58 | + { | ||
| 59 | + data = GsonConstructor.get().fromJson(toformatPayLoad(parserDeviceHostDto,GsonConstructor.get().fromJson(new String(clienConnectionImpl.getCommd()),JsonObject.class)),JsonObject.class); | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + JsonObject jsonObject = GsonConstructor.get().fromJson(new String(payload),JsonObject.class); | ||
| 64 | + ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto(); | ||
| 65 | + if(jsonObject.has("result") && "1".equals(jsonObject.get("result").getAsString())) | ||
| 66 | + { | ||
| 67 | + apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE); | ||
| 68 | + apiClientRePlyDto.setMessage("操作成功,等待"+parserDeviceHostDto.getDevice_life()+"秒后返回结果"); | ||
| 69 | + } | ||
| 70 | + return new AnalysisResult(false, true, data, apiClientRePlyDto); | ||
| 71 | + default: | ||
| 72 | + return new AnalysisResult(false,false,null); | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + private String toformatPayLoad(ParserDeviceHostDto parserDeviceHostDto, JsonObject jsonObject) | ||
| 77 | + { | ||
| 78 | + if(null != parserDeviceHostDto && null != parserDeviceHostDto.getIotProduct()) | ||
| 79 | + { | ||
| 80 | +// Integer iotProductid = parserDeviceHostDto.getIotProduct().getId(); | ||
| 81 | + JsonObject rj = new JsonObject(); | ||
| 82 | + for (String key : jsonObject.keySet()) | ||
| 83 | + { | ||
| 84 | + String[] keyArr = key.split("_"); | ||
| 85 | + String identifier = keyArr[1]; | ||
| 86 | + String temp_data_identifier = keyArr[keyArr.length-1]; | ||
| 87 | + String data_identifier = temp_data_identifier; | ||
| 88 | + | ||
| 89 | + String number = "0"; | ||
| 90 | + String number_name = "PLC主机"; | ||
| 91 | + if ("SYS".equals(identifier)) | ||
| 92 | + { | ||
| 93 | + }else{ | ||
| 94 | + IotProductPlcDevice iotProductPlcDevice = PLCDeviceChannelRelationConfig.getChannelRelation(identifier); | ||
| 95 | + if(null == iotProductPlcDevice) | ||
| 96 | + { | ||
| 97 | + System.out.println("未找到设备通道关系:"+identifier); | ||
| 98 | + continue; | ||
| 99 | + } | ||
| 100 | + number = keyArr[0]+"_"+iotProductPlcDevice.getNumbers().split(",")[0]+"_"+keyArr[2]; | ||
| 101 | + number_name = keyArr[0]+"区"+keyArr[2]+"号"+iotProductPlcDevice.getName()+keyArr[2]; | ||
| 102 | + if("YEL".equals(identifier)) | ||
| 103 | + { | ||
| 104 | + int type = jsonObject.get(key.replace("SENSOR","TYPE")).getAsInt(); | ||
| 105 | + if(type==0) | ||
| 106 | + { | ||
| 107 | + continue; | ||
| 108 | + } | ||
| 109 | + number += "_"+keyArr[3]; | ||
| 110 | + number_name += keyArr[3]+"号探头"; | ||
| 111 | + if (data_identifier.equals("SENSOR")) | ||
| 112 | + { | ||
| 113 | + switch (type) | ||
| 114 | + { | ||
| 115 | + case 3: | ||
| 116 | + data_identifier = "pH"; | ||
| 117 | + break; | ||
| 118 | + case 5: | ||
| 119 | + data_identifier = "dom"; | ||
| 120 | + break; | ||
| 121 | + case 16: | ||
| 122 | + data_identifier = "yw"; | ||
| 123 | + break; | ||
| 124 | + case 17: | ||
| 125 | + data_identifier = "yl"; | ||
| 126 | + break; | ||
| 127 | + } | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + if(StringUtils.isNotEmpty(number)) | ||
| 133 | + { | ||
| 134 | + JsonObject numberjson = rj.getAsJsonObject(number); | ||
| 135 | + if(null == numberjson) | ||
| 136 | + { | ||
| 137 | + numberjson = new JsonObject(); | ||
| 138 | + if(StringUtils.isNoneBlank(number_name)) | ||
| 139 | + { | ||
| 140 | + numberjson.addProperty("%sysdeviceinfoname%",number_name); | ||
| 141 | + } | ||
| 142 | + rj.add(number,numberjson); | ||
| 143 | + } | ||
| 144 | + numberjson.add(data_identifier,jsonObject.get(key).isJsonNull()?new JsonPrimitive(0):jsonObject.get(key)); | ||
| 145 | + | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + return rj.toString(); | ||
| 149 | + } | ||
| 150 | + return new JsonObject().toString(); | ||
| 151 | + } | ||
| 152 | +} |
| 1 | +package com.zhonglai.luhui.device.protocol.mnplc.analysis.topic; | ||
| 2 | + | ||
| 3 | +import com.google.gson.JsonObject; | ||
| 4 | +import com.ruoyi.common.utils.GsonConstructor; | ||
| 5 | +import com.zhonglai.luhui.device.protocol.factory.dto.AnalysisResult; | ||
| 6 | + | ||
| 7 | +public class AddPost { | ||
| 8 | + public AnalysisResult analysisPayload( byte[] payload) | ||
| 9 | + { | ||
| 10 | + return analysisPayload(new String(payload)); | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + public AnalysisResult analysisPayload(String payload) | ||
| 14 | + { | ||
| 15 | + JsonObject jsonObject = GsonConstructor.get().fromJson(payload, JsonObject.class); | ||
| 16 | + return new AnalysisResult(false,false,jsonObject); | ||
| 17 | + } | ||
| 18 | +} |
| 1 | +package com.zhonglai.luhui.device.protocol.mnplc.control; | ||
| 2 | + | ||
| 3 | +import com.google.gson.JsonElement; | ||
| 4 | +import com.google.gson.JsonObject; | ||
| 5 | +import com.google.gson.reflect.TypeToken; | ||
| 6 | +import com.ruoyi.common.utils.DateUtils; | ||
| 7 | +import com.ruoyi.common.utils.GsonConstructor; | ||
| 8 | +import com.zhonglai.luhui.device.analysis.comm.factory.Topic; | ||
| 9 | +import com.zhonglai.luhui.device.domain.IotProduct; | ||
| 10 | +import com.zhonglai.luhui.device.domain.IotProductPlcDevice; | ||
| 11 | +import com.zhonglai.luhui.device.protocol.factory.config.DeviceCach; | ||
| 12 | +import com.zhonglai.luhui.device.protocol.factory.config.PLCDeviceChannelRelationConfig; | ||
| 13 | +import com.zhonglai.luhui.device.protocol.factory.control.DeviceCommandServiceFactory; | ||
| 14 | +import com.zhonglai.luhui.device.protocol.factory.dto.NoticeMessageDto; | ||
| 15 | +import com.zhonglai.luhui.device.protocol.factory.dto.ParserDeviceHostDto; | ||
| 16 | +import org.slf4j.Logger; | ||
| 17 | +import org.slf4j.LoggerFactory; | ||
| 18 | + | ||
| 19 | +import java.lang.reflect.Type; | ||
| 20 | +import java.util.Map; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * 指令控制监听实现 | ||
| 24 | + */ | ||
| 25 | +public class DeviceCommandListenServiceImpl implements DeviceCommandServiceFactory { | ||
| 26 | + private static final String topicModel = "/{{roleid}}/{{username}}/{{clientid}}/{{payloadtype}}/{{topicType}}"; | ||
| 27 | + | ||
| 28 | + private static final Logger log = LoggerFactory.getLogger(DeviceCommandListenServiceImpl.class); | ||
| 29 | + @Override | ||
| 30 | + public NoticeMessageDto read(String deviceId, JsonObject jsonObject) { | ||
| 31 | + return null; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + public NoticeMessageDto write(String deviceId, JsonObject jsonObject) { | ||
| 36 | + ParserDeviceHostDto parserDeviceHostDto = DeviceCach.getDeviceHost(deviceId); | ||
| 37 | + | ||
| 38 | + Topic topic = getWriteTopic(deviceId,parserDeviceHostDto.getIotProduct()); | ||
| 39 | + NoticeMessageDto noticeMessageDto = new NoticeMessageDto(); | ||
| 40 | + noticeMessageDto.setTopic(topic); | ||
| 41 | + noticeMessageDto.setTopicconfig(topicModel); | ||
| 42 | + | ||
| 43 | + //将jsonObject里面的两层键值比如:{"1":{"key","value","key1",1}}提取成一层放在commdjson里面如{"key":"value","key1":1} | ||
| 44 | + JsonObject commdjson = flattenJsonObject(jsonObject); | ||
| 45 | + | ||
| 46 | + noticeMessageDto.setCommd(commdjson.toString().getBytes()); | ||
| 47 | + | ||
| 48 | + return noticeMessageDto; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + @Override | ||
| 52 | + public NoticeMessageDto notice(String deviceId, JsonObject jsonObject) { | ||
| 53 | + return null; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public NoticeMessageDto host(String deviceId, JsonObject jsonObject) { | ||
| 58 | + ParserDeviceHostDto parserDeviceHostDto = DeviceCach.getDeviceHost(deviceId); | ||
| 59 | + | ||
| 60 | + Topic topic = new Topic(); | ||
| 61 | + topic.setTopicType("HOST"); | ||
| 62 | + topic.setClientid(deviceId); | ||
| 63 | + topic.setRoleid(parserDeviceHostDto.getIotProduct().getRole_id()+""); | ||
| 64 | + topic.setUsername(parserDeviceHostDto.getIotProduct().getMqtt_username()); | ||
| 65 | + topic.setPayloadtype("Json"); | ||
| 66 | + topic.setMessageid(DateUtils.getNowTimeMilly()+""); | ||
| 67 | + | ||
| 68 | + NoticeMessageDto noticeMessageDto = new NoticeMessageDto(); | ||
| 69 | + noticeMessageDto.setTopic(topic); | ||
| 70 | + noticeMessageDto.setTopicconfig(topicModel); | ||
| 71 | + | ||
| 72 | + noticeMessageDto.setCommd(jsonObject.toString().getBytes()); | ||
| 73 | + | ||
| 74 | + return noticeMessageDto; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 将嵌套的JsonObject扁平化。 | ||
| 79 | + * | ||
| 80 | + * @param jsonObject 嵌套的JsonObject | ||
| 81 | + * @return 扁平化的JsonObject | ||
| 82 | + */ | ||
| 83 | + public JsonObject flattenJsonObject(JsonObject jsonObject) { | ||
| 84 | + // 使用Gson将嵌套的JsonObject转换为Map | ||
| 85 | + Type typeOfMap = new TypeToken<Map<String, JsonElement>>(){}.getType(); | ||
| 86 | + Map<String, JsonElement> map = GsonConstructor.get().fromJson(jsonObject, typeOfMap); | ||
| 87 | + | ||
| 88 | + // 创建一个新的JsonObject用于存储扁平化的结果 | ||
| 89 | + JsonObject flatJson = new JsonObject(); | ||
| 90 | + | ||
| 91 | + // 遍历Map中的所有键值对 | ||
| 92 | + for (Map.Entry<String, JsonElement> entry : map.entrySet()) { | ||
| 93 | + JsonElement value = entry.getValue(); | ||
| 94 | + | ||
| 95 | + String key = entry.getKey(); | ||
| 96 | + // 检查值是否为JsonObject | ||
| 97 | + if (value.isJsonObject()) { | ||
| 98 | + // 如果是JsonObject,则将其键值对添加到flatJson中 | ||
| 99 | + JsonObject innerJson = value.getAsJsonObject(); | ||
| 100 | + for (Map.Entry<String, JsonElement> innerEntry : innerJson.entrySet()) { | ||
| 101 | + flatJson.add(reverseKey(key,innerEntry.getKey()), innerEntry.getValue()); | ||
| 102 | + } | ||
| 103 | + } else { | ||
| 104 | + // 如果不是JsonObject,则直接添加到flatJson中 | ||
| 105 | + flatJson.add(entry.getKey(), value); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + return flatJson; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + private Topic getWriteTopic(String deviceId, IotProduct iotProduct) | ||
| 113 | + { | ||
| 114 | + Topic topic = new Topic(); | ||
| 115 | + topic.setTopicType("PUT"); | ||
| 116 | + topic.setClientid(deviceId); | ||
| 117 | + topic.setRoleid(iotProduct.getRole_id()+""); | ||
| 118 | + topic.setUsername(iotProduct.getMqtt_username()); | ||
| 119 | + topic.setPayloadtype("Json"); | ||
| 120 | + return topic; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * number + dataIdentifier 逆向解析为原始上报 key | ||
| 125 | + * | ||
| 126 | + * 支持: | ||
| 127 | + * SYS → A_SYS_1_temp | ||
| 128 | + * YEL 探头 → A_YEL_1_SENSOR_3 和 A_YEL_1_TYPE_3 | ||
| 129 | + * 普通设备 → A_ABC_1_value | ||
| 130 | + */ | ||
| 131 | + private String reverseKey(String number, String dataIdentifier) | ||
| 132 | + { | ||
| 133 | + String[] arr = number.split("_"); | ||
| 134 | + if (arr.length < 3) { | ||
| 135 | + return null; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + String area = arr[0]; // A | ||
| 139 | + String mappedNumber = arr[1]; // 09 | ||
| 140 | + String index = arr[2]; // 1 | ||
| 141 | + String probe = arr.length > 3 ? arr[3] : null; // 探头编号(如果有) | ||
| 142 | + | ||
| 143 | + // 反向查找设备类型(identifier) | ||
| 144 | + String identifier = getIdentifierByMappedNumber(mappedNumber); | ||
| 145 | + if (identifier == null) { | ||
| 146 | + return null; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + // ---------- SYS 类型 ---------- | ||
| 150 | + if ("SYS".equals(identifier)) | ||
| 151 | + { | ||
| 152 | + // 生成:A_SYS_1_xxx | ||
| 153 | + return area + "_SYS_" + index + "_" + dataIdentifier; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + // ---------- YEL(探头设备) ---------- | ||
| 157 | + if ("YEL".equals(identifier)) | ||
| 158 | + { | ||
| 159 | + if (probe == null) { | ||
| 160 | + // YEL 必须包含探头编号 | ||
| 161 | + return null; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + // dataIdentifier 是业务数据(例如 pH、doh-set) | ||
| 165 | + // 原始数据分为 SENSOR_xxx + TYPE_xxx | ||
| 166 | + // 本方法根据 dataIdentifier 只恢复 SENSOR_xxx | ||
| 167 | + return area + "_YEL_" + index + "_" + probe + "_" + dataIdentifier; | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + // ---------- 普通设备 ---------- | ||
| 171 | + // 例如:A_ABC_1_value | ||
| 172 | + return area + "_" + identifier + "_" + index | ||
| 173 | + + (probe != null ? "_" + probe : "") | ||
| 174 | + + "_" + dataIdentifier; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + /** | ||
| 178 | + * 根据 PLC 设备 numbers 值反推 identifier。 | ||
| 179 | + */ | ||
| 180 | + private String getIdentifierByMappedNumber(String mappedNumber) | ||
| 181 | + { | ||
| 182 | + for (String identifier : PLCDeviceChannelRelationConfig.getAllIdentifiers()) | ||
| 183 | + { | ||
| 184 | + IotProductPlcDevice dev = PLCDeviceChannelRelationConfig.getChannelRelation(identifier); | ||
| 185 | + if (dev == null) continue; | ||
| 186 | + | ||
| 187 | + for (String num : dev.getNumbers().split(",")) { | ||
| 188 | + if (num.equals(mappedNumber)) { | ||
| 189 | + return identifier; | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + return null; | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | +} |
| 1 | +package com.zhonglai.luhui.device.protocol.mnplc.purification; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson.JSONObject; | ||
| 4 | +import com.google.gson.JsonElement; | ||
| 5 | +import com.google.gson.JsonObject; | ||
| 6 | +import com.ruoyi.common.utils.GsonConstructor; | ||
| 7 | +import com.ruoyi.common.utils.spring.SpringUtils; | ||
| 8 | +import com.zhonglai.luhui.device.analysis.comm.dto.DeviceSensorData; | ||
| 9 | +import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelDataTypeEnum; | ||
| 10 | +import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelItemBase; | ||
| 11 | +import com.zhonglai.luhui.device.analysis.comm.factory.Topic; | ||
| 12 | +import com.zhonglai.luhui.device.analysis.comm.util.DateUtils; | ||
| 13 | +import com.zhonglai.luhui.device.domain.IotThingsModel; | ||
| 14 | +import com.zhonglai.luhui.device.protocol.factory.dto.*; | ||
| 15 | +import com.zhonglai.luhui.device.protocol.factory.purification.ProtocolPurificationFactory; | ||
| 16 | +import com.zhonglai.luhui.device.protocol.factory.service.IotThingsModelService; | ||
| 17 | +import org.apache.commons.lang3.EnumUtils; | ||
| 18 | + | ||
| 19 | +import java.util.ArrayList; | ||
| 20 | +import java.util.List; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * 默认的清洗服务 | ||
| 24 | + */ | ||
| 25 | +public class MNPLCProtocolPurificationFactoryImpl implements ProtocolPurificationFactory { | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public ProtocolPurificationModel purification(Integer product_id,Topic topic, AnalysisResult analysisResult ) { | ||
| 29 | + JsonObject protocolParserModel = analysisResult.getJsonObject(); | ||
| 30 | + if(null != protocolParserModel && protocolParserModel.size()!=0) | ||
| 31 | + { | ||
| 32 | + ProtocolPurificationModel protocolPurificationModel = new ProtocolPurificationModel(); | ||
| 33 | + ParserDeviceHostDto parserDeviceHostDto = analysisHost(product_id,topic,protocolParserModel,protocolPurificationModel.getDeviceSensorDataList()); | ||
| 34 | + protocolPurificationModel.setParserDeviceHostDto(parserDeviceHostDto); | ||
| 35 | + | ||
| 36 | + List<ParserDeviceInfoDto> parserDeviceInfoDtoList = analysisDeviceInfo(parserDeviceHostDto.getUpdateTime(),product_id,topic,protocolParserModel,protocolPurificationModel.getDeviceSensorDataList()); | ||
| 37 | + protocolPurificationModel.setParserDeviceInfoDtoList(parserDeviceInfoDtoList); | ||
| 38 | + return protocolPurificationModel; | ||
| 39 | + } | ||
| 40 | + return null; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + private ParserDeviceHostDto analysisHost(Integer product_id,Topic topic, JsonObject data,List<DeviceSensorData> deviceSensorDataList ) | ||
| 44 | + { | ||
| 45 | + int time = DateUtils.getNowTimeMilly(); | ||
| 46 | + if(data.has("0")) | ||
| 47 | + { | ||
| 48 | + JsonObject jsonObjectData = data.get("0").getAsJsonObject(); | ||
| 49 | + JsonObject summary = null; | ||
| 50 | + //解析设备摘要 | ||
| 51 | + if(jsonObjectData.has("summary") && null != jsonObjectData.get("summary") && jsonObjectData.get("summary").isJsonObject()) | ||
| 52 | + { | ||
| 53 | + summary = jsonObjectData.get("summary").getAsJsonObject(); | ||
| 54 | + jsonObjectData.remove("summary"); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + String online = null; | ||
| 58 | + //解析在线状态 | ||
| 59 | + if(jsonObjectData.has("online") && null != jsonObjectData.get("online")) | ||
| 60 | + { | ||
| 61 | + online = jsonObjectData.get("online").getAsString(); | ||
| 62 | + jsonObjectData.remove("online"); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + //信号 | ||
| 66 | + Integer rssi = null; | ||
| 67 | + if(jsonObjectData.has("rssi") && null != jsonObjectData.get("rssi")) | ||
| 68 | + { | ||
| 69 | + rssi = jsonObjectData.get("rssi").getAsInt(); | ||
| 70 | + jsonObjectData.remove("rssi"); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + ParserDeviceHostDto parserDeviceHostDto = null; | ||
| 74 | + if(null != jsonObjectData && jsonObjectData.size() != 0) | ||
| 75 | + { | ||
| 76 | + parserDeviceHostDto = analysisJsonData(time,"0",product_id,topic,jsonObjectData).pushDeviceSensorData(deviceSensorDataList).toParserDeviceHostDto(topic.getClientid(),time); | ||
| 77 | + } | ||
| 78 | + if(null == parserDeviceHostDto) | ||
| 79 | + { | ||
| 80 | + parserDeviceHostDto = new ParserDeviceHostDto(); | ||
| 81 | + parserDeviceHostDto.setId(topic.getClientid()); | ||
| 82 | + } | ||
| 83 | + if(null != summary && summary.size() != 0) | ||
| 84 | + { | ||
| 85 | + parserDeviceHostDto.setSummary(summary); | ||
| 86 | + } | ||
| 87 | + parserDeviceHostDto.setOnline(online); | ||
| 88 | + parserDeviceHostDto.setRssi(rssi); | ||
| 89 | + parserDeviceHostDto.setUpdateTime(time); | ||
| 90 | + return parserDeviceHostDto; | ||
| 91 | + } | ||
| 92 | + ParserDeviceHostDto parserDeviceHostDto = new ParserDeviceHostDto(); | ||
| 93 | + parserDeviceHostDto.setId(topic.getClientid()); | ||
| 94 | + parserDeviceHostDto.setUpdateTime(time); | ||
| 95 | + return parserDeviceHostDto; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + private List<ParserDeviceInfoDto> analysisDeviceInfo(Integer time,Integer product_id,Topic topic, JsonObject data,List<DeviceSensorData> deviceSensorDataList) | ||
| 99 | + { | ||
| 100 | + List<ParserDeviceInfoDto> list = new ArrayList<>(); | ||
| 101 | + | ||
| 102 | + for (String key:data.keySet()) | ||
| 103 | + { | ||
| 104 | + if(!key.equals("0") && data.get(key).isJsonObject()) | ||
| 105 | + { | ||
| 106 | + ParserDeviceInfoDto parserDeviceInfoDto = analysisJsonData(time,key,product_id,topic,data.get(key).getAsJsonObject()).pushDeviceSensorData(deviceSensorDataList).toParserDeviceInfoDto(topic.getClientid()+"_"+key,time); | ||
| 107 | + list.add(parserDeviceInfoDto); | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + return list; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + private AnalysisDto analysisJsonData(Integer time,String sensorNumber,Integer product_id,Topic topic, JsonObject jsonObjectData ) | ||
| 115 | + { | ||
| 116 | + if(null != jsonObjectData && jsonObjectData.size() !=0) | ||
| 117 | + { | ||
| 118 | + AnalysisDto analysisDto = new AnalysisDto(); | ||
| 119 | + | ||
| 120 | + JsonObject things_model_value = new JsonObject(); //存放数据 | ||
| 121 | + analysisDto.setThings_model_value(things_model_value); | ||
| 122 | + | ||
| 123 | + JsonObject things_model_config = new JsonObject(); //存放配置 | ||
| 124 | + analysisDto.setThings_model_config(things_model_config); | ||
| 125 | + for (String key: jsonObjectData.keySet()) | ||
| 126 | + { | ||
| 127 | + IotThingsModel thingsModel = SpringUtils.getBean(IotThingsModelService.class).getIotThingsModel(product_id, key); | ||
| 128 | + | ||
| 129 | + JsonElement jsonElement = jsonObjectData.get(key); | ||
| 130 | + if(null != jsonElement && !jsonElement.isJsonNull() ) | ||
| 131 | + { | ||
| 132 | + ThingsModelItemBase thingsModelItemBase = getThingsModelItemBase(thingsModel,jsonElement); | ||
| 133 | + if(null == thingsModelItemBase || !thingsModelItemBase.checkValue()) | ||
| 134 | + { | ||
| 135 | + continue; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + switch (thingsModel.getIs_config()) | ||
| 139 | + { | ||
| 140 | + case 0: | ||
| 141 | + things_model_value.add(key,GsonConstructor.get().fromJson(JSONObject.toJSONString(thingsModelItemBase),JsonObject.class)); | ||
| 142 | + break; | ||
| 143 | + case 1: | ||
| 144 | + things_model_config.add(key,GsonConstructor.get().fromJson(JSONObject.toJSONString(thingsModelItemBase),JsonObject.class)); | ||
| 145 | + break; | ||
| 146 | + case 2: | ||
| 147 | + things_model_config.add(key,GsonConstructor.get().fromJson(JSONObject.toJSONString(thingsModelItemBase),JsonObject.class)); | ||
| 148 | + things_model_value.add(key,GsonConstructor.get().fromJson(JSONObject.toJSONString(thingsModelItemBase),JsonObject.class)); | ||
| 149 | + break; | ||
| 150 | + default: | ||
| 151 | + things_model_value.add(key,GsonConstructor.get().fromJson(JSONObject.toJSONString(thingsModelItemBase),JsonObject.class)); | ||
| 152 | + break; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + //记录数据日志 | ||
| 156 | + if(1==thingsModelItemBase.getIs_save_log() ) | ||
| 157 | + { | ||
| 158 | + List<DeviceSensorData> deviceSensorDataList = analysisDto.getDeviceSensorDataList(); | ||
| 159 | + if(null == deviceSensorDataList) | ||
| 160 | + { | ||
| 161 | + deviceSensorDataList = new ArrayList<>(); | ||
| 162 | + analysisDto.setDeviceSensorDataList(deviceSensorDataList); | ||
| 163 | + } | ||
| 164 | + deviceSensorDataList.add(getDeviceSensorData(time,sensorNumber,topic,thingsModel,thingsModelItemBase)); | ||
| 165 | + } | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + return analysisDto; | ||
| 170 | + } | ||
| 171 | + return null; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + private ThingsModelItemBase getThingsModelItemBase(IotThingsModel thingsModel, JsonElement jsonElement) { | ||
| 175 | + String dataType = thingsModel.getData_type(); | ||
| 176 | + ThingsModelDataTypeEnum thingsModelDataTypeEnum; | ||
| 177 | + | ||
| 178 | + try { | ||
| 179 | + if (dataType == null) { | ||
| 180 | + thingsModelDataTypeEnum = ThingsModelDataTypeEnum.STRING; | ||
| 181 | + } else { | ||
| 182 | + // 统一转大写再校验 | ||
| 183 | + String upperType = dataType.toUpperCase(); | ||
| 184 | + if (EnumUtils.isValidEnum(ThingsModelDataTypeEnum.class, upperType)) { | ||
| 185 | + thingsModelDataTypeEnum = Enum.valueOf(ThingsModelDataTypeEnum.class, upperType); | ||
| 186 | + } else { | ||
| 187 | + thingsModelDataTypeEnum = ThingsModelDataTypeEnum.STRING; | ||
| 188 | + } | ||
| 189 | + } | ||
| 190 | + } catch (IllegalArgumentException | NullPointerException e) { | ||
| 191 | + // 容错处理,回退到 STRING | ||
| 192 | + thingsModelDataTypeEnum = ThingsModelDataTypeEnum.STRING; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + return ThingsModelItemBase.newhingsModel(thingsModelDataTypeEnum, thingsModel, jsonElement); | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + | ||
| 199 | + private DeviceSensorData getDeviceSensorData(Integer time,String sensorNumber,Topic topic,IotThingsModel thingsModel,ThingsModelItemBase thingsModelItemBase) | ||
| 200 | + { | ||
| 201 | + DeviceSensorData sensorData = new DeviceSensorData(); | ||
| 202 | + sensorData.setDataType(thingsModel.getIdentifier()); | ||
| 203 | + sensorData.setDataValue(thingsModelItemBase.getSaveView()); | ||
| 204 | + sensorData.setCreatTime(time); | ||
| 205 | + sensorData.setDeviceModel(topic.getUsername()); | ||
| 206 | + if("0".equals(sensorNumber)) | ||
| 207 | + { | ||
| 208 | + sensorData.setDeviceInfoId(topic.getClientid()); | ||
| 209 | + }else { | ||
| 210 | + sensorData.setDeviceInfoId(topic.getClientid()+"_"+sensorNumber); | ||
| 211 | + } | ||
| 212 | + return sensorData; | ||
| 213 | + | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | +} |
不能预览此文件类型
不能预览此文件类型
lh-modules/lh-device-protocol-parser/lh-device-protocol-agreement/lh-device-mn-plc/设备命名规范文档.md
0 → 100644
| 1 | +# 设备命名规范文档 | ||
| 2 | + | ||
| 3 | +## 一、命名总体原则 | ||
| 4 | + | ||
| 5 | +本命名规范用于设备点位、监测量、状态量等字段的统一命名规则。所有命名中的**英文全部使用大写**。 | ||
| 6 | + | ||
| 7 | +更新后的命名结构: | ||
| 8 | + | ||
| 9 | +``` | ||
| 10 | +区域_前缀_编号_参数名 | ||
| 11 | +``` | ||
| 12 | + | ||
| 13 | +### 1. 区域 | ||
| 14 | + | ||
| 15 | +* 使用区域代号,如 A、B、C 或 01、02。 | ||
| 16 | +* 用于区分设备所在区域、池体或生产单元。 | ||
| 17 | + | ||
| 18 | +### 2. 前缀 | ||
| 19 | + | ||
| 20 | +* 依据设备类型使用标准化英文缩写(全部大写)。 | ||
| 21 | +* 同类设备保持一致前缀。 | ||
| 22 | + | ||
| 23 | +### 3. 编号 | ||
| 24 | + | ||
| 25 | +* 使用阿拉伯数字编号,如 1、2、3。 | ||
| 26 | +* 若设备区域内为单台,可约定编号为 1。 | ||
| 27 | + | ||
| 28 | +### 4. 参数名 | ||
| 29 | + | ||
| 30 | +常用参数名如下: | ||
| 31 | + | ||
| 32 | +* RUN:运行状态(0 停止 / 1 运行) | ||
| 33 | +* ALARM:报警状态 | ||
| 34 | +* STATUS:综合状态 | ||
| 35 | +* VALUE:数值型采集量(如水位、流量等) | ||
| 36 | +* LEVEL:液位值 | ||
| 37 | +* MODE:运行模式 | ||
| 38 | +* OTHER:现场扩展参数 | ||
| 39 | + | ||
| 40 | +格式示例:`A_TLJ_1_RUN` | ||
| 41 | + | ||
| 42 | +--- | ||
| 43 | + | ||
| 44 | +## 二、设备命名前缀及示例 | ||
| 45 | + | ||
| 46 | +以下为设备的标准命名前缀、示例及说明(采用区域 A 示例): | ||
| 47 | + | ||
| 48 | +| 设备名称 | 前缀(大写) | 示例 | 示例说明 | | ||
| 49 | +|--------|--------|-----------------|------------------------------| | ||
| 50 | +| 系统级别参数 | SYS | A_SYS_0_SZGD | A 区 市政电源供电信号,<br/>这里的编号0表示不是plc下挂 | | ||
| 51 | +| 喂料机 | TLJ | A_TLJ_1_RUN | A 区 1 号喂料机运行状态 | | ||
| 52 | +| 增氧机 | ZYJ | A_ZYJ_2_ALARM | A 区 2 号增氧机告警状态 | | ||
| 53 | +| 排污 | PW | A_PW_1_RUN | A 区 1 号排污设备运行状态 | | ||
| 54 | +| 曝气 | PQ | A_PQ_1_RUN | A 区 1 号曝气设备运行状态 | | ||
| 55 | +| 流量计 | LLJ | A_LLJ_1_VALUE | A 区 1 号流量计读数 | | ||
| 56 | +| 水位计 | SWJ | A_SWJ_1_VALUE | A 区 1 号水位计水位值 | | ||
| 57 | +| 推水机 | TSJ | A_TSJ_1_RUN | A 区 1 号推水机运行状态 | | ||
| 58 | +| 鱼儿乐 | YEL | A_YEL_1_RUN | A 区 1 号鱼儿乐运行状态 | | ||
| 59 | +| 中转泵 | ZZB | A_ZZB_1_RUN | A 区 1 号中转泵运行状态 | | ||
| 60 | +| 中转池 | ZZC | A_ZZC_1_LEVEL | A 区 1 号中转池液位 | | ||
| 61 | +| 微滤机 | WLJ | A_WLJ_1_RUN | A 区 1 号微滤机运行状态 | | ||
| 62 | +| 循环水池 | XHSC | A_XHSC_1_LEVEL | A 区 1 号循环水池液位 | | ||
| 63 | +| 杀菌 | SJ | A_SJ_1_RUN | A 区 1 号杀菌设备运行状态 | | ||
| 64 | +| 生物滤筒 | SWLT | A_SWLT_1_RUN | A 区 1 号生物滤筒运行状态 | | ||
| 65 | +| 循环水泵 | XHSB | A_XHSB_1_RUN | A 区 1 号循环水泵运行状态 | | ||
| 66 | +| 底增氧风机 | DZYFJ | A_DZYFJ_1_RUN | A 区 1 号底部增氧风机运行状态 | | ||
| 67 | +| 推水风机 | TSFJ | A_TSFJ_1_RUN | A 区 1 号推水风机运行状态 | | ||
| 68 | +| 漩涡风机 | XWFJ | A_XWFJ_1_RUN | A 区 1 号漩涡风机运行状态 | | ||
| 69 | +| 蛋分射流泵 | DFSLB | A_DFSLB_1_RUN | A 区 1 号蛋分射流泵运行状态 | | ||
| 70 | +| 系统控制柜 | XTKZG | A_XTKZG_1_STATUS | A 区 1 号系统控制柜综合状态 | | ||
| 71 | +| 紫外线杀菌器 | UV | A_UV_1_RUN | A 区 1 号紫外线杀菌器运行状态 | | ||
| 72 | +| 变频控制柜 | BPKZG | A_BPKZG_1_STATUS | A 区 1 号变频控制柜状态 | | ||
| 73 | +| 液位计 | YWJ | A_YWJ_1_VALUE | A 区 1 号液位计读数 | | ||
| 74 | +| 热泵 | RB | A_RB_1_RUN | A 区 1 号热泵运行状态 | | ||
| 75 | +--- | ||
| 76 | + | ||
| 77 | +## 三、命名示例说明 | ||
| 78 | + | ||
| 79 | +### 1. 状态型 | ||
| 80 | + | ||
| 81 | +``` | ||
| 82 | +B_TSJ_3_RUN | ||
| 83 | +``` | ||
| 84 | + | ||
| 85 | +表示:B 区 3 号推水机运行状态 | ||
| 86 | + | ||
| 87 | +### 2. 数值型 | ||
| 88 | + | ||
| 89 | +``` | ||
| 90 | +C_LLJ_2_VALUE | ||
| 91 | +``` | ||
| 92 | + | ||
| 93 | +表示:C 区 2 号流量计流量值 | ||
| 94 | + | ||
| 95 | +### 3. 控制柜类 | ||
| 96 | + | ||
| 97 | +``` | ||
| 98 | +A_XTKZG_1_STATUS | ||
| 99 | +``` | ||
| 100 | + | ||
| 101 | +表示:A 区 1 号系统控制柜综合状态 | ||
| 102 | + | ||
| 103 | +--- | ||
| 104 | + | ||
| 105 | +## 四、扩展说明 | ||
| 106 | + | ||
| 107 | +### (新增)5. 多通道/多子设备扩展能力 | ||
| 108 | + | ||
| 109 | +针对含 **主机 + 多个传感器通道** 的设备(如鱼儿乐 YEL),在原有命名规则基础上增加 **子编号**,形成更完整的多级结构: | ||
| 110 | + | ||
| 111 | +``` | ||
| 112 | +区域_前缀_设备编号_子编号_参数名 | ||
| 113 | +``` | ||
| 114 | + | ||
| 115 | +#### 子编号规则: | ||
| 116 | + | ||
| 117 | +* `0` = 主机本体 | ||
| 118 | +* `1~N` = 各传感器通道 | ||
| 119 | + | ||
| 120 | +#### 扩展示例: | ||
| 121 | + | ||
| 122 | +| 点位示例 | 含义说明 | | ||
| 123 | +|----------------| ------------------- | | ||
| 124 | +| A_YEL_1_0_alarm | A 区 1 号鱼儿乐主机告警 | | ||
| 125 | +| A_YEL_1_0_at | A 区 1 号鱼儿乐主机气温 | | ||
| 126 | +| A_YEL_1_0_bar | A 区 1 号鱼儿乐主机气压 | | ||
| 127 | +| A_YEL_1_1_TYPE | A 区 1 号鱼儿乐 1 号传感器类型 | | ||
| 128 | +| A_YEL_1_1_alarm | A 区 1 号鱼儿乐 1 号传感器告警 | | ||
| 129 | +| A_YEL_1_1_wt | A 区 1 号鱼儿乐 1 号传感器水温 | | ||
| 130 | + | ||
| 131 | +##### 常用参数名如下: | ||
| 132 | + | ||
| 133 | +###### 可读参数: | ||
| 134 | +* wt:温度 | ||
| 135 | +* dom:溶氧 | ||
| 136 | +* alarm:故障代码 | ||
| 137 | +* state:控制器状态码 | ||
| 138 | +* at:气温 | ||
| 139 | +* bar:气压 | ||
| 140 | +* mode:控制器模式 | ||
| 141 | +* nh3n:氨氮 | ||
| 142 | +* pH:PH | ||
| 143 | +* nitrite:亚硝酸盐 | ||
| 144 | +* bga:藻类 | ||
| 145 | +* yl:压力 | ||
| 146 | +* ls:流速 | ||
| 147 | +* sw:水位 | ||
| 148 | +* 14:信号强度(0-30) | ||
| 149 | +* cod:COD | ||
| 150 | +* sal:盐度 | ||
| 151 | +* dop:溶氧百分比/溶氧饱和度 | ||
| 152 | +* yw:液位 | ||
| 153 | +* orp:ORP | ||
| 154 | +* turbidity:浊度 | ||
| 155 | +* co2:二氧化碳 | ||
| 156 | +* doh:溶氧高限 | ||
| 157 | +* dou:溶氧上限 | ||
| 158 | +* dol:溶氧下限 | ||
| 159 | +* doa:溶氧警戒线 | ||
| 160 | +###### 可写参数: | ||
| 161 | +* doh-set:溶氧高限 | ||
| 162 | +* dou-set:溶氧上限 | ||
| 163 | +* dol-set:溶氧下限 | ||
| 164 | +* doa-set:溶氧警戒线 | ||
| 165 | + | ||
| 166 | +###### 定制参数: | ||
| 167 | +* SENSOR:定制传感器数据,需要根据TYPE来定义数据类型,比如:A_YEL_1_1_SENSOR 表示 A 区 1 号鱼儿乐1号传感器定制的传感器数据,需要根据TYPE来定义数据类型 | ||
| 168 | + | ||
| 169 | +此扩展适用于所有具备:主机 + 多个测量通道、多探头结构、模块化采集单元等设备类型。 | ||
| 170 | + | ||
| 171 | +1. 区域可根据实际项目划分,如区域编码、池号、车间编号。 | ||
| 172 | +2. 若未来新增设备类型,可继续依照前缀规范扩展。 | ||
| 173 | +3. 所有英文保持大写,确保统一性与可识别性。 | ||
| 174 | + | ||
| 175 | +--- |
| @@ -25,5 +25,6 @@ | @@ -25,5 +25,6 @@ | ||
| 25 | <module>lh-device-defaul</module> | 25 | <module>lh-device-defaul</module> |
| 26 | <module>lh-device-6wp</module> | 26 | <module>lh-device-6wp</module> |
| 27 | <module>lh-device-wendubao</module> | 27 | <module>lh-device-wendubao</module> |
| 28 | + <module>lh-device-mn-plc</module> | ||
| 28 | </modules> | 29 | </modules> |
| 29 | </project> | 30 | </project> |
| 1 | +package com.zhonglai.luhui.device.protocol.factory.config; | ||
| 2 | + | ||
| 3 | +import com.zhonglai.luhui.device.analysis.comm.dao.BaseDao; | ||
| 4 | +import com.zhonglai.luhui.device.domain.IotProductPlcDevice; | ||
| 5 | + | ||
| 6 | +import java.util.HashMap; | ||
| 7 | +import java.util.Map; | ||
| 8 | +import java.util.Set; | ||
| 9 | + | ||
| 10 | +public class PLCDeviceChannelRelationConfig { | ||
| 11 | + private static Map<String, IotProductPlcDevice> channelRelationMap = new HashMap<String, IotProductPlcDevice>(); | ||
| 12 | + public static IotProductPlcDevice getChannelRelation(String channel) { | ||
| 13 | + return channelRelationMap.get(channel); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + public static void addChannelRelation(String channel, IotProductPlcDevice relation) { | ||
| 17 | + channelRelationMap.put(channel, relation); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public static Set<String> getAllIdentifiers() | ||
| 21 | + { | ||
| 22 | + return channelRelationMap.keySet(); | ||
| 23 | + } | ||
| 24 | +} |
| @@ -65,6 +65,9 @@ public class SysCommandListenService implements RocketMQReplyListener<MessageExt | @@ -65,6 +65,9 @@ public class SysCommandListenService implements RocketMQReplyListener<MessageExt | ||
| 65 | case upProductPayloadModelNumber: | 65 | case upProductPayloadModelNumber: |
| 66 | iotThingsModelService.upProductPayloadModelNumberCach(deviceCommand.getData().get("product_ids").getAsInt()); | 66 | iotThingsModelService.upProductPayloadModelNumberCach(deviceCommand.getData().get("product_ids").getAsInt()); |
| 67 | return new Message(MessageCode.DEFAULT_SUCCESS_CODE,"更新产品模型编号关系成功"); | 67 | return new Message(MessageCode.DEFAULT_SUCCESS_CODE,"更新产品模型编号关系成功"); |
| 68 | + case upProductPlcDevice: | ||
| 69 | + iotThingsModelService.upProductPlcDeviceCach(deviceCommand.getData().get("identifier").getAsString()); | ||
| 70 | + return new Message(MessageCode.DEFAULT_SUCCESS_CODE,"更新产品模型编号关系成功"); | ||
| 68 | case delSubscribe: //取消订阅 | 71 | case delSubscribe: //取消订阅 |
| 69 | mqttSubscribeService.unSubscribe(deviceCommand.getData().get("ip").getAsString(),deviceCommand.getData().get("product_ids").getAsString()); | 72 | mqttSubscribeService.unSubscribe(deviceCommand.getData().get("ip").getAsString(),deviceCommand.getData().get("product_ids").getAsString()); |
| 70 | default: | 73 | default: |
| @@ -39,6 +39,11 @@ public enum CommandType { | @@ -39,6 +39,11 @@ public enum CommandType { | ||
| 39 | upProductPayloadModelNumber, | 39 | upProductPayloadModelNumber, |
| 40 | 40 | ||
| 41 | /** | 41 | /** |
| 42 | + * 流水鱼plc设备 | ||
| 43 | + */ | ||
| 44 | + upProductPlcDevice, | ||
| 45 | + | ||
| 46 | + /** | ||
| 42 | * 删除订阅 | 47 | * 删除订阅 |
| 43 | */ | 48 | */ |
| 44 | delSubscribe, | 49 | delSubscribe, |
| @@ -9,8 +9,10 @@ import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelBase; | @@ -9,8 +9,10 @@ import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelBase; | ||
| 9 | import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelDataTypeEnum; | 9 | import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelDataTypeEnum; |
| 10 | import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelItemBase; | 10 | import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelItemBase; |
| 11 | import com.zhonglai.luhui.device.domain.IotProductPayloadModelNumber; | 11 | import com.zhonglai.luhui.device.domain.IotProductPayloadModelNumber; |
| 12 | +import com.zhonglai.luhui.device.domain.IotProductPlcDevice; | ||
| 12 | import com.zhonglai.luhui.device.domain.IotProductTranslate; | 13 | import com.zhonglai.luhui.device.domain.IotProductTranslate; |
| 13 | import com.zhonglai.luhui.device.domain.IotThingsModel; | 14 | import com.zhonglai.luhui.device.domain.IotThingsModel; |
| 15 | +import com.zhonglai.luhui.device.protocol.factory.config.PLCDeviceChannelRelationConfig; | ||
| 14 | import com.zhonglai.luhui.device.protocol.factory.config.ProductPayloadModelNumberCach; | 16 | import com.zhonglai.luhui.device.protocol.factory.config.ProductPayloadModelNumberCach; |
| 15 | import org.apache.commons.lang3.EnumUtils; | 17 | import org.apache.commons.lang3.EnumUtils; |
| 16 | import org.springframework.beans.factory.annotation.Autowired; | 18 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -53,6 +55,8 @@ public class IotThingsModelService { | @@ -53,6 +55,8 @@ public class IotThingsModelService { | ||
| 53 | } | 55 | } |
| 54 | 56 | ||
| 55 | upProductPayloadModelNumberCach(null); | 57 | upProductPayloadModelNumberCach(null); |
| 58 | + | ||
| 59 | + upProductPlcDeviceCach(null); | ||
| 56 | } | 60 | } |
| 57 | 61 | ||
| 58 | 62 | ||
| @@ -138,6 +142,18 @@ public class IotThingsModelService { | @@ -138,6 +142,18 @@ public class IotThingsModelService { | ||
| 138 | } | 142 | } |
| 139 | } | 143 | } |
| 140 | 144 | ||
| 145 | + public void upProductPlcDeviceCach(String identifier) | ||
| 146 | + { | ||
| 147 | + List<IotProductPlcDevice> list = persistenceDBService.getProductPlcDeviceList(identifier); | ||
| 148 | + if (null != list && list.size() != 0) | ||
| 149 | + { | ||
| 150 | + for (IotProductPlcDevice iotProductPlcDevice:list) | ||
| 151 | + { | ||
| 152 | + PLCDeviceChannelRelationConfig.addChannelRelation(iotProductPlcDevice.getIdentifier(),iotProductPlcDevice); | ||
| 153 | + } | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + | ||
| 141 | /** | 157 | /** |
| 142 | * 逆向翻译模式数据 | 158 | * 逆向翻译模式数据 |
| 143 | * @param product_id | 159 | * @param product_id |
| @@ -197,6 +197,11 @@ public class PersistenceDBService { | @@ -197,6 +197,11 @@ public class PersistenceDBService { | ||
| 197 | return defaultDbService.getProductPayloadModelNumberList(product_id); | 197 | return defaultDbService.getProductPayloadModelNumberList(product_id); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | + public List<IotProductPlcDevice> getProductPlcDeviceList(String identifier) | ||
| 201 | + { | ||
| 202 | + return defaultDbService.getProductPlcDeviceList(identifier); | ||
| 203 | + } | ||
| 204 | + | ||
| 200 | /** | 205 | /** |
| 201 | * 获取默认数据库的操作服务 | 206 | * 获取默认数据库的操作服务 |
| 202 | * @return | 207 | * @return |
| @@ -288,6 +288,15 @@ public class DefaultDbService { | @@ -288,6 +288,15 @@ public class DefaultDbService { | ||
| 288 | return baseDao.findBysql("SELECT * FROM `iot_product_payload_model_number` WHERE product_id=?", IotProductPayloadModelNumber.class,product_id); | 288 | return baseDao.findBysql("SELECT * FROM `iot_product_payload_model_number` WHERE product_id=?", IotProductPayloadModelNumber.class,product_id); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | + public List<IotProductPlcDevice> getProductPlcDeviceList(String identifier) | ||
| 292 | + { | ||
| 293 | + if (null == identifier) | ||
| 294 | + { | ||
| 295 | + return baseDao.findBysql("SELECT * FROM `iot_product_plc_device`", IotProductPlcDevice.class); | ||
| 296 | + } | ||
| 297 | + return baseDao.findBysql("SELECT * FROM `iot_product_plc_device` WHERE identifier=?", IotProductPlcDevice.class,identifier); | ||
| 298 | + } | ||
| 299 | + | ||
| 291 | public String getProductUsernames() | 300 | public String getProductUsernames() |
| 292 | { | 301 | { |
| 293 | return baseDao.findBysql("SELECT GROUP_CONCAT(mqtt_username) users FROM `iot_product`",String.class); | 302 | return baseDao.findBysql("SELECT GROUP_CONCAT(mqtt_username) users FROM `iot_product`",String.class); |
| @@ -29,11 +29,11 @@ mqtt: | @@ -29,11 +29,11 @@ mqtt: | ||
| 29 | client: | 29 | client: |
| 30 | #客户端操作时间 | 30 | #客户端操作时间 |
| 31 | operationTime: 10 | 31 | operationTime: 10 |
| 32 | - productids: 13 | 32 | + productids: 39,40 |
| 33 | 33 | ||
| 34 | #rocketmq配置信息 | 34 | #rocketmq配置信息 |
| 35 | rocketmq: | 35 | rocketmq: |
| 36 | #nameservice服务器地址(多个以英文逗号隔开) | 36 | #nameservice服务器地址(多个以英文逗号隔开) |
| 37 | name-server: 8.129.224.117:9876 | 37 | name-server: 8.129.224.117:9876 |
| 38 | consumerGroup: lh-mqtt-service-listen${random.uuid} | 38 | consumerGroup: lh-mqtt-service-listen${random.uuid} |
| 39 | - operationToken: local_lh-mqtt-service-listen | ||
| 39 | + operationToken: localhost |
-
请 注册 或 登录 后发表评论