Slide 1

Slide 1 text

低レベルな Kotlin tomoya0x00 集まれKotlin好き︕Kotlin愛好会 vol2

Slide 2

Slide 2 text

About me tomoya0x00 Twitter, GitHub, Qiita Android, Embedded system, BLE/BT, iOS DeNA Co., Ltd. Automotive Business Unit.

Slide 3

Slide 3 text

低レベル 低レイヤー

Slide 4

Slide 4 text

BT/BLE通信をKotlinで書いてて ちょっとハマった事 ※BT/BLEの技術的な話しはゼロなのでご安⼼を ※⼀応、Androidアプリのお話しです

Slide 5

Slide 5 text

KotlinのByte型は 符号有り Javaも同じだけど

Slide 6

Slide 6 text

何が困るのか︖

Slide 7

Slide 7 text

何が困るのか︖ BT/BLE通信に限らず、デバイス間通信では 符号無し 前提で通信する ことがまぁまぁある なので、サイズ1byteで 符号無し な型が欲しくなるときがある

Slide 8

Slide 8 text

困る例 // 通信して受信したデータだとする val received = 0x80.toByte() // 10進数で 128 と出⼒されるのが期待値 println(received) result -128

Slide 9

Slide 9 text

NG

Slide 10

Slide 10 text

なぜこうなるのか︖

Slide 11

Slide 11 text

負の数のコンピューター内部表現

Slide 12

Slide 12 text

負の数のコンピューター内部表現 基本的には 2の補数 で表現されている 詳細は ぐぐる or 直接聞いてみてね︕ そして、最上位bitが⽴っていれば負の数と判定できる

Slide 13

Slide 13 text

KotlinのByte型における0x80とは 最上位bitが⽴っているので、負の数 10進数表現では -128 となってしまう

Slide 14

Slide 14 text

どうするのか︖

Slide 15

Slide 15 text

toInt()して下位1byteだけ取り出す 1. 符号無しとして扱ったときの最⼤値が⼗分に表現できる型へ変換 2. 不要な部分はマスクして捨てる // 通信して受信したデータだとする val received = 0x80.toByte() // 10進数で 128 と出⼒されるのが期待値 println(received.toInt() and 0xff) result 128

Slide 16

Slide 16 text

OK

Slide 17

Slide 17 text

Slide 18

Slide 18 text

チェックサム

Slide 19

Slide 19 text

チェックサム is 何︖

Slide 20

Slide 20 text

データ転送時のエラー検出⽅法の⼀つ シリアル通信とかで独⾃プロトコル実装時に良く使われている TCP/IPでも使われているよ チェックサム⾃体、何パターンかある 全部⾜してゼロ 全部⾜した下位1byte ★今回取り上げるパターン CRC etc...

Slide 21

Slide 21 text

Example

Slide 22

Slide 22 text

Aデバイス Bデバイス

Slide 23

Slide 23 text

0x80, 0x01, 0x02, 0x84 を送信したい

Slide 24

Slide 24 text

送信フォーマット 以降、送信フォーマットに合わせたデータを パケット と呼びます データ部サイズ (1byte) データ部(0〜 255byte) チェックサム(1byte) 0x01 0x02 0xfe ※チェックサムの計算にデータ部サイズは含めないものとする

Slide 25

Slide 25 text

送信︓Aデバイス 1. 0x80, 0x01, 0x02, 0x84 を全部⾜す -> 0x0107 2. 0x0107 の下位1byteを取り出す -> 0x07 3. 計算結果をチェックサム値とし、送信フォーマットに合わせて送信 送信したパケット データ部サイズ (1byte) データ部(0〜 255byte) チェックサム(1byte) 0x04 0x80,0x01,0x02,0x84 0x07

Slide 26

Slide 26 text

受信︓Bデバイス 1. 1byte読み出し、データ部サイズが4byteであることを知る 2. 4byte読み出して全部⾜し、下位1byteを取り出す -> 0x07 3. 1byte読み出し(チェックサム)、計算結果と合致を確認 受信したパケット データ部サイズ (1byte) データ部(0〜 255byte) チェックサム(1byte) 0x04 0x80,0x01,0x02,0x84 0x07

Slide 27

Slide 27 text

チェックサムの部分をKotlinで

Slide 28

Slide 28 text

in Kotlin 2の補数表現の事を考慮して・・・ // 通信して受信したByteArrayだとする val received = read() val size = received[0] val body = received.slice(1 until size + 1) val checkSum = received[size + 1] val sum = body.map { it.toLong() and 0xff }.sum() val isValid = (sum and 0xff) == (checkSum.toLong() and 0xff) println(isValid)

Slide 29

Slide 29 text

OK

Slide 30

Slide 30 text

But...

Slide 31

Slide 31 text

これでも良さそう ということに資料作っている内に気付きました・・・ // 通信して受信したByteArrayだとする val received = read() val size = received[0] val body = received.slice(1 until size + 1) val checkSum = received[size + 1] //val sum = body.map { it.toLong() and 0xff }.sum() val sum = body.sum() //val isValid = (sum and 0xff) == (checkSum.toLong() and 0xff) val isValid = sum and 0xff == checkSum.toInt() println(isValid)

Slide 32

Slide 32 text

なんででしょうね︖ 2の補数とかで説明できそうな気がしています

Slide 33

Slide 33 text

ありがとうございました