java 上位机编程常用的 BCD 码、ASCII,BIN 码常用格式解析生成。
2023-12-20 07:59:24
? ? ? 1 生成报文序列seq
? ? ? ? 序列号域即为数据包的发送顺序号,从 0 开始顺序增加,如是应答数据包,则与询问数据包序号保持一致,当桩与平台网络断开重新建立连接或者溢出后归 0。
import java.util.HashMap;
/**
* @author hua
* @date 2023-10-10 19:09
*/
public class SeqNumGenerator {
private static HashMap<String,SeqNumGenerator> local=new HashMap<String,SeqNumGenerator>();
/**
* 开始序列
*/
private short sequenceNumber = 0;
/**
* 依据报文格式要求设置最允许序列
*/
private short maxSeqLimit = 99;
public byte[] getNextSequenceNumber() {
// 递增序号
sequenceNumber++;
if(sequenceNumber>maxSeqLimit){
sequenceNumber=0;
}
byte[] bytes = new byte[2];
bytes[0] = (byte) (sequenceNumber & 0xFF);
bytes[1] = (byte) ((sequenceNumber >> 8) & 0xFF);
return bytes;
}
/**
* 报文序列生成
* @param seqKeyName
* @return
*/
public static byte[] getSeq(String seqKeyName){
if(!(seqKeyName!=null&&seqKeyName.trim().length()>0)){
seqKeyName="common";
}
if(local.get(seqKeyName)==null){
SeqNumGenerator generator = new SeqNumGenerator();
byte[] r=generator.getNextSequenceNumber();
return r;
}else{
return local.get(seqKeyName).getNextSequenceNumber();
}
}
}
2 bcd格式解析?
static final char[] HEX_CHAR = "0123456789ABCDEF".toCharArray();
/**
* 转金额
*
* @param dataByte bcd码
* @param left 左移位数, 123456 -> 12345.6
* @return
*/
public static BigDecimal getBcdValueBy(byte[] dataByte, int left) {
byte[] data = MessageUtils.convertToLittleEndian(dataByte);
char[] chars = new char[data.length * 2];
for (int i = 0; i < data.length; ++i) {
chars[i * 2] = HEX_CHAR[data[i] >> 4 & 15];
chars[i * 2 + 1] = HEX_CHAR[data[i] & 15];
}
String str = new String(chars).toLowerCase();
return new BigDecimal(str).movePointLeft(left);
}
3 bin格式解析
/**
* bin码解析
*
* @param bytes
* @return
*/
public static int getPriceByBin(byte[] bytes) {
int result = 0;
for (int i = bytes.length - 1; i >= 0; i--) {
result = (result << 8) | (bytes[i] & 0xFF);
}
return result;
}
4 生成下发金额生成bin
? 文档要求:
? 按文档生成长度为4的byte字节,精度五位小数
/**
* 计费规则用 4byte 5位小数
*
* @param price
* @return
*/
public static byte[] get4bPrice(BigDecimal price) {
int price_int = price.movePointRight(5).intValue();//右移5位,与文档要求一致
ByteBuffer byteBuffer = ByteBuffer.allocate(4); //这里的4是与设备下发要求的长度一致
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); //这里是小端模式
byteBuffer.putInt(price_int);
byte[] bytes =byteBuffer.array();
return bytes;
}
5 生成bcd数据
// 将十进制数字转换为BCD码
public static byte[] getBCDBy(int dec) {
int temp = dec;
// 计算BCD码数组的长度
int bcdLength = (int) Math.ceil((double) Integer.toString(dec).length() / 2);
// 创建存储BCD码的字节数组
byte[] bcdCode = new byte[bcdLength];
// 从右向左遍历BCD码数组
for (int i = bcdLength - 1; i >= 0; i--) {
// 取出最低位的十进制数字
byte lowerNibble = (byte) (temp % 10);
// 取出次低位的十进制数字
byte upperNibble = (byte) ((temp / 10) % 10);
// 使用位运算将两个十进制数字合并成一个字节,高位使用upperNibble,低位使用lowerNibble
bcdCode[i] = (byte) ((upperNibble << 4) | lowerNibble);
// 将temp右移两位,准备处理下两位十进制数字
temp /= 100;
}
return bcdCode;
}
6 ascii码解析
public static String bytesToAscii(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append((char) b);
}
return sb.toString();
}
7 互转大小端
? 设备上传的不全是小端时需要转换。window平台一般都是小端模式。
/**
* 互转小端
*
* @param data
* @return
*/
public static byte[] convertToLittleEndian(byte[] data) {
byte[] converted = new byte[data.length];
for (int i = 0; i < data.length; i++) {
converted[i] = data[data.length - i - 1];
}
return converted;
}
文章来源:https://blog.csdn.net/qyhua/article/details/135063769
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!