riku
2021-06-17 81bd0388494d45463de42cd91bd8c33f10f0030a
src/main/kotlin/com/flightfeather/uav/socket/decoder/DataPackageDecoder.kt
@@ -1,7 +1,8 @@
package com.flightfeather.uav.socket.decoder
import com.flightfeather.uav.socket.bean.DataUnit
import com.flightfeather.uav.socket.eunm.ObdCommandUnit
import com.flightfeather.uav.socket.eunm.AirCommandUnit
import java.util.*
/**
 * uav 第一层数据包解码器
@@ -11,32 +12,107 @@
 * 数据第一层结构定义如下:
 * 起始字节         定义
 * 0                    起始符
 * 2                    命令单元  类型@see [ObdCommandUnit]
 * 3                    车辆识别号
 * 4                    终端软件版本号
 * 21                   数据加密方式
 * 22                   数据单元长度
 * 24                   数据单元  解码器@see [DataUnitDecoder]
 * 倒数第1           校验码
 * 1                   命令单元  类型@see [AirCommandUnit]
 * 2                   数据单元长度
 * 倒数第2           校验码
 */
interface DataPackageDecoder {
class DataPackageDecoder {
    fun getHead(b: List<String>): String?
    companion object {
        //        数据头
        const val HEAD_BYTES = 1
        //        监测参数确认指令位
        const val COMMAND_UNIT_BYTES = 1
        //        设备类型
        const val DEVICE_CODE_BYTES = 6
        //        本次监测的空气因子数量
        const val DATA_LENGTH = 1
        //        校验
        const val BCC_BYTES = 2
    }
    fun getCommandUnit(b: List<String>): Int?
    private val dataUnitDecoder: DataUnitDecoder = DataUnitDecoder()
    fun getVinCode(b: List<String>): String?
    fun getSoftwareVersion(b: List<String>): Int?
    fun getHead(b: List<String>): String? {
        return if (b.isNotEmpty()) {
            val s = StringBuilder()
            repeat(HEAD_BYTES) {
                s.append(b[it])
            }
            s.toString()
        } else {
            null
        }
    }
    fun getEncryptionWay(b: List<String>): Int?
    fun getCommandUnit(b: List<String>): Int? = if (b.size >= (HEAD_BYTES + COMMAND_UNIT_BYTES)) {
        val s = StringBuilder()
        repeat(COMMAND_UNIT_BYTES) {
            s.append(b[HEAD_BYTES + it])
        }
        s.toString().toIntOrNull(16)
    } else {
        null
    }
    fun getDataLength(b: List<String>): Int
    fun getDeviceCode(b: List<String>): String? = if (b.size >= (HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES)) {
        //2021/1/7 '0A'代表车载设备,'0B'代表无人机设备,'0C'为网格化监测
        val s = StringBuilder()
        repeat(DEVICE_CODE_BYTES) {
            s.append(b[HEAD_BYTES + COMMAND_UNIT_BYTES + it])
        }
        s.toString()
    } else {
        null
    }
    fun getDataUnit(b: List<String>): List<DataUnit>
    fun getDataTime(b: List<String>): Date {
        // FIXME: 2021/1/7 采样时间和监测因子一同放在了数据部分,此处不再做解析
        return Date()
    }
    fun getCheckCode(b: List<String>): Int?
    fun getDataLength(b: List<String>): Int {
        if (b.size <= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH) return 0
    fun toStringList(msg: String): List<String>
        val hexNum = b[HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES]
        return hexNum.toIntOrNull(16) ?: 0
    }
    fun getDataUnit(b: List<String>): List<DataUnit> {
        if (getDataLength(b) == 0 || b.size <= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH) {
            return emptyList()
        }
        val unit = mutableListOf<String>()
        val start = HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH
        for (i in start..b.size - 1 - BCC_BYTES) {
            unit.add(b[i])
        }
        dataUnitDecoder.run {
            return when (getCommandUnit(b)) {
                AirCommandUnit.Confirm.value -> getAirConfirmData(unit, getDeviceCode(b))
                AirCommandUnit.AirData.value -> getAirData(unit, getDeviceCode(b))
                else -> emptyList()
            }
        }
    }
    fun getCheckCode(b: List<String>): Int? {
        return if (b.size >= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + BCC_BYTES) {
            val hexNum = "${b[b.size - 2]}${b[b.size - 1]}"
            hexNum.toIntOrNull(16)
        } else {
            null
        }
    }
    fun toStringList(msg: String): List<String> {
        return msg.split(" ")
    }
}