๐Ÿš€ BLE(Bluetooth Low Energy) ํ†ต์‹  ๊ตฌํ˜„: Java๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ €์ „๋ ฅ ๋ฌด์„  ์„ธ์ƒ ๐ŸŒŸ

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ BLE(Bluetooth Low Energy) ํ†ต์‹  ๊ตฌํ˜„: Java๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ €์ „๋ ฅ ๋ฌด์„  ์„ธ์ƒ ๐ŸŒŸ

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๋ฏธ๋ž˜์˜ BLE ๋งˆ์Šคํ„ฐ๋“ค! ์˜ค๋Š˜์€ ์—ฌ๋Ÿฌ๋ถ„๊ณผ ํ•จ๊ป˜ BLE(Bluetooth Low Energy) ํ†ต์‹ ์˜ ์„ธ๊ณ„๋กœ ํฅ๋ฏธ์ง„์ง„ํ•œ ์—ฌํ–‰์„ ๋– ๋‚˜๋ณด๋ ค๊ณ  ํ•ด์š”. ๐ŸŽข Java๋ฅผ ์‚ฌ์šฉํ•ด BLE ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๋ฉด์„œ, ๋งˆ์น˜ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋˜์–ด ๋””๋ฐ”์ด์Šค๋“ค์„ ์ž์œ ์ž์žฌ๋กœ ์กฐ์ข…ํ•˜๋Š” ๋“ฏํ•œ ๋Š๋‚Œ์„ ๋ฐ›๊ฒŒ ๋  ๊ฑฐ์˜ˆ์š”!

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท์ด๋ผ๋Š” ํ”Œ๋žซํผ์„ ๋“ค์–ด๋ณด์…จ๋‚˜์š”? ์ด๊ณณ์—์„œ๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ์ˆ  ์žฌ๋Šฅ์„ ๊ณต์œ ํ•˜๊ณ  ๊ฑฐ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. BLE ํ†ต์‹  ๊ตฌํ˜„ ๋Šฅ๋ ฅ๋„ ๋ถ„๋ช… ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ฐพ๋Š” ๊ท€์ค‘ํ•œ ์žฌ๋Šฅ์ด ๋  ๊ฑฐ์˜ˆ์š”. ์ž, ๊ทธ๋Ÿผ ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ BLE์˜ ์„ธ๊ณ„๋กœ ๋›ฐ์–ด๋“ค์–ด๋ณผ๊นŒ์š”? ๐ŸŠโ€โ™‚๏ธ

๐Ÿ” BLE๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”? ์ €์ „๋ ฅ์˜ ๋น„๋ฐ€์„ ํŒŒํ—ค์ณ๋ด์š”!

BLE, ์ฆ‰ Bluetooth Low Energy๋Š” ๊ธฐ์กด์˜ ๋ธ”๋ฃจํˆฌ์Šค๋ณด๋‹ค ํ›จ์”ฌ ์ ์€ ์ „๋ ฅ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„ ๋น„์Šทํ•œ ํ†ต์‹  ๋ฒ”์œ„๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฌด์„  ํ†ต์‹  ๊ธฐ์ˆ ์ด์—์š”. ๐Ÿ”‹โœจ

BLE์˜ ์ฃผ์š” ํŠน์ง•:

  • ์ดˆ์ €์ „๋ ฅ ์†Œ๋น„ ๐Ÿ‘
  • ๋น ๋ฅธ ์—ฐ๊ฒฐ ์†๋„ ๐Ÿš€
  • ์ž‘์€ ๋ฐ์ดํ„ฐ ํŒจํ‚ท ํฌ๊ธฐ ๐Ÿ“ฆ
  • ์ €๋ ดํ•œ ํ•˜๋“œ์›จ์–ด ๋น„์šฉ ๐Ÿ’ฐ

BLE๋Š” ๋งˆ์น˜ ์ดˆ์ ˆ์ „ ๋ชจ๋“œ๋กœ ์ž‘๋™ํ•˜๋Š” ์—๋„ˆ์ง€ ์ ˆ์•ฝํ˜• ์Šˆํผํžˆ์–ด๋กœ ๊ฐ™์•„์š”! ๐Ÿฆธโ€โ™‚๏ธ ์ž‘์€ ๋ฐฐํ„ฐ๋ฆฌ๋กœ๋„ ์˜ค๋žซ๋™์•ˆ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์–ด ์›จ์–ด๋Ÿฌ๋ธ” ๊ธฐ๊ธฐ, ์Šค๋งˆํŠธํ™ˆ ์„ผ์„œ, ์˜๋ฃŒ๊ธฐ๊ธฐ ๋“ฑ ๋‹ค์–‘ํ•œ IoT ๋””๋ฐ”์ด์Šค์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ต๋‹ˆ๋‹ค.

BLE์™€ ๊ธฐ์กด ๋ธ”๋ฃจํˆฌ์Šค ๋น„๊ต BLE ๊ธฐ์กด ๋ธ”๋ฃจํˆฌ์Šค ์ €์ „๋ ฅ ์†Œ๋น„ ๋†’์€ ์ „๋ ฅ ์†Œ๋น„

์œ„ ๊ทธ๋ฆผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, BLE๋Š” ๊ธฐ์กด ๋ธ”๋ฃจํˆฌ์Šค์— ๋น„ํ•ด ํ›จ์”ฌ ์ ์€ ์ „๋ ฅ์„ ์†Œ๋น„ํ•ด์š”. ์ด๋Š” ๋งˆ์น˜ ์ ˆ์•ฝ ๋ชจ๋“œ๋กœ ์‚ด์•„๊ฐ€๋Š” ์—์ฝ” ํ”„๋ Œ๋“ค๋ฆฌํ•œ ๊ธฐ์ˆ ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ฃ ! ๐ŸŒฑ

BLE์˜ ์ด๋Ÿฌํ•œ ํŠน์„ฑ์€ Java ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์ƒˆ๋กœ์šด ๊ธฐํšŒ์˜ ๋ฌธ์„ ์—ด์–ด์ค๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ์•ฑ, IoT ๋””๋ฐ”์ด์Šค ์ œ์–ด, ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์—์„œ BLE๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด์ฃ . ์ด์ œ ์šฐ๋ฆฌ๋Š” Java๋ฅผ ์‚ฌ์šฉํ•ด ์ด ๋†€๋ผ์šด ๊ธฐ์ˆ ์„ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ๋Š”์ง€ ์‚ดํŽด๋ณผ ๊ฑฐ์˜ˆ์š”!

๐Ÿ›  Java๋กœ BLE ๊ตฌํ˜„ํ•˜๊ธฐ: ์ฒซ ๊ฑธ์Œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์š”!

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Java๋ฅผ ์‚ฌ์šฉํ•ด BLE ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•ด๋ณผ ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์„ ์กฐ๋ฆฝํ•˜๋“ฏ์ด, ํ•˜๋‚˜์”ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์›Œ๋‚˜๊ฐ€ ๋ด์š”! ๐Ÿงฑ

1. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ • ๐Ÿ–ฅ๏ธ

๋จผ์ €, ์šฐ๋ฆฌ์˜ ์ฝ”๋”ฉ ๋ชจํ—˜์„ ์œ„ํ•œ ์ค€๋น„๋ฌผ์„ ์ฑ™๊ฒจ๋ณผ๊นŒ์š”?

  • Java Development Kit (JDK) 8 ์ด์ƒ
  • Android Studio (์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ ๊ฐœ๋ฐœ ์‹œ)
  • BlueZ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ ์‹œ)

๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์ œ๋Œ€๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์„ฑ๊ณต์ ์ธ BLE ๊ตฌํ˜„์˜ ์ฒซ ๊ฑธ์Œ์ด์—์š”! ๋งˆ์น˜ ์š”๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ฃผ๋ฐฉ์„ ๊นจ๋—์ด ์ •๋ฆฌํ•˜๊ณ  ์žฌ๋ฃŒ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ฃ . ๐Ÿง‘โ€๐Ÿณ

2. BLE ๊ถŒํ•œ ์„ค์ • ๐Ÿ”

BLE๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์•ฑ์— ํ•„์š”ํ•œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ด์•ผ ํ•ด์š”. Android ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํŒŒ์ผ์— ๋‹ค์Œ ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”:


<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  

์ด ๊ถŒํ•œ๋“ค์€ ๋งˆ์น˜ ๋น„๋ฐ€ ์š”์›์—๊ฒŒ ์ฃผ์–ด์ง€๋Š” ํŠน๋ณ„ ํ—ˆ๊ฐ€์ฆ ๊ฐ™์€ ๊ฑฐ์˜ˆ์š”. ์ด์ œ ์šฐ๋ฆฌ ์•ฑ์€ BLE ์„ธ๊ณ„์— ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋Š” VIP๊ฐ€ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ•ต๏ธโ€โ™‚๏ธ

3. BLE ์ง€์› ํ™•์ธ ๐Ÿ”

๋ชจ๋“  ๊ธฐ๊ธฐ๊ฐ€ BLE๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์—์š”. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ๊ฐ€ BLE๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•ด์•ผ ํ•ด์š”:


PackageManager packageManager = getPackageManager();
if (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    // BLE ์ง€์›!
} else {
    // BLE ๋ฏธ์ง€์› :(
}
  

์ด ๊ณผ์ •์€ ๋งˆ์น˜ ๋†€์ด๊ณต์›์— ์ž…์žฅํ•˜๊ธฐ ์ „์— ํ‚ค๋ฅผ ์žฌ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”. BLE๋ผ๋Š” ์‹ ๋‚˜๋Š” ๋†€์ด๊ธฐ๊ตฌ๋ฅผ ํƒˆ ์ˆ˜ ์žˆ๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•˜๋Š” ๊ฑฐ์ฃ ! ๐Ÿ“

4. BluetoothAdapter ์ดˆ๊ธฐํ™” ๐Ÿ”ง

BluetoothAdapter๋Š” BLE ํ†ต์‹ ์˜ ํ•ต์‹ฌ์ด์—์š”. ์ด๋ฅผ ํ†ตํ•ด BLE ์žฅ์น˜๋ฅผ ์Šค์บ”ํ•˜๊ณ  ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด์š”:


BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
  

BluetoothAdapter๋Š” ๋งˆ์น˜ ์šฐ๋ฆฌ์˜ ์Šค๋งˆํŠธํฐ์„ BLE ์„ธ๊ณ„์™€ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๋งˆ๋ฒ•์˜ ๋ฌธ ๊ฐ™์•„์š”. ์ด ๋ฌธ์„ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” ์ˆ˜๋งŽ์€ BLE ๋””๋ฐ”์ด์Šค๋“ค๊ณผ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ ! ๐Ÿšชโœจ

5. BLE ์Šค์บ” ์‹œ์ž‘ ๐Ÿ”Ž

์ด์ œ ์ฃผ๋ณ€์˜ BLE ์žฅ์น˜๋“ค์„ ์ฐพ์•„๋ณผ ์ฐจ๋ก€์˜ˆ์š”:


private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
        // ๋ฐœ๊ฒฌ๋œ ๋””๋ฐ”์ด์Šค ์ฒ˜๋ฆฌ
    }
};

bluetoothAdapter.startLeScan(leScanCallback);
  

์ด ๊ณผ์ •์€ ๋งˆ์น˜ ๋ณด๋ฌผ์ฐพ๊ธฐ ๊ฒŒ์ž„์„ ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”! ๐Ÿดโ€โ˜ ๏ธ ์šฐ๋ฆฌ์˜ ์•ฑ์ด ์ฃผ๋ณ€์„ ๋‘˜๋Ÿฌ๋ณด๋ฉฐ ์ˆจ์–ด์žˆ๋Š” BLE ๋””๋ฐ”์ด์Šค๋“ค์„ ์ฐพ์•„๋‚ด๋Š” ๊ฑฐ์ฃ . ๊ฐ ๋ฐœ๊ฒฌ๋œ ๋””๋ฐ”์ด์Šค๋Š” ์šฐ๋ฆฌ๊ฐ€ ์—ด์–ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ณด๋ฌผ์ƒ์ž ๊ฐ™์€ ์กด์žฌ์˜ˆ์š”!

์ฃผ์˜์‚ฌํ•ญ: BLE ์Šค์บ”์€ ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ ๋งŽ์ด ์†Œ๋ชจํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ผญ ํ•„์š”ํ•œ ์‹œ๊ฐ„ ๋™์•ˆ๋งŒ ์Šค์บ”์„ ์ง„ํ–‰ํ•˜๊ณ , ์™„๋ฃŒ ํ›„์—๋Š” ๋ฐ˜๋“œ์‹œ ์Šค์บ”์„ ์ค‘์ง€ํ•ด์•ผ ํ•ด์š”!

์ด๋ ‡๊ฒŒ ํ•ด์„œ ์šฐ๋ฆฌ๋Š” Java๋กœ BLE ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ฒซ ๊ฑธ์Œ์„ ๋‚ด๋”›์—ˆ์–ด์š”! ๋งˆ์น˜ ์ƒˆ๋กœ์šด ์–ธ์–ด๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์ฒ˜์Œ์—๋Š” ์–ด๋ ค์›Œ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์ตํ˜€๋‚˜๊ฐ€๋‹ค ๋ณด๋ฉด ์–ด๋Š์ƒˆ BLE ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๐Ÿ’ช

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๋ฐœ๊ฒฌ๋œ BLE ๋””๋ฐ”์ด์Šค์— ์—ฐ๊ฒฐํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ๊ณ„์†ํ•ด์„œ ์ด ํฅ๋ฏธ์ง„์ง„ํ•œ BLE ์—ฌํ–‰์„ ํ•จ๊ป˜ ๋– ๋‚˜๋ณผ๊นŒ์š”? ๐Ÿš€

๐Ÿ”— BLE ๋””๋ฐ”์ด์Šค ์—ฐ๊ฒฐ: ๋ฌด์„  ์„ธ๊ณ„์™€์˜ ์ฒซ ๋งŒ๋‚จ

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” ์ฃผ๋ณ€์˜ BLE ๋””๋ฐ”์ด์Šค๋“ค์„ ๋ฐœ๊ฒฌํ–ˆ์–ด์š”. ๋งˆ์น˜ ์ƒˆ๋กœ์šด ์นœ๊ตฌ๋“ค์„ ๋งŒ๋‚œ ๊ฒƒ ๊ฐ™์ฃ ? ๐Ÿค ์ด์ œ๋Š” ์ด ์นœ๊ตฌ๋“ค๊ณผ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆŒ ์ฐจ๋ก€์˜ˆ์š”! BLE ๋””๋ฐ”์ด์Šค์— ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด์š”.

1. ๋””๋ฐ”์ด์Šค ์—ฐ๊ฒฐํ•˜๊ธฐ ๐Ÿค–

์Šค์บ”์„ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•œ ๋””๋ฐ”์ด์Šค ์ค‘ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋””๋ฐ”์ด์Šค๋ฅผ ์„ ํƒํ•˜์—ฌ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•ด๋ด์š”:


private BluetoothGatt bluetoothGatt;

public void connectToDevice(BluetoothDevice device) {
    bluetoothGatt = device.connectGatt(this, false, gattCallback);
}

private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            // ์—ฐ๊ฒฐ ์„ฑ๊ณต!
            gatt.discoverServices();
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            // ์—ฐ๊ฒฐ ํ•ด์ œ :(
        }
    }
    
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            // ์„œ๋น„์Šค ๋ฐœ๊ฒฌ ์„ฑ๊ณต!
        }
    }
};
  

์ด ๊ณผ์ •์€ ๋งˆ์น˜ ์ „ํ™”๋ฅผ ๊ฑธ์–ด ์นœ๊ตฌ์™€ ์—ฐ๊ฒฐ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”. ๐Ÿ“ž ์—ฐ๊ฒฐ์ด ์„ฑ๊ณตํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ์ด์ œ BLE ๋””๋ฐ”์ด์Šค์™€ ๋Œ€ํ™”ํ•  ์ค€๋น„๊ฐ€ ๋œ ๊ฑฐ์˜ˆ์š”!

Tip: ์—ฐ๊ฒฐ ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•ญ์ƒ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์ฒดํฌํ•˜๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

2. ์„œ๋น„์Šค์™€ ํŠน์„ฑ ํƒ์ƒ‰ํ•˜๊ธฐ ๐Ÿ”

BLE ๋””๋ฐ”์ด์Šค๋Š” ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์™€ ํŠน์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”. ์ด๋Š” ๋งˆ์น˜ ๋””๋ฐ”์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ์š”. ์—ฐ๊ฒฐ๋œ ๋””๋ฐ”์ด์Šค์˜ ์„œ๋น„์Šค๋ฅผ ํƒ์ƒ‰ํ•ด๋ด์š”:


private void exploreServices(BluetoothGatt gatt) {
    for (BluetoothGattService service : gatt.getServices()) {
        String serviceUuid = service.getUuid().toString();
        // ์„œ๋น„์Šค UUID ์ฒ˜๋ฆฌ
        
        for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
            String characteristicUuid = characteristic.getUuid().toString();
            // ํŠน์„ฑ UUID ์ฒ˜๋ฆฌ
        }
    }
}
  

์ด ๊ณผ์ •์€ ๋งˆ์น˜ ์ƒˆ๋กœ ์‚ฐ ์Šค๋งˆํŠธ ๊ฐ€์ „์ œํ’ˆ์˜ ์„ค๋ช…์„œ๋ฅผ ์ฝ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ๐Ÿ“š ์–ด๋–ค ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋Š”์ง€, ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๊ฐ€๋Š” ๊ฑฐ์ฃ !

3. ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ ๐Ÿ“–

์ด์ œ ํŠน์ • ํŠน์„ฑ์˜ ๊ฐ’์„ ์ฝ์–ด๋ณผ๊นŒ์š”?


public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
    bluetoothGatt.readCharacteristic(characteristic);
}

// BluetoothGattCallback์— ๋‹ค์Œ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        byte[] data = characteristic.getValue();
        // ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
    }
}
  

์ด๋Š” ๋งˆ์น˜ ์นœ๊ตฌ์—๊ฒŒ "์ง€๊ธˆ ๋ญํ•ด?"๋ผ๊ณ  ๋ฌผ์–ด๋ณด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ์šฐ๋ฆฌ๋Š” ์งˆ๋ฌธ์„ ๋˜์ง€๊ณ , BLE ๋””๋ฐ”์ด์Šค๋Š” ๊ทธ์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์ฃผ๋Š” ๊ฑฐ์ฃ ! ๐Ÿ’ฌ

4. ๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ โœ๏ธ

๋ฐ˜๋Œ€๋กœ, ์šฐ๋ฆฌ๊ฐ€ BLE ๋””๋ฐ”์ด์Šค์— ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ์–ด์š”:


public void writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] data) {
    characteristic.setValue(data);
    bluetoothGatt.writeCharacteristic(characteristic);
}

// BluetoothGattCallback์— ๋‹ค์Œ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // ์“ฐ๊ธฐ ์„ฑ๊ณต!
    }
}
  

์ด๊ฒƒ์€ ๋งˆ์น˜ ์นœ๊ตฌ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. "์˜ค๋Š˜ ์ €๋…์— ์˜ํ™” ๋ณผ๋ž˜?"๋ผ๊ณ  ๋ฌผ์–ด๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์šฐ๋ฆฌ๋Š” BLE ๋””๋ฐ”์ด์Šค์— ๋ช…๋ น์ด๋‚˜ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿ“จ

5. ์•Œ๋ฆผ ์„ค์ •ํ•˜๊ธฐ ๐Ÿ””

์–ด๋–ค ํŠน์„ฑ์€ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์šฐ๋ฆฌ์—๊ฒŒ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ์œ„ํ•ด ์•Œ๋ฆผ์„ ์„ค์ •ํ•ด๋ณผ๊นŒ์š”?


public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
    bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
        UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    bluetoothGatt.writeDescriptor(descriptor);
}

// BluetoothGattCallback์— ๋‹ค์Œ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    byte[] data = characteristic.getValue();
    // ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
}
  

์ด๊ฒƒ์€ ๋งˆ์น˜ ์นœ๊ตฌ์™€ ์•ฝ์†์„ ์ •ํ•ด๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. "๋„ค๊ฐ€ ์ง‘์— ๋„์ฐฉํ•˜๋ฉด ๊ผญ ๋‚˜ํ•œํ…Œ ์—ฐ๋ฝํ•ด!"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, BLE ๋””๋ฐ”์ด์Šค์—๊ฒŒ "์ด ๊ฐ’์ด ๋ณ€ํ•˜๋ฉด ๊ผญ ์•Œ๋ ค์ค˜!"๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ๐Ÿ ๐Ÿ“ฑ

์ฃผ์˜์‚ฌํ•ญ: ์•Œ๋ฆผ์„ ๋„ˆ๋ฌด ๋งŽ์ด ์„ค์ •ํ•˜๋ฉด ๋ฐฐํ„ฐ๋ฆฌ ์†Œ๋ชจ๊ฐ€ ์ปค์งˆ ์ˆ˜ ์žˆ์–ด์š”. ๊ผญ ํ•„์š”ํ•œ ํŠน์„ฑ์— ๋Œ€ํ•ด์„œ๋งŒ ์•Œ๋ฆผ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ด๋ ‡๊ฒŒ ํ•ด์„œ ์šฐ๋ฆฌ๋Š” BLE ๋””๋ฐ”์ด์Šค์™€ ์„ฑ๊ณต์ ์œผ๋กœ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ„๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์–ด์š”! ๋งˆ์น˜ ์ƒˆ๋กœ์šด ์™ธ๊ตญ์–ด๋ฅผ ๋ฐฐ์›Œ ํ˜„์ง€์ธ๊ณผ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์šฐ๋ฆฌ๋Š” ์ด์ œ BLE๋ผ๋Š” ์–ธ์–ด๋กœ ๋””๋ฐ”์ด์Šค๋“ค๊ณผ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค. ๐ŸŒ๐Ÿ—ฃ๏ธ

์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด ์žฌ๋Šฅ๋„ท์—์„œ BLE๋ฅผ ์ด์šฉํ•œ ์Šค๋งˆํŠธํ™ˆ ์ œ์–ด ์•ฑ์„ ๊ฐœ๋ฐœํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ˆ˜์ฃผ๋ฐ›์„ ์ˆ˜๋„ ์žˆ๊ฒ ์ฃ ? ์—ฌ๋Ÿฌ๋ถ„์˜ BLE ์‹ค๋ ฅ์ด ๋†’์•„์งˆ์ˆ˜๋ก, ๋” ๋งŽ์€ ๊ธฐํšŒ๊ฐ€ ์—ด๋ฆด ๊ฑฐ์˜ˆ์š”!

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” BLE ํ†ต์‹ ์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ๋“ค์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ๊ณ„์†ํ•ด์„œ BLE ๋งˆ์Šคํ„ฐ์˜ ๊ธธ์„ ํ•จ๊ป˜ ๊ฑธ์–ด๊ฐ€๋ณผ๊นŒ์š”? ๐Ÿšถโ€โ™‚๏ธ๐Ÿšถโ€โ™€๏ธ

๐Ÿ—๏ธ BLE ํ”„๋กœ์ ํŠธ ๊ตฌํ˜„: ์‹ค์ „ ์‘์šฉ๊ณผ ์ฃผ์˜์‚ฌํ•ญ

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” BLE์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์–ด์š”! ๐ŸŽ“ ํ•˜์ง€๋งŒ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— BLE๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋˜ ๋‹ค๋ฅธ ์ฐจ์›์˜ ๋„์ „์ด ๋  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ์š”๋ฆฌ๋ฅผ ๋ฐฐ์šด ํ›„ ์‹ค์ œ๋กœ ๋ ˆ์Šคํ† ๋ž‘์„ ์šด์˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ฃ . ์ด๋ฒˆ ์„น์…˜์—์„œ๋Š” BLE๋ฅผ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•  ๋•Œ ์•Œ์•„์•ผ ํ•  ์ค‘์š”ํ•œ ์ ๋“ค๊ณผ ๋ช‡ ๊ฐ€์ง€ ์‹ค์šฉ์ ์ธ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณผ ๊ฑฐ์˜ˆ์š”.

1. BLE ์ƒํƒœ ๊ด€๋ฆฌ ๐Ÿ”„

์‹ค์ œ ์•ฑ์—์„œ๋Š” BLE ์—ฐ๊ฒฐ ์ƒํƒœ๋ฅผ ์ง€์†์ ์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•ด์š”. ์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ์„ ๋•Œ ์ž๋™์œผ๋กœ ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ์ฃผ๋Š” ๋“ฑ์˜ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•ด์š”.


public class BleManager {
    private BluetoothGatt bluetoothGatt;
    private boolean isConnected = false;

    public void connect(BluetoothDevice device) {
        bluetoothGatt = device.connectGatt(context, false, gattCallback);
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                isConnected = true;
                // ์—ฐ๊ฒฐ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                isConnected = false;
                // ์—ฐ๊ฒฐ ํ•ด์ œ ์ฒ˜๋ฆฌ
                reconnect();
            }
        }
    };

    private void reconnect() {
        if (bluetoothGatt != null) {
            bluetoothGatt.connect();
        }
    }
}
  

์ด ์ฝ”๋“œ๋Š” ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์นœ๊ตฌ์™€ ํ†ตํ™” ์ค‘ ์ „ํ™”๊ฐ€ ๋Š์–ด์กŒ์„ ๋•Œ, ์ž๋™์œผ๋กœ ๋‹ค์‹œ ์ „ํ™”๋ฅผ ๊ฑฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ์—ฐ๊ฒฐ์ด ๋Š์–ด์ ธ๋„ ๋‹นํ™ฉํ•˜์ง€ ์•Š๊ณ  ์ฐจ๋ถ„ํžˆ ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๋Š” ๊ฑฐ์ฃ ! ๐Ÿ˜Œ๐Ÿ“ž

2. ๋ฐฐํ„ฐ๋ฆฌ ์ตœ์ ํ™” ๐Ÿ”‹

BLE๋Š” ์ €์ „๋ ฅ ๊ธฐ์ˆ ์ด์ง€๋งŒ, ๋ถ€์ฃผ์˜ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ์ „ํžˆ ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ ๋งŽ์ด ์†Œ๋ชจํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐฐํ„ฐ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”:

  • ํ•„์š”ํ•  ๋•Œ๋งŒ ์Šค์บ”ํ•˜๊ธฐ
  • ์—ฐ๊ฒฐ ๊ฐ„๊ฒฉ(Connection Interval) ์กฐ์ ˆํ•˜๊ธฐ
  • ๋ถˆํ•„์š”ํ•œ ์•Œ๋ฆผ ์ค„์ด๊ธฐ

private void startLeScan() {
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            bluetoothAdapter.stopLeScan(leScanCallback);
        }
    }, SCAN_PERIOD);
    bluetoothAdapter.startLeScan(leScanCallback);
}
  

์ด ์ฝ”๋“œ๋Š” ๋งˆ์น˜ ์ ˆ์ „ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ํ•„์š”ํ•œ ์‹œ๊ฐ„ ๋™์•ˆ๋งŒ ์—ด์‹ฌํžˆ ์ผํ•˜๊ณ , ๊ทธ ์™ธ์—๋Š” ์—๋„ˆ์ง€๋ฅผ ์•„๋ผ๋Š” ๊ฑฐ์ฃ ! ๐ŸŒฑ๐Ÿ’ก

3. ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ ๐Ÿ”’

BLE ํ†ต์‹ ๋„ ๋ณด์•ˆ์— ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”.


private void encryptAndSendData(byte[] data) {
    // ์•”ํ˜ธํ™” ๋กœ์ง
    byte[] encryptedData = encrypt(data);
    writeCharacteristic(characteristic, encryptedData);
}

private byte[] encrypt(byte[] data) {
    // ์‹ค์ œ ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„
    // ์˜ˆ: AES ์•”ํ˜ธํ™” ์‚ฌ์šฉ
    return encryptedData;
}
  

์ด๊ฒƒ์€ ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ๋น„๋ฐ€ ํŽธ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ ์•”ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ๋ˆ„๊ตฐ๊ฐ€ ์ค‘๊ฐ„์— ํŽธ์ง€๋ฅผ ๊ฐ€๋กœ์ฑ„๋”๋ผ๋„ ๋‚ด์šฉ์„ ์•Œ์•„๋ณผ ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฑฐ์ฃ ! ๐Ÿ•ต๏ธโ€โ™€๏ธโœ‰๏ธ

4. ์—๋Ÿฌ ์ฒ˜๋ฆฌ โš ๏ธ

BLE ํ†ต์‹  ์ค‘์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด์— ๋Œ€๋น„ํ•œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์ˆ˜์ ์ด์—์š”.


private void handleBleError(int errorCode) {
    switch (errorCode) {
        case BleErrorCodes.CONNECTION_TIMEOUT:
            // ์—ฐ๊ฒฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์ฒ˜๋ฆฌ
            break;
        case BleErrorCodes.GATT_ERROR:
            // GATT ์—๋Ÿฌ ์ฒ˜๋ฆฌ
            break;
        // ๊ธฐํƒ€ ์—๋Ÿฌ ์ผ€์ด์Šค
        default:
            // ๊ธฐ๋ณธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ
    }
}
  

์ด๋Š” ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์—ฌํ–‰์„ ๊ฐˆ ๋•Œ ๋น„์ƒ ์ƒํ™ฉ์— ๋Œ€๋น„ํ•ด ์‘๊ธ‰ ํ‚คํŠธ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋”๋ผ๋„ ๋‹นํ™ฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ ! ๐Ÿงณ๐Ÿš‘

5. ์‹ค์ œ ํ”„๋กœ์ ํŠธ ์˜ˆ์‹œ: ์Šค๋งˆํŠธ ์ฒด์ค‘๊ณ„ ์•ฑ ๐Ÿ’ชโš–๏ธ

์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ข…ํ•ฉํ•ด์„œ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณผ๊นŒ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด, BLE๋ฅผ ์ด์šฉํ•œ ์Šค๋งˆํŠธ ์ฒด์ค‘๊ณ„ ์•ฑ์„ ๋งŒ๋“ค์–ด๋ณธ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด์š”.


public class SmartScaleManager {
    private BluetoothGatt bluetoothGatt;
    private BluetoothGattCharacteristic weightCharacteristic;

    public void connectToScale(BluetoothDevice device) {
        bluetoothGatt = device.connectGatt(context, false, gattCallback);
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                // ์—ฐ๊ฒฐ ํ•ด์ œ ์ฒ˜๋ฆฌ
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                weightCharacteristic = findWeightCharacteristic(gatt);
                if (weightCharacteristic != null) {
                    enableWeightNotification(weightCharacteristic);
                }
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (characteristic.getUuid().equals(WEIGHT_CHARACTERISTIC_UUID)) {
                float weight = parseWeight(characteristic.getValue());
                updateWeightUI(weight);
            }
        }
    };

    private void enableWeightNotification(BluetoothGattCharacteristic characteristic) {
        bluetoothGatt.setCharacteristicNotification(characteristic, true);
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        bluetoothGatt.writeDescriptor(descriptor);
    }

    private float parseWeight(byte[] data) {
        // ์ฒด์ค‘๊ณ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์ œ ์ฒด์ค‘๊ฐ’์œผ๋กœ ๋ณ€ํ™˜
        // ์˜ˆ: ๋ฆฌํ‹€ ์—”๋””์•ˆ 2๋ฐ”์ดํŠธ ์ •์ˆ˜๋ฅผ float๋กœ ๋ณ€ํ™˜
        return ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getShort() / 10f;
    }

    private void updateWeightUI(float weight) {
        // UI ์—…๋ฐ์ดํŠธ ๋กœ์ง
        // ์˜ˆ: runOnUiThread(() -> weightTextView.setText(String.format("%.1f kg", weight)));
    }
}
  

์ด ์ฝ”๋“œ๋Š” ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์ฒด์ค‘๊ณ„์™€ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. "์•ˆ๋…•, ์ฒด์ค‘๊ณ„์•ผ! ๋‚ด ์ฒด์ค‘์ด ์–ผ๋งˆ์ธ์ง€ ์•Œ๋ ค์ค„๋ž˜?"๋ผ๊ณ  ๋ฌผ์–ด๋ณด๋ฉด, ์ฒด์ค‘๊ณ„๋Š” "๋„ค, ๋‹น์‹ ์˜ ์ฒด์ค‘์€ 65.5kg์ž…๋‹ˆ๋‹ค!"๋ผ๊ณ  ๋Œ€๋‹ตํ•ด์ฃผ๋Š” ๊ฑฐ์ฃ . ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ ์•ฑ์€ ์ด ์ •๋ณด๋ฅผ ๋ฐ›์•„์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ฑฐ์˜ˆ์š”! ๐Ÿ“Š๐Ÿ‹๏ธโ€โ™€๏ธ

Pro Tip: ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ๊ณผ ์‹ ๋ขฐ์„ฑ์„ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋ฒˆ ์ธก์ •๊ฐ’์„ ๋ฐ›์•„ ํ‰๊ท ์„ ๋‚ด๊ฑฐ๋‚˜, ๊ฐ‘์ž๊ธฐ ํฐ ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์žฌํ™•์ธํ•˜๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

6. ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„  ๐ŸŽจ

BLE ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•  ๋•Œ, ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ•ญ์ƒ ์ตœ์šฐ์„ ์œผ๋กœ ๊ณ ๋ คํ•ด์•ผ ํ•ด์š”. ์—ฐ๊ฒฐ์ด ์ง€์—ฐ๋˜๊ฑฐ๋‚˜ ์‹คํŒจํ•  ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”.


private void showConnectionStatus(int status) {
    switch (status) {
        case STATUS_CONNECTING:
            showProgressDialog("์ฒด์ค‘๊ณ„์— ์—ฐ๊ฒฐ ์ค‘์ž…๋‹ˆ๋‹ค...");
            break;
        case STATUS_CONNECTED:
            dismissProgressDialog();
            showToast("์ฒด์ค‘๊ณ„์— ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
            break;
        case STATUS_DISCONNECTED:
            showAlertDialog("์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?");
            break;
    }
}
  

์ด๋Š” ๋งˆ์น˜ ์นœ์ ˆํ•œ ๋น„์„œ๊ฐ€ ์šฐ๋ฆฌ์—๊ฒŒ ์ƒํ™ฉ์„ ๊ณ„์† ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. "์ง€๊ธˆ ์ฒด์ค‘๊ณ„๋ฅผ ์ฐพ๊ณ  ์žˆ์–ด์š”!", "์ฒด์ค‘๊ณ„๋ฅผ ์ฐพ์•˜์–ด์š”!", "์•—, ์ฒด์ค‘๊ณ„์™€์˜ ์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ๋„ค์š”. ๋‹ค์‹œ ์—ฐ๊ฒฐํ•ด ๋“œ๋ฆด๊นŒ์š”?" ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ณ„์† ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ฉด, ์‚ฌ์šฉ์ž๋Š” ์•ฑ์„ ๋” ํŽธ์•ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ˜Š๐Ÿ‘

๋งˆ๋ฌด๋ฆฌ: BLE ๋งˆ์Šคํ„ฐ๋กœ ๊ฐ€๋Š” ๊ธธ ๐Ÿ†

์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ์—ฌ๋Ÿฌ๋ถ„์€ ์ด์ œ BLE ํ†ต์‹ ์˜ ๊ธฐ๋ณธ๋ถ€ํ„ฐ ์‹ค์ œ ํ”„๋กœ์ ํŠธ ์ ์šฉ๊นŒ์ง€ ์ „๋ฐ˜์ ์ธ ๋‚ด์šฉ์„ ๋ฐฐ์› ์–ด์š”. ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ BLE๋ฅผ ์ด์šฉํ•ด ๋‹ค์–‘ํ•œ IoT ๋””๋ฐ”์ด์Šค์™€ ํ†ต์‹ ํ•˜๋Š” ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ๊ฐ–์ถ”๊ฒŒ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค!

์ด๋Ÿฐ ๊ธฐ์ˆ ๋ ฅ์€ ์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ํฐ ๊ฐ€์น˜๋ฅผ ๋ฐœํœ˜ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์Šค๋งˆํŠธํ™ˆ ์ œ์–ด ์•ฑ, ๊ฑด๊ฐ• ๋ชจ๋‹ˆํ„ฐ๋ง ์•ฑ, ์›จ์–ด๋Ÿฌ๋ธ” ๋””๋ฐ”์ด์Šค ์—ฐ๋™ ์•ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์˜ BLE ์ง€์‹์ด ๋น›์„ ๋ฐœํ•  ๊ฑฐ์˜ˆ์š”!

๊ธฐ์–ตํ•˜์„ธ์š”, ๊ธฐ์ˆ ์˜ ์„ธ๊ณ„๋Š” ๊ณ„์†ํ•ด์„œ ๋ฐœ์ „ํ•˜๊ณ  ์žˆ์–ด์š”. BLE๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ฃ . ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๊ณผ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ํ•™์Šตํ•˜๊ณ , ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๋ฉด์„œ ๊ฒฝํ—˜์„ ์Œ“์•„๊ฐ€์„ธ์š”. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‹ค ๋ณด๋ฉด ์–ด๋Š์ƒˆ ์—ฌ๋Ÿฌ๋ถ„์€ BLE ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿš€๐ŸŒŸ

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ ๋ฉ‹์ง„ BLE ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•ด๋ณผ ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‚˜์š”? ์„ธ์ƒ์„ ๋” ์Šค๋งˆํŠธํ•˜๊ณ  ์—ฐ๊ฒฐ๋œ ๊ณณ์œผ๋กœ ๋งŒ๋“œ๋Š” ์—ฌ์ •์— ์—ฌ๋Ÿฌ๋ถ„์„ ์ดˆ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜„