ModBusServiceImpl.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package com.jg.service.impl;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONArray;
  4. import com.jg.common.ValueType;
  5. import com.jg.service.ModBusService;
  6. import com.jg.util.ModBusUtil;
  7. import com.jg.util.WebSocketServer;
  8. import com.jg.vo.ShowVo;
  9. import com.jg.vo.TagVo;
  10. import com.serotonin.modbus4j.BatchRead;
  11. import com.serotonin.modbus4j.BatchResults;
  12. import com.serotonin.modbus4j.ModbusMaster;
  13. import com.serotonin.modbus4j.code.DataType;
  14. import com.serotonin.modbus4j.locator.BaseLocator;
  15. import jdk.nashorn.internal.ir.annotations.Reference;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.springframework.beans.factory.annotation.Value;
  18. import org.springframework.boot.context.event.ApplicationReadyEvent;
  19. import org.springframework.context.event.EventListener;
  20. import org.springframework.scheduling.annotation.Scheduled;
  21. import org.springframework.stereotype.Service;
  22. import java.io.ByteArrayOutputStream;
  23. import java.io.IOException;
  24. import java.io.InputStream;
  25. import java.math.BigDecimal;
  26. import java.net.URISyntaxException;
  27. import java.nio.charset.StandardCharsets;
  28. import java.nio.file.Files;
  29. import java.nio.file.Paths;
  30. import java.util.*;
  31. @Slf4j
  32. @Service
  33. public class ModBusServiceImpl implements ModBusService {
  34. private static final Map<Long, ModbusMaster> MASTER_MAP = new HashMap<>(64);
  35. private String show;
  36. @Value("${modbus.host}")
  37. private String host;
  38. @Value("${modbus.port}")
  39. private Integer port;
  40. @Reference
  41. private WebSocketServer webSocketServer;
  42. /**
  43. * 创建ModBusTCP连接
  44. */
  45. // @EventListener(ApplicationReadyEvent.class)
  46. private void createConn() {
  47. // 创建ModBus连接, 存入MASTER_MAP
  48. // List<CollectModuleInfo> collectModuleInfoList = collectModuleInfoService.findCurrent();
  49. // log.info("[查询采集模块列表]: {}", collectModuleInfoList);
  50. // if (!CollectionUtils.isEmpty(collectModuleInfoList)) {
  51. // for (CollectModuleInfo collectModuleInfo : collectModuleInfoList) {
  52. // Long collectModuleInfoId = collectModuleInfo.getId();
  53. // MODULE_INFO_MAP.put(collectModuleInfoId, collectModuleInfo);
  54. // // 循环创建ModBus连接
  55. // ModbusMaster modbusMaster = MASTER_MAP.get(collectModuleInfoId);
  56. // if (null == modbusMaster) {
  57. // // 创建ModBus连接, 存入Map, key: 采集模块id, value: ModBus连接
  58. // modbusMaster = ModBusUtil.createMaster(collectModuleInfo);
  59. // MASTER_MAP.put(collectModuleInfoId, modbusMaster);
  60. // }
  61. // }
  62. // } else {
  63. //// throw new BizException("连接失败! 没有查询到ModBus模块信息!");
  64. // }
  65. // log.warn("[开始连接采集模块]: {}", JSON.toJSONString(collectModuleInfoList));
  66. // ModbusMaster master = ModBusUtil.createMaster(host, port);
  67. // MASTER_MAP.put(1l, master);
  68. InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tag.json");
  69. try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()){
  70. byte[] buffer = new byte[1024];
  71. int length;
  72. while ((length = inputStream.read(buffer)) != -1) {
  73. byteArrayOutputStream.write(buffer, 0, length);
  74. }
  75. show = byteArrayOutputStream.toString(StandardCharsets.UTF_8.name());
  76. // 使用 show 字符串
  77. } catch (Exception e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. // @Scheduled(fixedRate = 1000)
  82. private void readTagsValue(){
  83. List<TagVo> tagVos = JSON.parseArray(show, TagVo.class);
  84. BatchRead<String> batch = new BatchRead<>();
  85. JSONArray array = new JSONArray();
  86. for (TagVo tagVo: tagVos){
  87. Integer slaveId = tagVo.getSlaveId();
  88. Integer functionCode = tagVo.getFunctionCode();
  89. int offset = tagVo.getOffset();
  90. String tag = tagVo.getTag();
  91. String dataType = tagVo.getDataType();
  92. switch (functionCode) {
  93. case 1:
  94. batch.addLocator(tag, BaseLocator.coilStatus(slaveId, offset));
  95. break;
  96. case 2:
  97. batch.addLocator(tag, BaseLocator.inputStatus(slaveId, offset));
  98. break;
  99. case 3:
  100. batch.addLocator(tag, BaseLocator.holdingRegister(slaveId, offset, getValueType(dataType)));
  101. break;
  102. case 4:
  103. batch.addLocator(tag, BaseLocator.inputRegister(slaveId, offset, getValueType(dataType)));
  104. break;
  105. default:
  106. break;
  107. }
  108. }
  109. batch.setContiguousRequests(false);
  110. ModbusMaster modbusMaster = MASTER_MAP.get(1l);
  111. try {
  112. if (!modbusMaster.isInitialized()) {
  113. modbusMaster.init();
  114. }
  115. modbusMaster.setTimeout(500);
  116. BatchResults<String> results = modbusMaster.send(batch);
  117. for (TagVo tagVo: tagVos){
  118. // log.info("采集中文: {}, 值: {}", tagVo.getDesc(), results.getValue(tagVo.getTag()));
  119. Object value = results.getValue(tagVo.getTag());
  120. BigDecimal bigDecimalValue = convertToBigDecimal(value);
  121. ShowVo showVo = new ShowVo();
  122. showVo.setName(tagVo.getDesc());
  123. showVo.setValue(bigDecimalValue);
  124. showVo.setUnit(tagVo.getUnit());
  125. // showVos.add(showVo);
  126. array.add(showVo);
  127. }
  128. log.info(array.toString());
  129. webSocketServer.sendInfo(array.toString(), "push");
  130. modbusMaster.destroy();
  131. } catch (Exception e) {
  132. log.error("采集模块Id: {}, 读取失败: {}", 1l, e.getMessage());
  133. }
  134. }
  135. /**
  136. * 获取数据类型
  137. * 说明:此处可根据实际项目情况进行拓展
  138. * 1.swap 交换
  139. * 2.大端/小端,默认是大端
  140. * 3.拓展其他数据类型
  141. *
  142. * @param type Value Type
  143. * @return Modbus Data Type
  144. */
  145. public static int getValueType(String type) {
  146. switch (type.toLowerCase()) {
  147. case ValueType.LONG:
  148. return DataType.FOUR_BYTE_INT_SIGNED;
  149. case ValueType.FLOAT:
  150. return DataType.FOUR_BYTE_FLOAT;
  151. case ValueType.DOUBLE:
  152. return DataType.EIGHT_BYTE_FLOAT;
  153. default:
  154. return DataType.TWO_BYTE_INT_UNSIGNED;
  155. }
  156. }
  157. /**
  158. * 将 Object 转换为 BigDecimal
  159. **/
  160. private static BigDecimal convertToBigDecimal(Object obj) {
  161. // 处理 obj 为 null 的情况,返回 -1
  162. if (obj == null) {
  163. return BigDecimal.valueOf(-1);
  164. }
  165. if (obj instanceof BigDecimal) {
  166. return (BigDecimal) obj;
  167. } else if (obj instanceof Integer) {
  168. return BigDecimal.valueOf((Integer) obj);
  169. } else if (obj instanceof Double) {
  170. return BigDecimal.valueOf((Double) obj);
  171. } else if (obj instanceof String) {
  172. return new BigDecimal((String) obj);
  173. } else if (obj instanceof Float){
  174. return BigDecimal.valueOf(((Float) obj).doubleValue());
  175. } else if (obj instanceof Boolean) {
  176. return BigDecimal.valueOf((Boolean) obj ? 1 : 0);
  177. } else {
  178. throw new IllegalArgumentException("Unsupported object type: " + obj.getClass());
  179. }
  180. }
  181. @Override
  182. public void startCollect() {
  183. createConn();
  184. readTagsValue();
  185. }
  186. }