| | |
| | | import com.dayu.baselibrary.bean.BaseUserCardCard |
| | | import com.dayu.baselibrary.tools.BcdUtil |
| | | import com.dayu.baselibrary.tools.HexUtil |
| | | import com.dayu.general.tool.CardCommon.Companion.USER_CARD_TYPE_1 |
| | | import java.io.Serializable |
| | | import java.util.* |
| | | |
| | | /** |
| | | * 通用项目用户卡结构 |
| | | */ |
| | | class UserCard : BaseCard(), Serializable { |
| | | var cardType: String = "A1" // 卡类型:A1终端写卡 A8刷卡开泵后值 A2叠加充值 |
| | | var areaNumber: Int = 0 // 国家行政区域号(12位BCD,精确到村) |
| | | class UserCard : BaseUserCardCard(), Serializable { |
| | | var cardType: String = USER_CARD_TYPE_1 // 卡类型:A1终端写卡 A8刷卡开泵后值 A2叠加充值 |
| | | var areaNumber: String = "" // 国家行政区域号(12位BCD,精确到村) |
| | | var userCode: String = "" // 用户编号BCD |
| | | var userCodeNumber: Int = 0 // 用户卡编号(HEX) |
| | | var phoneNumber: String = "" // 手机号(BCD) |
| | | var projectCode: Int = 0 // 项目编码(HEX 1-255) |
| | | var balance: Int = 0 // 剩余金额(2位小数点,单位元) |
| | | var balance: Int = 0 // 剩余金额(2位小数点,单位分) |
| | | var surplusWater: Int = 0 // 剩余水量(2位小数点,单位立方米) |
| | | var waterPrice: Float = 0f // 水量单价(最大655.35,2位小数点。单位:m3/元) |
| | | var electricPrice: Float = 0f // 电量单价(最大655.35,2位小数点。单位: 元/度) |
| | | var waterPrice: Int = 0 // 水量单价(2位小数点,单位分/m3) |
| | | var electricPrice: Int = 0 // 电量单价(2位小数点,单位分/度) |
| | | var rechargeDate: Calendar? = null // 充值时间 |
| | | |
| | | /** |
| | |
| | | if (data == null || data.size < 3) { |
| | | return false |
| | | } |
| | | |
| | | |
| | | val expectedBytes = arrayOf(getZeroBytes(), getOneBytes(), getTwoBytes()) |
| | | return data.zip(expectedBytes.toList()).all { (actual, expected) -> |
| | | actual.contentEquals(expected) |
| | | return data.zip(expectedBytes.toList()).all { (actual, expected) -> |
| | | actual.contentEquals(expected) |
| | | } |
| | | } |
| | | |
| | |
| | | /** |
| | | * 通过byte转bean |
| | | */ |
| | | fun getBean(data: List<ByteArray>): UserCard? { |
| | | override fun getBean(data: List<ByteArray>): UserCard? { |
| | | try { |
| | | val userCard = UserCard() |
| | | // 解析第0块 |
| | |
| | | userCard.apply { |
| | | // 解析国家行政区域号(0-5位) |
| | | val areaCodeBytes = zero.copyOfRange(0, 6) |
| | | areaNumber = BcdUtil.bcdToStr(areaCodeBytes).toInt() |
| | | areaNumber = BcdUtil.bcdToStr(areaCodeBytes) |
| | | |
| | | // 解析用户卡编号(6-7位) |
| | | val userCodeNumberBytes = zero.copyOfRange(6, 8) |
| | |
| | | projectCode = HexUtil.get16To10LowHightByBytes(byteArrayOf(one[0])) |
| | | balance = HexUtil.get16To10LowHightByBytes(one.copyOfRange(1, 5)) |
| | | surplusWater = HexUtil.get16To10LowHightByBytes(one.copyOfRange(5, 9)) |
| | | electricPrice = HexUtil.hexToFloatLowHigh(one.copyOfRange(9, 11)) |
| | | |
| | | electricPrice = HexUtil.get16To10LowHightByBytes(one.copyOfRange(9, 11)) |
| | | |
| | | // 解析充值时间 |
| | | val year = HexUtil.getBcdToInt(one[11]) |
| | | val month = HexUtil.getBcdToInt(one[12]) |
| | |
| | | // 解析第2块 |
| | | val two = data[2] |
| | | userCard.apply { |
| | | waterPrice = HexUtil.hexToFloatLowHigh(two.copyOfRange(9, 11)) |
| | | waterPrice = HexUtil.get16To10LowHightByBytes(two.copyOfRange(9, 11)) |
| | | } |
| | | |
| | | return userCard |
| | |
| | | val data = ByteArray(16) |
| | | try { |
| | | // 设置国家行政区域号(BCD格式,6字节,0-5位) |
| | | val areaCodeBytes = BcdUtil.strToBcd(String.format("%012d", areaNumber)) |
| | | System.arraycopy(areaCodeBytes, 0, data, 0, 6) |
| | | val areaNumberStr = if (areaNumber.isBlank() || !areaNumber.all { it.isDigit() }) { |
| | | "000000000000" |
| | | } else { |
| | | areaNumber.padStart(12, '0') |
| | | } |
| | | val areaCodeBytes = BcdUtil.strToBcd(areaNumberStr) |
| | | System.arraycopy(areaCodeBytes, 0, data, 0, minOf(areaCodeBytes.size, 6)) |
| | | |
| | | // 设置用户卡编号(HEX格式,2字节,6-7位) |
| | | // 设置用户卡编号(HEX格式,2字节,6-7位) - 修复:确保数组长度正确 |
| | | val userCodeBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(userCodeNumber)) |
| | | System.arraycopy(userCodeBytes, 0, data, 6, 2) |
| | | val userCodePadded = ByteArray(2) |
| | | System.arraycopy(userCodeBytes, 0, userCodePadded, 0, minOf(userCodeBytes.size, 2)) |
| | | System.arraycopy(userCodePadded, 0, data, 6, 2) |
| | | |
| | | // 设置卡类型(8位) |
| | | data[8] = HexUtil.hexToByte(cardType) |
| | | |
| | | // 设置手机号(BCD格式,6字节,9-14位) |
| | | val phoneBytes = BcdUtil.strToBcd(phoneNumber.padStart(12, '0')) |
| | | System.arraycopy(phoneBytes, 0, data, 9, 6) |
| | | System.arraycopy(phoneBytes, 0, data, 9, minOf(phoneBytes.size, 6)) |
| | | |
| | | // 设置校验和(15位) |
| | | data[15] = getByteSum(data) |
| | |
| | | val data = ByteArray(16) |
| | | try { |
| | | data[0] = projectCode.toByte() |
| | | |
| | | // 设置余额 |
| | | val balanceBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(balance)) |
| | | System.arraycopy(balanceBytes, 0, data, 1, 4) |
| | | |
| | | // 设置剩余水量 |
| | | val waterBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(surplusWater)) |
| | | System.arraycopy(waterBytes, 0, data, 5, 4) |
| | | |
| | | // 设置电价 |
| | | val priceBytes = HexUtil.hexToByteArray(HexUtil.floatToHexLowHigh(electricPrice)) |
| | | System.arraycopy(priceBytes, 0, data, 9, 2) |
| | | |
| | | |
| | | // 设置余额 - 修复:确保数组长度正确 |
| | | val balanceHex = HexUtil.get10To16LowHigh(balance) |
| | | val balanceBytes = HexUtil.hexToByteArray(balanceHex) |
| | | val balancePadded = ByteArray(4) |
| | | System.arraycopy(balanceBytes, 0, balancePadded, 0, minOf(balanceBytes.size, 4)) |
| | | System.arraycopy(balancePadded, 0, data, 1, 4) |
| | | |
| | | // 设置剩余水量 - 修复:确保数组长度正确 |
| | | val waterHex = HexUtil.get10To16LowHigh(surplusWater) |
| | | val waterBytes = HexUtil.hexToByteArray(waterHex) |
| | | val waterPadded = ByteArray(4) |
| | | System.arraycopy(waterBytes, 0, waterPadded, 0, minOf(waterBytes.size, 4)) |
| | | System.arraycopy(waterPadded, 0, data, 5, 4) |
| | | |
| | | // 设置电价 - 修复:确保数组长度正确 |
| | | val electricPriceHex = HexUtil.get10To16LowHigh(electricPrice) |
| | | val electricPriceBytes = HexUtil.hexToByteArray(electricPriceHex) |
| | | val electricPricePadded = ByteArray(2) |
| | | System.arraycopy(electricPriceBytes, 0, electricPricePadded, 0, minOf(electricPriceBytes.size, 2)) |
| | | System.arraycopy(electricPricePadded, 0, data, 9, 2) |
| | | |
| | | // 设置充值时间 |
| | | rechargeDate?.let { |
| | | data[11] = HexUtil.getIntToBCD(it.get(Calendar.YEAR) % 100)[0] |
| | |
| | | data[13] = HexUtil.getIntToBCD(it.get(Calendar.DAY_OF_MONTH))[0] |
| | | data[14] = HexUtil.getIntToBCD(it.get(Calendar.HOUR_OF_DAY))[0] |
| | | } |
| | | |
| | | |
| | | data[15] = getByteSum(data) |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | |
| | | fun toBytes(): ByteArray { |
| | | val data = ByteArray(16) |
| | | try { |
| | | // 备份余额和水量数据 |
| | | val balanceBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(balance)) |
| | | System.arraycopy(balanceBytes, 0, data, 1, 4) |
| | | |
| | | val waterBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(surplusWater)) |
| | | System.arraycopy(waterBytes, 0, data, 5, 4) |
| | | |
| | | // 设置水价 |
| | | val priceBytes = HexUtil.hexToByteArray(HexUtil.floatToHexLowHigh(waterPrice)) |
| | | System.arraycopy(priceBytes, 0, data, 9, 2) |
| | | |
| | | // 备份余额和水量数据 - 修复:确保数组长度正确 |
| | | val balanceHex = HexUtil.get10To16LowHigh(balance) |
| | | val balanceBytes = HexUtil.hexToByteArray(balanceHex) |
| | | val balancePadded = ByteArray(4) |
| | | System.arraycopy(balanceBytes, 0, balancePadded, 0, minOf(balanceBytes.size, 4)) |
| | | System.arraycopy(balancePadded, 0, data, 1, 4) |
| | | |
| | | val waterHex = HexUtil.get10To16LowHigh(surplusWater) |
| | | val waterBytes = HexUtil.hexToByteArray(waterHex) |
| | | val waterPadded = ByteArray(4) |
| | | System.arraycopy(waterBytes, 0, waterPadded, 0, minOf(waterBytes.size, 4)) |
| | | System.arraycopy(waterPadded, 0, data, 5, 4) |
| | | |
| | | // 设置水价 - 修复:确保数组长度正确 |
| | | val waterPriceHex = HexUtil.get10To16LowHigh(waterPrice) |
| | | val waterPriceBytes = HexUtil.hexToByteArray(waterPriceHex) |
| | | val waterPricePadded = ByteArray(2) |
| | | System.arraycopy(waterPriceBytes, 0, waterPricePadded, 0, minOf(waterPriceBytes.size, 2)) |
| | | System.arraycopy(waterPricePadded, 0, data, 9, 2) |
| | | |
| | | // 设置充值时间 |
| | | rechargeDate?.let { |
| | | data[11] = HexUtil.getIntToBCD(it.get(Calendar.YEAR) % 100)[0] |
| | |
| | | data[13] = HexUtil.getIntToBCD(it.get(Calendar.DAY_OF_MONTH))[0] |
| | | data[14] = HexUtil.getIntToBCD(it.get(Calendar.HOUR_OF_DAY))[0] |
| | | } |
| | | |
| | | |
| | | data[15] = getByteSum(data) |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | |
| | | } |
| | | } |
| | | |
| | | fun getZeroBytes(): ByteArray = Zero().toBytes() |
| | | fun getOneBytes(): ByteArray = One().toBytes() |
| | | fun getTwoBytes(): ByteArray = Two().toBytes() |
| | | override fun getZeroBytes(): ByteArray = Zero().toBytes() |
| | | override fun getOneBytes(): ByteArray = One().toBytes() |
| | | override fun getTwoBytes(): ByteArray = Two().toBytes() |
| | | } |