左晓为主开发手持机充值管理机
zuojincheng
2025-03-21 8521954fa97bdfc54123afb4a72755ece311db06
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.dayu.general.bean.card
 
import com.dayu.baselibrary.tools.BcdUtil
import com.dayu.baselibrary.tools.HexUtil
import com.dayu.general.tool.CardCommon.Companion.ELECTRIC_PRICE_CARD
import com.dayu.general.tool.CardCommon.Companion.MANAGE_CRAD
import java.io.Serializable
 
/**
 * 取数卡
 * 用于在用户卡丢失后,读取当前用户或挂起用户的卡内信息,作为补卡依据
 */
class FetchDataCard : BaseCard(), Serializable {
    companion object {
        const val CARD_TYPE_NEED_FETCH = ELECTRIC_PRICE_CARD    // 需要刷卡取数
        const val CARD_TYPE_FETCH_SUCCESS = MANAGE_CRAD  // 刷卡取数返写成功
 
    }
 
    var areaNumber: Int = 0      // 国家行政区域号(12位BCD,精确到村)
    var userNumber: Int = 0      // 用户编号(HEX)
    var cardType: String = CARD_TYPE_NEED_FETCH  // 卡类型:B1需要刷卡取数,B2刷卡取数返写成功
    var projectCode: Int = 0     // 项目编码(HEX 1-255)
 
    /**
     * 写卡完成后校验是否写卡成功
     */
    fun equalsFetchDataCard(data: List<ByteArray>?): Boolean {
        if (data == null || data.isEmpty()) {
            return false
        }
        return data[0].contentEquals(getZeroBytes())
    }
 
    /**
     * 通过byte转bean
     */
    fun getBean(data: List<ByteArray>): FetchDataCard? {
        try {
            val fetchDataCard = FetchDataCard()
            // 解析第0块
            val zero = data[0]
            
            // 解析国家行政区域号(0-5位)
            val areaCodeBytes = zero.copyOfRange(0, 6)
            fetchDataCard.areaNumber = BcdUtil.bcdToStr(areaCodeBytes).toInt()
            
            // 解析用户编号(6-7位)
            val userNumberBytes = zero.copyOfRange(6, 8)
            fetchDataCard.userNumber = HexUtil.get16To10LowHightByBytes(userNumberBytes)
            
            // 解析卡类型(8位)
            val cardType = HexUtil.byteToHex(zero[8])
            if (cardType != CARD_TYPE_NEED_FETCH && cardType != CARD_TYPE_FETCH_SUCCESS) {
                return null
            }
            fetchDataCard.cardType = cardType
            
            // 验证识别码(9-12位)
            if (zero[9] != IDENTIFY_CODE_A0 ||
                zero[10] != IDENTIFY_CODE_B1 ||
                zero[11] != IDENTIFY_CODE_C2 ||
                zero[12] != IDENTIFY_CODE_89) {
                return null
            }
            
            // 解析项目编码(13位)
            fetchDataCard.projectCode = HexUtil.get16To10LowHightByBytes(byteArrayOf(zero[13]))
 
            return fetchDataCard
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }
 
    /**
     * 生成第0块数据
     */
    inner class Zero : BaseCard() {
        fun toBytes(): ByteArray {
            val data = ByteArray(16)
            try {
                // 设置国家行政区域号(BCD格式,6字节,0-5位)
                val areaCodeBytes = BcdUtil.strToBcd(String.format("%012d", areaNumber))
                System.arraycopy(areaCodeBytes, 0, data, 0, 6)
                
                // 设置用户编号(6-7位)
                val userNumberBytes = HexUtil.hexToByteArray(HexUtil.get10To16LowHigh(userNumber))
                System.arraycopy(userNumberBytes, 0, data, 6, 2)
                
                // 设置卡类型(8位)
                data[8] = HexUtil.hexToByte(cardType)
                
                // 设置识别码(9-12位)
                data[9] = IDENTIFY_CODE_A0
                data[10] = IDENTIFY_CODE_B1
                data[11] = IDENTIFY_CODE_C2
                data[12] = IDENTIFY_CODE_89
                
                // 设置项目编码(13位)
                data[13] = projectCode.toByte()
                
                // 设置备用位(14位)
                data[14] = 0x00
                
                // 设置校验和(15位)
                data[15] = getByteSum(data)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return data
        }
    }
 
    /**
     * 将卡片状态更新为取数成功
     */
    fun markAsFetchSuccess() {
        cardType = CARD_TYPE_FETCH_SUCCESS
    }
 
    /**
     * 检查是否已经取数成功
     */
    fun isFetchSuccess(): Boolean {
        return cardType == CARD_TYPE_FETCH_SUCCESS
    }
 
    fun getZeroBytes(): ByteArray = Zero().toBytes()