package org.jeecg.modules.iot.service.impl; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.iot.depository.DbConfig; import org.jeecg.modules.iot.depository.MysqlDataWriter; import org.jeecg.modules.iot.entity.EmptyParameter; import org.jeecg.modules.iot.entity.Equipment; import org.jeecg.modules.iot.entity.RealParameter; import org.jeecg.modules.iot.entity.ScriptCompilation; import org.jeecg.modules.iot.mapper.EmptyParameterMapper; import org.jeecg.modules.iot.mapper.RealParameterMapper; import org.jeecg.modules.iot.service.IEmptyParameterService; import org.jeecg.modules.iot.service.IEquipmentService; import org.jeecg.modules.iot.util.AESUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.*; import java.util.*; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * @Description: 虚设备参数 * @Author: cuikaidong * @Date: 2025-1-7 * @Version: V1.0 */ @Service public class EmptyParameterServiceImpl extends ServiceImpl implements IEmptyParameterService { @Resource private RealParameterMapper realParameterMapper; @Autowired private IEquipmentService equipmentService; @Autowired private DataSource dataSource; @Override public List findParameterByEquipmentIds(Set ids) { return new LambdaQueryChainWrapper<>(baseMapper).in(EmptyParameter::getEquipmentId, ids).list(); } @Override public Result handleCompile(EmptyParameter emptyParameter) { Map referenceInfo = new HashMap<>(); // 验证脚本实设备 List attributes = new ArrayList<>(getAttributes(emptyParameter.getScript(), "IOT_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+")); if (!attributes.isEmpty()) { List realParameterList = realParameterMapper.findRealParameterList(attributes); // 判断实设备参数数量是否相等 if (attributes.size() != realParameterList.size()) { // 求差集 Set difference1 = new HashSet<>(attributes); // 使用 Stream API 将 name 字段转换为 Set Set difference2 = realParameterList.stream() .map(RealParameter::getAddress).collect(Collectors.toSet()); difference1.removeAll(difference2); return Result.error(difference1 + "属性有误!!!"); } realParameterList.forEach(r -> { if (r.getSystemDataType().isEmpty()) { referenceInfo.put(r.getAddress(), r.getParameterType()); } else { referenceInfo.put(r.getAddress(), r.getSystemDataType()); } }); } // 验证虚设备 List empAttributes = new ArrayList<>(getAttributes(emptyParameter.getScript(), "IOT_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+")); if (!empAttributes.isEmpty()) { List emptyParameterList = new ArrayList<>(); Set difference = new HashSet<>(empAttributes); if (!attributes.isEmpty()) { // 求差集 difference.removeAll(attributes); List www = new ArrayList<>(difference); // 查询数据库中匹配的数量 if (!www.isEmpty()) { emptyParameterList = baseMapper.findEmptyParameterList(www); } } else { emptyParameterList = baseMapper.findEmptyParameterList(empAttributes); } // 使用 HashSet 去重 Set personSet = new HashSet<>(emptyParameterList); // 判断虚设备参数数量是否相等 if (difference.size() != personSet.size()) { // 求差集 Set difference1 = new HashSet<>(difference); // 使用 Stream API 将 name 字段转换为 Set Set difference2 = personSet.stream() .map(EmptyParameter::getAddress).collect(Collectors.toSet()); difference1.removeAll(difference2); return Result.error(difference1 + "属性有误!!!"); } personSet.forEach(p -> { if (p.getSystemDataType().isEmpty()) { referenceInfo.put(p.getAddress(), p.getParameterType()); } else { referenceInfo.put(p.getAddress(), p.getSystemDataType()); } }); } // --------AES_CBC加密--------- String cbcResult = AESUtil.encryptCBC(emptyParameter.getScript(), "xhVs6DRXLfUGxw+AhtfQdpQGoa+8SA9d"); try { ScriptCompilation scriptCompilation = new ScriptCompilation(); Equipment equipment = equipmentService.getById(emptyParameter.getEquipmentId()); scriptCompilation.setDeviceId(equipment.getEqptCode()); scriptCompilation.setParameterCode(cbcResult); scriptCompilation.setParameterDataType(emptyParameter.getParameterType()); scriptCompilation.setParameterName(emptyParameter.getParameterName()); scriptCompilation.setReferenceinfo(referenceInfo); String jsonPayload = JSONObject.toJSONString(scriptCompilation); // 创建 HttpClient 实例 HttpClient httpClient = HttpClients.createDefault(); // 创建 HttpPost 请求实例 HttpPost httpPost = new HttpPost("http://localhost:3002/ScriptCompiler/ScriptCompiler"); // 设置请求头,指定内容类型为 JSON,编码为 UTF-8 httpPost.setHeader("Content-Type", "application/json; charset=UTF-8"); // 创建 StringEntity 并指定编码为 UTF-8 StringEntity entity = new StringEntity(jsonPayload, "UTF-8"); httpPost.setEntity(entity); // 执行请求并获取响应 HttpResponse response = httpClient.execute(httpPost); // 获取响应实体内容 String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); boolean isContain = responseBody.contains("编译成功"); if (isContain) { return Result.ok(responseBody); } else { // 输出响应内容 return Result.error(responseBody); } } catch (Exception e) { e.printStackTrace(); } return Result.error("编译失败"); } @Override public Result preserveScript(EmptyParameter emptyParameter) { Map referenceInfo = new HashMap<>(); // 验证脚本实设备 List attributes = new ArrayList<>(getAttributes(emptyParameter.getScript(), "IOT_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+")); if (!attributes.isEmpty()) { List realParameterList = realParameterMapper.findRealParameterList(attributes); realParameterList.forEach(r -> { if (r.getSystemDataType().isEmpty()) { referenceInfo.put(r.getAddress(), r.getParameterType()); } else { referenceInfo.put(r.getAddress(), r.getSystemDataType()); } }); } // 验证虚设备 List empAttributes = new ArrayList<>(getAttributes(emptyParameter.getScript(), "IOT_[\\p{L}\\p{N}_]+_[\\p{L}\\p{N}_]+")); if (!empAttributes.isEmpty()) { List emptyParameterList = new ArrayList<>(); Set difference = new HashSet<>(empAttributes); if (!attributes.isEmpty()) { // 求差集 difference.removeAll(attributes); List www = new ArrayList<>(difference); // 查询数据库中匹配的数量 if (!www.isEmpty()) { emptyParameterList = baseMapper.findEmptyParameterList(www); } } else { emptyParameterList = baseMapper.findEmptyParameterList(empAttributes); } // 使用 HashSet 去重 Set personSet = new HashSet<>(emptyParameterList); personSet.forEach(p -> { if (p.getSystemDataType().isEmpty()) { referenceInfo.put(p.getAddress(), p.getParameterType()); } else { referenceInfo.put(p.getAddress(), p.getSystemDataType()); } }); } // --------AES_CBC加密--------- String cbcResult = AESUtil.encryptCBC(emptyParameter.getScript(), "xhVs6DRXLfUGxw+AhtfQdpQGoa+8SA9d"); try { ScriptCompilation scriptCompilation = new ScriptCompilation(); Equipment equipment = equipmentService.getById(emptyParameter.getEquipmentId()); scriptCompilation.setDeviceId(equipment.getEqptCode()); scriptCompilation.setParameterCode(cbcResult); scriptCompilation.setParameterDataType(emptyParameter.getParameterType()); scriptCompilation.setParameterName(emptyParameter.getParameterName()); scriptCompilation.setReferenceinfo(referenceInfo); String jsonPayload = JSONObject.toJSONString(scriptCompilation); // 创建 HttpClient 实例 HttpClient httpClient = HttpClients.createDefault(); // 创建 HttpPost 请求实例 HttpPost httpPost = new HttpPost("http://localhost:3002/ScriptCompiler/ScriptSave"); // 设置请求头,指定内容类型为 JSON,编码为 UTF-8 httpPost.setHeader("Content-Type", "application/json; charset=UTF-8"); // 创建 StringEntity 并指定编码为 UTF-8 StringEntity entity = new StringEntity(jsonPayload, "UTF-8"); httpPost.setEntity(entity); // 执行请求并获取响应 HttpResponse response = httpClient.execute(httpPost); // 获取响应实体内容 String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); boolean isContain = responseBody.contains("保存成功"); // 将 JSON 字符串转换为 JSONObject cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject(responseBody); // 访问 JSON 对象的属性 String message = jsonObject.getStr("Message"); if (isContain) { // 保存脚本标记列表 StringBuilder scriptTagList = new StringBuilder(); for (String key : referenceInfo.keySet()) { if (scriptTagList.toString().equals("")) { scriptTagList = new StringBuilder(key); } else { scriptTagList.append("|").append(key); } } // 保存属性 emptyParameter.setScriptTagList(scriptTagList.toString()); // 保存脚本 emptyParameter.setScriptContent(emptyParameter.getScript()); baseMapper.updateById(emptyParameter); return Result.ok(message); } else { // 输出响应内容 return Result.error(message); } } catch (Exception e) { e.printStackTrace(); } return Result.error("编译失败"); } @Override public Integer findEmptyParameterCode(String equipmentId) { List list = new LambdaQueryChainWrapper<>(baseMapper) .eq(EmptyParameter::getEquipmentId, equipmentId) .orderByDesc(EmptyParameter::getParameterCode) .list(); if (list.size() == 0) { return 1; } return list.get(0).getParameterCode() + 1; } @Override public Boolean findEmptyParameterByName(EmptyParameter emptyParameter) { List realParameters = new LambdaQueryChainWrapper<>(baseMapper) .eq(EmptyParameter::getEquipmentId, emptyParameter.getEquipmentId()) .eq(EmptyParameter::getParameterName, emptyParameter.getParameterName()) .list(); return realParameters.size() > 0; } @Override public void createEmptyEmptyField(Date deployDate, String serverId) { List emptyParameterList = baseMapper.findEmptyParameterListByTime(deployDate, serverId); Map> emptyParameterListMap = emptyParameterList.stream() .collect(Collectors.groupingBy(EmptyParameter::getEqptCode)); emptyParameterListMap.forEach((eqptCode, parameterList) -> { Equipment equipment = equipmentService.findEquipmentByCode(eqptCode); List columnDefinitions = new ArrayList<>(); Set columnNames = new HashSet<>(); // 遍历当前设备下的所有参数 parameterList.forEach(param -> { columnDefinitions.add("NVARCHAR(100) DEFAULT ''"); columnNames.add(param.getParameterName()); }); addSqlserverColumns(equipment.getControlSystem() + '_' + eqptCode, new ArrayList<>(columnDefinitions), new ArrayList<>(columnNames)); }); } /** * // 批量导入字段(SQL Server 版本) * * @param tableName * @param columnDefinitions * @param columnNames */ public void addSqlserverColumns(String tableName, List columnDefinitions, List columnNames) { if (columnDefinitions.size() != columnNames.size()) { throw new IllegalArgumentException("字段定义和字段名的数量必须一致"); } // 转义表名中的方括号,防止SQL注入 tableName = tableName.replace("[", "[[").replace("]", "]]"); StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append("ALTER TABLE").append("[") .append(tableName).append("] ADD "); boolean hasNewColumns = false; for (int i = 0; i < columnDefinitions.size(); i++) { String columnName = columnNames.get(i); if (sqlServeBatchIsColumnExists(tableName, columnName)) { System.out.println("字段已存在,无需添加: " + columnName); continue; } String columnDefinition = columnDefinitions.get(i); if (hasNewColumns) { sqlBuilder.append(", "); } sqlBuilder.append("[").append(columnName.replace("[", "[[").replace("]", "]]")).append("] ") .append(columnDefinition); hasNewColumns = true; } String sql = sqlBuilder.toString(); if (!hasNewColumns) { System.out.println("没有需要添加的新字段"); return; } try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { System.out.println("执行SQL: " + sql); // 调试用 stmt.executeUpdate(sql); System.out.println("字段批量添加成功"); } catch (SQLException e) { System.err.println("批量添加字段失败: " + sql); e.printStackTrace(); } } /** * 验证字段是否存在(SQL Server 版本) */ private boolean sqlServeBatchIsColumnExists(String tableName, String columnName) { // 自动转义表名(处理方括号和特殊字符) String quotedTable = "[" + tableName.replace("]", "]]") + "]"; String sql = "SELECT COUNT(*) FROM sys.columns " + "WHERE object_id = OBJECT_ID(?) AND name = ?"; try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) { // 设置第一个参数:转义后的表名 stmt.setString(1, quotedTable); // 设置第二个参数:字段名 stmt.setString(2, columnName); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) { return rs.getInt(1) > 0; } } } catch (SQLException e) { // log.error("检查字段 {} 在表 {} 中是否存在时出错", columnName, tableName, e); return false; } return false; } /** * 根据表达式查询脚本中包含的属性 * * @param script 脚本 * @param regex 表达式 * @return 属性 */ Set getAttributes(String script, String regex) { Set scriptList = new HashSet<>(); // 编译正则表达式 Pattern pattern = Pattern.compile(regex); // 创建 Matcher 对象 Matcher matcher = pattern.matcher(script); // 查找所有匹配的子字符串 while (matcher.find()) { // 获取当前匹配到的内容 scriptList.add(matcher.group()); } return scriptList; } }