ModBusServiceImpl.java 7.1 KB

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