fix:寄存器首地址取值先走DB
This commit is contained in:
parent
94c49e36b1
commit
471c3a6a2c
@ -41,7 +41,7 @@ spring:
|
||||
# slave:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://1.116.124.85:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: root
|
||||
# password: fastbee
|
||||
shardingsphere:
|
||||
@ -113,7 +113,7 @@ spring:
|
||||
mqtt:
|
||||
username: fastbee # 账号
|
||||
password: fastbee # 密码
|
||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||
host-url: tcp://1.116.124.85:1883 # mqtt连接tcp地址
|
||||
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||
default-topic: test # 默认主题
|
||||
timeout: 30 # 超时时间
|
||||
@ -121,7 +121,7 @@ spring:
|
||||
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||
# EMQX API配置需要在运行emqx之后去EMQX管理后台手动创建API Key和Secret,并配置到application.yml中
|
||||
emqx:
|
||||
host: localhost # EMQX服务器地址
|
||||
host: 1.116.124.85 # EMQX服务器地址
|
||||
port: 18083
|
||||
ApiKey: emqx.key.123 # EMQX API Key
|
||||
ApiSecret: emqx.api.123
|
||||
|
||||
@ -51,6 +51,8 @@ server:
|
||||
|
||||
# Spring配置
|
||||
spring:
|
||||
# quartz:
|
||||
# auto-startup: false # 上线前去掉
|
||||
# 环境配置,dev=开发环境,prod=生产环境
|
||||
profiles:
|
||||
active: dev # 环境配置,dev=开发环境,prod=生产环境
|
||||
|
||||
@ -301,8 +301,8 @@ public class CaculateUtils {
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static Float toFloat32_CDAB(byte[] bytes) {
|
||||
int intValue = ((bytes[2] & 0xFF) << 24) | ((bytes[3] & 0xFF) << 16) | ((bytes[0] & 0xFF) << 8) | ((bytes[1] & 0xFF)) ;
|
||||
public static Float toFloat32_DCBA(byte[] bytes) {
|
||||
int intValue = ((bytes[3] & 0xFF) << 24) | ((bytes[2] & 0xFF) << 16) | ((bytes[1] & 0xFF) << 8) | ((bytes[0] & 0xFF)) ;
|
||||
return Float.intBitsToFloat(intValue);
|
||||
}
|
||||
|
||||
@ -339,8 +339,8 @@ public class CaculateUtils {
|
||||
case FLOAT_ABCD:
|
||||
value = CaculateUtils.toFloat32_ABCD(bytes) + "";
|
||||
break;
|
||||
case FLOAT_CDAB:
|
||||
value = CaculateUtils.toFloat32_CDAB(bytes) + "";
|
||||
case FLOAT_CDAB: // todo:待改枚举页面枚举
|
||||
value = CaculateUtils.toFloat32_DCBA(bytes) + "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -417,7 +417,7 @@ public class CaculateUtils {
|
||||
System.out.println(i);
|
||||
byte[] bytes1 = ByteBufUtil.decodeHexDump(hexToBytes1);
|
||||
|
||||
float v2 = toFloat32_CDAB(bytes1);
|
||||
float v2 = toFloat32_DCBA(bytes1);
|
||||
System.out.println("转32位浮点型-CDAB序:"+v2);
|
||||
|
||||
int signedShort = -32627; // 16位有符号整形
|
||||
|
||||
@ -141,7 +141,7 @@ public class CRC16Utils {
|
||||
byte[] byte8 = ByteUtils.hexToByte(crc8);
|
||||
int b = CRC8(byte8);
|
||||
System.out.println((int) b);
|
||||
float v = CaculateUtils.toFloat32_CDAB(bytes);
|
||||
float v = CaculateUtils.toFloat32_DCBA(bytes);
|
||||
System.out.println(v);
|
||||
}
|
||||
|
||||
|
||||
@ -71,5 +71,7 @@ public class ModbusUtils {
|
||||
public static void main(String[] args) {
|
||||
int modbusAddress = getModbusAddress("0101000A0001FDCA");
|
||||
System.out.println(modbusAddress);
|
||||
Mparams modbusParams = getModbusParams("01030001000815cc");
|
||||
System.out.println("modbusParams.getAddress() = " + modbusParams.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,26 +11,20 @@ import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.mq.message.FunctionCallBackBo;
|
||||
import com.fastbee.common.core.protocol.modbus.ModbusCode;
|
||||
import com.fastbee.common.core.redis.RedisCache;
|
||||
import com.fastbee.common.core.redis.RedisKeyBuilder;
|
||||
import com.fastbee.common.core.thingsModel.ThingsModelSimpleItem;
|
||||
import com.fastbee.common.enums.FunctionReplyStatus;
|
||||
import com.fastbee.common.enums.ModbusDataType;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.CaculateUtils;
|
||||
import com.fastbee.common.utils.DateUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.gateway.CRC16Utils;
|
||||
import com.fastbee.common.utils.modbus.BitUtils;
|
||||
import com.fastbee.common.utils.modbus.ModbusUtils;
|
||||
import com.fastbee.common.utils.modbus.Mparams;
|
||||
import com.fastbee.iot.cache.IModbusConfigCache;
|
||||
import com.fastbee.iot.domain.Device;
|
||||
import com.fastbee.iot.domain.ModbusConfig;
|
||||
import com.fastbee.iot.model.ThingsModelItem.Datatype;
|
||||
import com.fastbee.iot.mapper.DeviceMapper;
|
||||
import com.fastbee.iot.mapper.ModbusConfigMapper;
|
||||
import com.fastbee.iot.model.ThingsModels.ThingsModelValueItem;
|
||||
import com.fastbee.iot.model.gateWay.SubDeviceListVO;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import com.fastbee.iot.service.ISubGatewayService;
|
||||
import com.fastbee.iot.service.IThingsModelService;
|
||||
import com.fastbee.modbus.model.ModbusRtu;
|
||||
import com.fastbee.protocol.base.protocol.IProtocol;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
@ -41,7 +35,10 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -64,6 +61,11 @@ public class ModbusProtocol implements IProtocol {
|
||||
private IModbusConfigCache modbusConfigCache;
|
||||
@Resource
|
||||
private ISubGatewayService subGatewayService;
|
||||
@Resource
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Resource
|
||||
private ModbusConfigMapper modbusConfigMapper;
|
||||
|
||||
@Override
|
||||
public DeviceReport decode(DeviceData deviceData, String clientId) {
|
||||
@ -158,8 +160,9 @@ public class ModbusProtocol implements IProtocol {
|
||||
modbusConfigList.addAll(entry.getValue());
|
||||
}
|
||||
int isReadOnly = message.getCode() == 1 ? 1 : 0;
|
||||
Map<Integer, List<ModbusConfig>> listMap = modbusConfigList.stream().filter(config ->
|
||||
{ return config.getType() == 1 && config.getIsReadonly() == isReadOnly;}).collect(Collectors.groupingBy(ModbusConfig::getAddress));
|
||||
Map<Integer, List<ModbusConfig>> listMap = modbusConfigList.stream()
|
||||
.filter(config -> config.getType() == 1 && config.getIsReadonly() == isReadOnly)
|
||||
.collect(Collectors.groupingBy(ModbusConfig::getAddress));
|
||||
//分割值
|
||||
List<String> values = StringUtils.splitEvenly(hexDump, 2);
|
||||
int ioAd = Integer.parseInt(address);
|
||||
@ -241,10 +244,20 @@ public class ModbusProtocol implements IProtocol {
|
||||
modbusConfigList.addAll(entry.getValue());
|
||||
}
|
||||
int isReadOnly = message.getCode() == 3 ? 1 : 0;
|
||||
Map<Integer, ModbusConfig> configMap = modbusConfigList.stream().filter(config ->
|
||||
{return config.getType() == 2 && config.getIsReadonly() == isReadOnly;}).collect(Collectors.toMap(ModbusConfig::getAddress, Function.identity()));
|
||||
Map<Integer, ModbusConfig> configMap = modbusConfigList.stream()
|
||||
.filter(config -> config.getType() == 2 && config.getIsReadonly() == isReadOnly)
|
||||
.collect(Collectors.toMap(ModbusConfig::getAddress, Function.identity()));
|
||||
int registerAd = Integer.parseInt(address);
|
||||
for (int i = 0; i < length; i++) {
|
||||
// 需要根据首地址值以及数据长度动态截取数据 例如数据:0103 0800 3800 4500 5600 7801 e9
|
||||
int startIndex = registerAd * 4; // 每个寄存器占4个十六进制字符
|
||||
if (startIndex > 0 && startIndex < dataHex.length()) {
|
||||
dataHex = dataHex.substring(startIndex);
|
||||
log.debug("截取后数据(起始地址{}): {}", registerAd, dataHex);
|
||||
} else if (startIndex >= dataHex.length()) {
|
||||
log.error("起始地址{}超出数据范围! 数据长度: {}", registerAd, dataHex.length() / 4);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < length; ) { // 移除i++,手动控制循环
|
||||
ModbusConfig modbusConfig = configMap.get(registerAd);
|
||||
if (Objects.isNull(modbusConfig)) {
|
||||
// 处理可能是 03按位运行情况,判断是否有寄存器,而且寄存器对应物模型多个
|
||||
@ -262,6 +275,7 @@ public class ModbusProtocol implements IProtocol {
|
||||
log.warn("寄存器地址:{},不存在", registerAd);
|
||||
}
|
||||
registerAd += 1;
|
||||
i += 1; // 单个寄存器,i增加1
|
||||
continue;
|
||||
}
|
||||
//个数
|
||||
@ -271,9 +285,12 @@ public class ModbusProtocol implements IProtocol {
|
||||
simpleItem.setTs(DateUtils.getNowDate());
|
||||
if (quantity == 1) {
|
||||
//将identity与address替换
|
||||
simpleItem.setValue(CaculateUtils.handleToUnSign16(data[i] + "", modbusConfig.getDataType()));
|
||||
String handleHex = dataHex.substring(0, 4);
|
||||
String value = CaculateUtils.handleToUnSign16(Long.parseLong(handleHex, 16) + "", modbusConfig.getDataType());
|
||||
simpleItem.setValue(value);
|
||||
simpleItemList.add(simpleItem);
|
||||
dataHex = dataHex.substring(4);
|
||||
i += 1; // 单个寄存器,i增加1
|
||||
} else if (quantity == 2) {
|
||||
//这里做数据处理
|
||||
String handleHex = dataHex.substring(0, 8);
|
||||
@ -282,17 +299,18 @@ public class ModbusProtocol implements IProtocol {
|
||||
simpleItemList.add(simpleItem);
|
||||
//处理dataHex
|
||||
dataHex = dataHex.substring(8);
|
||||
//处理quantity ==2的情况,跳过一次循环
|
||||
i += 1;
|
||||
i += 2; // 浮点数,i增加2
|
||||
}
|
||||
//寄存器地址+1
|
||||
registerAd += 1;
|
||||
|
||||
//寄存器地址根据quantity增加
|
||||
registerAd += quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下发指令设备回复消息,按照modbus协议约定会返回一样的指令
|
||||
*
|
||||
* @param message 解析后数据
|
||||
*/
|
||||
private void handleMsgReply(ModbusRtu message, DeviceReport report, ModbusCode code) {
|
||||
@ -412,19 +430,38 @@ public class ModbusProtocol implements IProtocol {
|
||||
* 获取modbus地址
|
||||
*/
|
||||
private String getCacheModbusAddress(String serialNumber, int salveId, int code) {
|
||||
String key = RedisKeyBuilder.buildModbusRuntimeCacheKey(serialNumber);
|
||||
Set<String> commandSet = redisCache.zRange(key, 0, -1);
|
||||
if (commandSet.size() == 0) {
|
||||
throw new ServiceException("No cache modbus address found");
|
||||
// String key = RedisKeyBuilder.buildModbusRuntimeCacheKey(serialNumber);
|
||||
// Set<String> commandSet = redisCache.zRange(key, 0, -1);
|
||||
//
|
||||
// // 1. 遍历匹配指令
|
||||
// for (String command : commandSet) {
|
||||
// try {
|
||||
// Mparams params = ModbusUtils.getModbusParams(command);
|
||||
// redisCache.zRem(key, command); // 删除缓存
|
||||
// if (params.getSlaveId() == salveId && params.getCode() == code) {
|
||||
// return String.valueOf(params.getAddress());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.warn("解析指令异常: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
// 2. 无匹配时查询数据库
|
||||
try {
|
||||
Device device = deviceMapper.selectDeviceBySerialNumber(serialNumber);
|
||||
if (device == null) return "0";
|
||||
|
||||
List<ModbusConfig> configs = modbusConfigMapper.selectModbusConfigListByProductId(device.getProductId());
|
||||
if (CollectionUtils.isEmpty(configs)) return "0";
|
||||
|
||||
return configs.stream()
|
||||
.mapToInt(ModbusConfig::getAddress)
|
||||
.min()
|
||||
.orElse(0) + "";
|
||||
} catch (Exception e) {
|
||||
log.error("数据库查询异常: {}", e.getMessage());
|
||||
return "0";
|
||||
}
|
||||
for (String command : commandSet) {
|
||||
Mparams params = ModbusUtils.getModbusParams(command);
|
||||
redisCache.zRem(key, command);
|
||||
if (params.getSlaveId() == salveId && params.getCode() == code){
|
||||
return params.getAddress()+"";
|
||||
}
|
||||
}
|
||||
throw new ServiceException("No cache modbus address found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -90,4 +90,11 @@ public interface ModbusConfigMapper
|
||||
* @return
|
||||
*/
|
||||
public List<ModbusConfig> selectShortListByProductId(ModbusConfig config);
|
||||
|
||||
/**
|
||||
* 根据产品id获取modbus配置
|
||||
* @param productId
|
||||
* @return
|
||||
*/
|
||||
List<ModbusConfig> selectModbusConfigListByProductId(Long productId);
|
||||
}
|
||||
|
||||
@ -344,4 +344,13 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectModbusConfigListByProductId" resultType="com.fastbee.iot.domain.ModbusConfig">
|
||||
<include refid="selectModbusConfigShortVo"/>
|
||||
<where>
|
||||
<if test="productId != null">
|
||||
and product_id = #{productId}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user