gpt4 book ai didi

java.nio.BufferOverflowException 构造 byte[]

转载 作者:太空宇宙 更新时间:2023-11-04 10:52:07 26 4
gpt4 key购买 nike

我正在构建一个字节数组来识别 M-Bus 主设备,并且我需要使用辅助地址来完成此操作。

Details from Seller Software

To do it i need to build a byte[] with the identification of the address:

  1. 识别号(4 个字节)- 范围从 00000000 到99999999识别电表。
  2. 制造商 ID(2 个字节)- 三个字母,用于识别制造商制造商。
  3. 版本(1 个字节)- 指定设备的版本。版本是制造商特定的。
  4. 设备类型(1 个字节)——该字段对设备类型进行编码(例如电表、冷水表)

如果我的数学没让我失望的话,它总共有 8 个字节。

这是我的代码:

public static void main(String[] args) {
// TODO code application logic here
MBusSerialBuilder builder = MBusConnection.newSerialBuilder("COM4").setBaudrate(2400);
try (MBusConnection mBusConnection = builder.build()) {
// read/write
int primaryAddress = 253;

byte[] idNum = ByteBuffer.allocate(4).putInt(46152604).array();
byte version = 0xFF & 88; //only need a byte not a 4 byte int
byte deviceType = 0xFF & 13; //only need a byte not a 4 byte int
short manuID = createManuID("ZRI");
//builds the message without overflow now
byte[] data = ByteBuffer.allocate(8).put(idNum).putShort(manuID).put(version).put(deviceType).array();

mBusConnection.write(primaryAddress, data);
VariableDataStructure vds = mBusConnection.read(primaryAddress);
System.out.println(vds);
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}

注意以前我有

byte[] manId = ByteBuffer.allocate(2).putChar('Z').putChar('R').putChar('I').array();

它返回了我java.nio.BufferOverflowException

经过最近的更改,错误现在出现在 data 声明上。

即使我分配了 50 个字节

byte[] data = ByteBuffer.allocate(50).put(idNum).put(manId).putInt(88).putInt(13).array();

不同的错误

java.lang.IndexOutOfBoundsException

这是我从卖家程序的日志文件中提取的一些信息。

MBus Tx_raw-><11><68><b><b><68><53><fd><52><4><26><15><46><ff><ff><ff><ff><23><16>
MBus Rx_raw-><0><aa><1><e5><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0>
MBus Tx_raw-><5><10><7b><fd><78><16>
MBus Rx_raw-><0><aa><b7><68><b1><b1><68><8><0><72><4><26><15><46><49><6a><88><d><29><0><0><0><4><6d><34><a><27><2c><82><4><6c><21><21><82><a><6c><21><2c><4><6><0><0><0><0><84><4><6><0><0><0><0><84><a><6><0><0><0><0><4><13><4a><30><0><0>
MBus consecutive Frame [183]-><68><b1><b1><68><8><0><72><4><26><15><46><49><6a><88><d><29><0><0><0><4><6d><34><a><27><2c><82><4><6c><21><21><82><a><6c><21><2c><4><6><0><0><0><0><84><4><6><0><0><0><0><84><a><6><0><0><0><0><4><13><4a><30><0><0><2><59><8a><7><2><5d><bc><7><2><61><ce><ff><4><3b><bf><2><0><0><4><2d><4><0><0><0><4><26><b><8><0><0><84><10><6><2><0><0><0><84><14><6><0><0><0><0><84><1a><6><0><0><0><0><84><40><14><c1><6><0><0><84><44><14><0><0><0><0><84><4a><14><a9><0><0><0><84><80><40><14><10><0><0><0><84><84><40><14><0><0><0><0><84><8a><40><14><0><0><0><0><84><c0><40><14><e3><0><0><0><84><c4><40><14><0><0><0><0><84><ca><40><14><0><0><0><0><1b><16>

Readout insert->INSERT INTO LETTURE_CONTATORI_TEMP VALUES(NULL,'OK','1','1','510','07/12/2017 10:16:23','','','1512641783','0','07/12/2017 10:52','01/01/2017','01/12/2017','0','0','0','12362','1930','1980','-50','703','4','2059','2','0','0','1729','0','169','16','0','0','227','0','0','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');

最佳答案

好的,因此,每个字符的偏移量为 65 (A),您可以创建一个字母映射,将它们转换为更小的值,适合 2 个字节(16 位),其中值的范围从 0 到 25(0=A、1=B...、25=Z)。由于此范围最多需要 5 位,并且您最多需要转换 3 个字符,因此您只需要 15 位,并且可以将它们压缩为制造商 ID 所需的 2 个字节(16 位)。您所要做的就是应用 5 位移位(值的大小)* 制造商 ID 字符串中的字符索引。

方法如下

  public static short createManuID(String id)
{
int bitMashedManuID = 0;
id = id.toUpperCase(); //force the chars to be within 65-90
if(id.length() == 3)
{
short offset = 65; //A = 0, B = 1 ... Z = 25
//number bits needed to fit 0-25 and so values won't overlap during the bit mashing
short bitShift = 5;
for(int i = 0; i < id.length(); i++)
{
short valueOfChar = (short)id.charAt(i);
valueOfChar -= offset; //apply the offset
bitMashedManuID += valueOfChar << bitShift * i; //pack the bits
}
}
return (short)bitMashedManuID;
}

示例

Z = 90,应用偏移量 65,我们得到 25 (11001)

因此 ZZZ 的制造商 ID 应类似于 (11001|11001|11001),等于 26425。

System.out.println(createManuID("ZZZ")); //outputs 26425

您的制造商 ID

Z = 90 - 65 = 25 = 11001
R = 82 - 65 = 17 = 10001
I = 73 - 65 = 8 = 01000

ZRI = |01000|10001|11001| = 8761

System.out.println(createManuID("ZRI")); //8761

因此,当一切都说完之后,您可以像这样创建字节数组,而不会溢出并满足 8 字节数组长度要求。

  public static void main(String[] args) 
{
byte[] idNum = ByteBuffer.allocate(4).putInt(46152604).array();
byte version = 0xFF & 88; //only need a byte not a 4 byte int
byte deviceType = 0xFF & 13; //only need a byte not a 4 byte int

short manuID = createManuID("ZRI");
//builds the message without overflow now
byte[] data = ByteBuffer.allocate(8).put(idNum).putShort(manuID).put(version).put(deviceType).array();

}

剩下的就是确定要打包的字母的顺序。目前我从右到左打包它们,但根据您正在交谈的设备,可能需要从左到右,这意味着循环从 for(int i = id.length() - 1; i >= 0; i--) 开始

关于java.nio.BufferOverflowException 构造 byte[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47701264/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com