安卓物联网开发指令集转换问题(一)

前言

进行安卓端物联网开发时分为蓝牙传输和IOT传输,上述两种通信方式都是要依赖于十六进制bytes指令集进行传输,Android收到设备发出的指令集进行解析,从而得到数据源,然后根据数据源进行业务逻辑处理和UI页面的刷新。


十六进制bytes指令集是什么?

在此之前,我们先了解bit、byte、位、字节、字符的关系

a.字节
字节(Byte)-- 通常将可表示常用英文字符8位二进制称为一个字节;例如:0xFF、0xaa、0x33;
1字节(Byte) = 8位(bit)
例如:0xFF(十六进制) = 255 (十进制)= 1111 1111(二进制)
上述进制转换请使用mac科学计算器/win-Google搜索进制转换
比特(Bit),称之为二进制位,比特是二进制中的一位,是二进制最小信息单位,1个比特就是1位。

字节(Byte): 字节是通过网络传输信息(或在硬盘、内存中存储信息)的单位。字节是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制。在ASCII码中,一个英文字母(不区分大小写)占一个字节的空间,一个汉字占两个字节的空间,一个英文标点占一个字节,一个汉语标点占两个字节。其他语种请查阅Google!
一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,如一个ASCII码就是一个字节,此类单位换算如下:

计量单位 占字节数 2的次幂 换算公式
1千吉字节(TB) 1024吉字节 2的40次方字节 1TB=1024GB
1 吉字节(GB) 1024兆字节 2的30次方字节 1GB=1024MB
1 兆字节(MB) 1024千字节 2的20次方字节 1MB=1024KB
1 兆字节(MB) 1024千字节 2的20次方字节 1MB=1024KB
1 千字节(KB) 1024千字节 2的10次方字节 1KB=1024B
1 字节(Byte) 1byte=8bit

关于ASCII码的解释: 在计算机中所有的数据存储和运算都要使用二进制数来表示(因为计算机用高电平和低电平分别表示1和0)ASCII码是一种7位编码,但它存放时必须占全一个字节,也即占用8位。例如,像a、b、c这样的52个字母(包含大写)以及0,1等数字以及一些常用的符号(例如:#、@、*等)在计算机中存储也要使用二进制数来表示,而具体使用哪些二进制数字来表示哪个符号,使用国际标准化组织(International Organization for Standardization,ISO)定的国际编码标准,即ISO 646标准,此标准适用于所有拉丁文字母!

b.计算机中的位:
二进制数系统中,每个0或1就是一个位(比特/bit) ,位是数据存储的最小单位。其中8bit就称为一个字节(Byte)。计算机中的CPU位数指的是CPU一次能处理的最大位数。例如64位计算机的CPU一次最多能处理64位数据。

c.bit/比特/位:
1)计算机专业术语,是信息量单位,是有英文BIT音译而成bit,新港台译为位元,(猜测位的说法来源于位元),二进制数的一位所包含的信息就是一比特,如十六进制0xFF等于十进制的255,等于二进制的1111 1111,这1111 1111就是8bit/比特/位元/位。

2) 二进制数字中的位,信息量的度量单位,为信息量的最小单位,数字化音响中用电脉冲来表达音频信号,“1”代表有脉冲,“0”代表脉冲间隔。如果波形上每个点的信息用四位一组的代码表示,则称之为4比特/位/位元/bit,比特数越高,表达模拟信号越精确,对音频信号还原能力则更强!

d. 字符:
字符是可使用多种不同字符方案或代码页来表示的抽象实体。例如,Unicode UTF-16编码将字符表示为16位整数序列,而Unicode UTF-8编码则将相同的字符表示为8位字节序列。公共语言运行库使用Unicode UTF-16(Unicode转换格式,16位编码形式)表示字符。

发送字节序列作为IOT或蓝牙传输的指令集:

a):
在这里插入图片描述
如上图,设备或服务器传输过来的字节指令集序列中其中两个byte中最高位bit设置为了特定标志位,剩下15个bit表示了特定数值。
下面的函数可以完成相关转换:

/**
 *  功能描述:根据多位byte转成具体int值
 *  @param value 多位的byte
 *  @param hFirst 是否高位在前
 **/
fun getSignedBytesToInt(value: ByteArray, hFirst: Boolean = true): Int {
    var result = 0
    var loop: Byte
    val length = value.size
    if (hFirst) {
        for (i in 0 until length) {
            loop = value[length - 1 - i]
            result += loop.toInt() and 0xFF shl 8 * i
        }
    }
    else {
        for (i in 0 until length) {
            loop = value[i]
            result += loop.toInt() and 0xFF shl 8 * i
        }
    }
    return result
}

/**
 * 多位byte转换为int值,求除了最高bit位外剩余bit位之和
 * @param hFirst: 是否高位在前
 */
fun bytesToInt(value: ByteArray, hFirst: Boolean = true): List<Int> {
    val length = value.size
    val list = mutableListOf<Int>()
    val result = getSignedBytesToInt(value, hFirst)
    /*取减去最高比特位之和*/
    val shlOrShr = length * 8 - 1
    val highBitValue: Int = result and (1 shl shlOrShr)
    val highBitNum: Int = (highBitValue and 0xFF) shr shlOrShr
    val calculateBitValue: Int = result - highBitValue
    list.add(highBitNum)
    list.add(calculateBitValue)
    return list
}

第一步:
getSignedBytesToInt(…,…)函数中的for循环可以将传进来的字节数组中的每个字节和0xFF执行与操作,然后逻辑左移8个bit位 * i。因为任何数和1(bit)做与操作都是任何数本身,任何数和0(bit)做与操作都是0,然后还有一个hFirst的判断,这是调用该函数时的传参,决定传进来的字节数组是前面的那个字节算高位字节,还是后面的那个字节算高位字节。高位在前和高位在后使用两种转换方式,通过这个函数我们将字节转换为了整型。
第二步:
bytesToInt(…, …)函数中调用上述getSignedBytesToInt(…,…)函数,得到返回值是相应的整型值,图中是两个byte中最高位为我们需要的标志位,我们则要把1左移8 * length - 1就移动到了那个最高位bit位,图中两个byte就是15个bit位,1左移动shl(left)就是1000 0000,result and/与 1000 0000
因为和1与为本身,和0与为0,所以能得到最高bit位是0还是1,之后将这个result和1000 0000与之后得到的数右移shr8*length - 1 ,即右移15位,这个时候就能得到最高bit位数,0000 0001 或 0000 0000,就得到了我们需要的标志位;最后通过result - highBitValue就能得到后15位的bit位之和。

b):
取出一个字节(byte)中的每一位bit:

/**
 *  功能描述:根据下标取具体位数的值
 *  @param value 对应的int值
 *  @param index int转成8byte后具体取byte的第几位
 **/
fun getByteValueByIndex(value: Int, index: Int): Int {
    return when (index) {
        1 -> {
            (value and 0x02) shr 1
        }
        2 -> {
            (value and 0x04) shr 2
        }
        3 -> {
            (value and 0x08) shr 3
        }
        4 -> {
            (value and 0x10) shr 4
        }
        5 -> {
            (value and 0x20) shr 5
        }
        6 -> {
            (value and 0x40) shr 6
        }
        7 -> {
            (value and 0x80) shr 7
        }
        else -> {
            value and 0x01
        }
    }
}

上述代码举个例子:传入一个byte 0x36 ,如果想取出传入的value的index为0的bit,就value and 0x01 ,可以得出第一位bit的值,如果传入的index为1,就value and 0x02(==0000 0010) 可以得到第二位bit的值,同样是因为和1“与”为本身,和0“与”为0, 之后shr/右移 一位,其他index为2、3、4、5、6、7都是同理。还有一种方法取出一个字节(byte)中的每一位(bit),

    val isEqualsZero = value and 0x01 == 0x01
    val valueZero = if (isEqualsZero) 1 else 0
    val isEqualsOne = value and 0x02 == 0x02
    val valueOne =if (isEqualsOne) 1 else 0
    val isEqualsTwo = value and 0x04 == 0x04
    val valueTwo =if (isEqualsTwo) 1 else 0
    val isEqualsThree = value and 0x08 == 0x08
    val valueThree =if (isEqualsThree) 1 else 0
    val isEqualsFour = value and 0x10 == 0x10
    val valueFour =if (isEqualsFour) 1 else 0
    val isEqualsFive = value and 0x20 == 0x20
    val valueFive =if (isEqualsFive) 1 else 0
    val isEqualsSix = value and 0x40 == 0x40
    val valueSix =if (isEqualsSix) 1 else 0
    val isEqualsSeven = value and 0x80 == 0x80
    val valueSeven =if (isEqualsSeven) 1 else 0

总结

下一篇继续研究物联网指令集转换问题(二)

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>