From 88a89bcbd38daf8b993017967392beb7c35dcc8d Mon Sep 17 00:00:00 2001 From: Prathiyuman Date: Tue, 16 Dec 2025 15:10:39 +0530 Subject: [PATCH 1/2] Latest Code Updated --- android/src/main/AndroidManifest.xml | 12 ++ .../com/weightscalebridge/MainApplication.kt | 6 + .../WeightScaleBridgeModule.kt | 200 ++++++++++++++++-- .../WeightScaleBridgePackage.kt | 35 +-- 4 files changed, 212 insertions(+), 41 deletions(-) create mode 100644 android/src/main/java/com/weightscalebridge/MainApplication.kt diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index a2f47b6..6cac27a 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,2 +1,14 @@ + + + + + + + + + + + + diff --git a/android/src/main/java/com/weightscalebridge/MainApplication.kt b/android/src/main/java/com/weightscalebridge/MainApplication.kt new file mode 100644 index 0000000..f4f3a38 --- /dev/null +++ b/android/src/main/java/com/weightscalebridge/MainApplication.kt @@ -0,0 +1,6 @@ +// Inside the getPackages() method +override fun getPackages(): List { + val packages = PackageList(this).packages + packages.add(WeightScalePackage()) // Add this line + return packages +} \ No newline at end of file diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt index 9285a00..8fcb905 100644 --- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt +++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt @@ -2,22 +2,192 @@ package com.weightscalebridge import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.annotations.ReactModule +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothManager +import android.bluetooth.le.* +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.os.CountDownTimer +import androidx.core.content.ContextCompat +import com.facebook.react.bridge.* +import com.facebook.react.modules.core.DeviceEventManagerModule +import kotlin.math.abs -@ReactModule(name = WeightScaleBridgeModule.NAME) -class WeightScaleBridgeModule(reactContext: ReactApplicationContext) : - NativeWeightScaleBridgeSpec(reactContext) { +class WeightScaleModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { - override fun getName(): String { - return NAME - } + override fun getName(): String = "WeightScale" - // Example method - // See https://reactnative.dev/docs/native-modules-android - override fun multiply(a: Double, b: Double): Double { - return a * b - } + private var bluetoothAdapter: BluetoothAdapter? = null + private var scanner: BluetoothLeScanner? = null + private var isScanning = false + private var timer: CountDownTimer? = null - companion object { - const val NAME = "WeightScaleBridge" - } -} + private var candidateKg: Double = Double.NaN + private var stableSince: Long = 0L + + private val STABLE_WINDOW_MS = 4000L + private val WEIGHT_TOL = 0.1 + private val MIN_VALID_KG = 5.0 + private val MAX_VALID_KG = 250.0 + private val MEASURE_WINDOW_MS = 20000L // 20 seconds timeout + private val TARGET_MAC = "34:5C:F3:40:2C:D8" // Your scale MAC + + private fun sendEvent(eventName: String, params: WritableMap) { + reactApplicationContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(eventName, params) + } + + @ReactMethod + fun startMeasuring() { + if (isScanning) return + + val bluetoothManager = reactApplicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + bluetoothAdapter = bluetoothManager.adapter + + if (bluetoothAdapter == null || !bluetoothAdapter!!.isEnabled) { + val params = Arguments.createMap().apply { + putString("message", "Bluetooth is not enabled. Please turn it on in settings.") + } + sendEvent("onScaleError", params) + return + } + + if (!hasRequiredPermissions()) { + val params = Arguments.createMap().apply { + putString("message", "Required permissions not granted.") + } + sendEvent("onScaleError", params) + return + } + + scanner = bluetoothAdapter!!.bluetoothLeScanner + + // Reset stability tracking + candidateKg = Double.NaN + stableSince = 0L + isScanning = true + + // Send initial status + sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "scanning") }) + + // Use filter for your specific scale MAC (more efficient) + val scanFilter = ScanFilter.Builder() + .setDeviceAddress(TARGET_MAC) + .build() + val scanFilters = listOf(scanFilter) + + val scanSettings = ScanSettings.Builder() + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) + .build() + + try { + scanner!!.startScan(scanFilters, scanSettings, scanCallback) + } catch (e: Exception) { + val params = Arguments.createMap().apply { putString("message", e.message ?: "Scan start failed") } + sendEvent("onScaleError", params) + stopMeasuring() + return + } + + // 20-second timeout + timer = object : CountDownTimer(MEASURE_WINDOW_MS, 1000) { + override fun onTick(millisUntilFinished: Long) { + // Optional: send remaining seconds if needed + } + + override fun onFinish() { + stopMeasuring() + sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "timeout") }) + } + }.start() + } + + @ReactMethod + fun stopMeasuring() { + if (!isScanning) return + + try { + scanner?.stopScan(scanCallback) + } catch (e: Exception) { + // Ignore + } + timer?.cancel() + timer = null + isScanning = false + + sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "stopped") }) + } + + private val scanCallback = object : ScanCallback() { + override fun onScanResult(callbackType: Int, result: ScanResult?) { + result ?: return + val scanRecord = result.scanRecord ?: return + val manufacturerData = scanRecord.manufacturerSpecificData + + if (manufacturerData != null && manufacturerData.size() > 0) { + for (i in 0 until manufacturerData.size()) { + val data = manufacturerData.valueAt(i) ?: continue + if (data.size >= 2) { + val tenths = ((data[0].toInt() and 0xFF) shl 8) or (data[1].toInt() and 0xFF) + val kg = tenths / 10.0 + if (kg in MIN_VALID_KG..MAX_VALID_KG) { + processWeight(kg) + } + } + } + } + } + + override fun onScanFailed(errorCode: Int) { + val params = Arguments.createMap().apply { + putString("message", "Scan failed with code: $errorCode") + } + sendEvent("onScaleError", params) + stopMeasuring() + } + } + + private fun processWeight(kg: Double) { + // Send live weight update + val liveParams = Arguments.createMap().apply { putDouble("weight", kg) } + sendEvent("onLiveWeight", liveParams) + + // Update status to measuring + sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "measuring") }) + + val now = System.currentTimeMillis() + + // Stability detection + if (candidateKg.isNaN() || abs(kg - candidateKg) > WEIGHT_TOL) { + candidateKg = kg + stableSince = now + } else if (now - stableSince >= STABLE_WINDOW_MS) { + // Stable weight achieved + val stableParams = Arguments.createMap().apply { putDouble("weight", candidateKg) } + sendEvent("onStableWeight", stableParams) + sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "stable") }) + stopMeasuring() + } + } + + private fun hasRequiredPermissions(): Boolean { + val perms = mutableListOf() + perms.add(android.Manifest.permission.ACCESS_FINE_LOCATION) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + perms.add(android.Manifest.permission.BLUETOOTH_SCAN) + perms.add(android.Manifest.permission.BLUETOOTH_CONNECT) + } + + return perms.all { + ContextCompat.checkSelfPermission(reactApplicationContext, it) == PackageManager.PERMISSION_GRANTED + } + } + + override fun onCatalystInstanceDestroy() { + super.onCatalystInstanceDestroy() + stopMeasuring() // Cleanup when RN instance destroys + } +} \ No newline at end of file diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt index b5a984a..364be9b 100644 --- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt +++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt @@ -1,33 +1,16 @@ -package com.weightscalebridge +package com.cureselect.weightpluse -import com.facebook.react.BaseReactPackage +import com.facebook.react.ReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.module.model.ReactModuleInfo -import com.facebook.react.module.model.ReactModuleInfoProvider -import java.util.HashMap +import com.facebook.react.uimanager.ViewManager -class WeightScaleBridgePackage : BaseReactPackage() { - override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { - return if (name == WeightScaleBridgeModule.NAME) { - WeightScaleBridgeModule(reactContext) - } else { - null +class WeightScalePackage : ReactPackage { + override fun createNativeModules(reactContext: ReactApplicationContext): List { + return listOf(WeightScaleModule(reactContext)) } - } - override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { - return ReactModuleInfoProvider { - val moduleInfos: MutableMap = HashMap() - moduleInfos[WeightScaleBridgeModule.NAME] = ReactModuleInfo( - WeightScaleBridgeModule.NAME, - WeightScaleBridgeModule.NAME, - false, // canOverrideExistingModule - false, // needsEagerInit - false, // isCxxModule - true // isTurboModule - ) - moduleInfos + override fun createViewManagers(reactContext: ReactApplicationContext): List> { + return emptyList() } - } -} +} \ No newline at end of file -- 2.49.1 From c14d41b3451dcd19309f7c6f6d3659384506547c Mon Sep 17 00:00:00 2001 From: Prathiyuman Date: Tue, 16 Dec 2025 16:39:05 +0530 Subject: [PATCH 2/2] refactor: update WeightScaleBridge integration and error handling --- .../com/weightscalebridge/MainApplication.kt | 6 - .../WeightScaleBridgeModule.kt | 332 +++++++++--------- .../WeightScaleBridgePackage.kt | 21 +- src/index.tsx | 27 +- 4 files changed, 202 insertions(+), 184 deletions(-) delete mode 100644 android/src/main/java/com/weightscalebridge/MainApplication.kt diff --git a/android/src/main/java/com/weightscalebridge/MainApplication.kt b/android/src/main/java/com/weightscalebridge/MainApplication.kt deleted file mode 100644 index f4f3a38..0000000 --- a/android/src/main/java/com/weightscalebridge/MainApplication.kt +++ /dev/null @@ -1,6 +0,0 @@ -// Inside the getPackages() method -override fun getPackages(): List { - val packages = PackageList(this).packages - packages.add(WeightScalePackage()) // Add this line - return packages -} \ No newline at end of file diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt index 8fcb905..f3a6dc6 100644 --- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt +++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt @@ -1,10 +1,11 @@ package com.weightscalebridge -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.module.annotations.ReactModule +import android.Manifest import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothManager -import android.bluetooth.le.* +import android.bluetooth.le.BluetoothLeScanner +import android.bluetooth.le.ScanCallback +import android.bluetooth.le.ScanResult import android.content.Context import android.content.pm.PackageManager import android.os.Build @@ -12,182 +13,181 @@ import android.os.CountDownTimer import androidx.core.content.ContextCompat import com.facebook.react.bridge.* import com.facebook.react.modules.core.DeviceEventManagerModule -import kotlin.math.abs +import kotlin.math.pow +import kotlin.math.round -class WeightScaleModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { +class WeightScaleModule( + private val reactContext: ReactApplicationContext +) : ReactContextBaseJavaModule(reactContext) { - override fun getName(): String = "WeightScale" + private var bluetoothAdapter: BluetoothAdapter? = null + private var scanner: BluetoothLeScanner? = null + private var isScanning = false + private var timer: CountDownTimer? = null + private var currentWeight = 0.0 - private var bluetoothAdapter: BluetoothAdapter? = null - private var scanner: BluetoothLeScanner? = null - private var isScanning = false - private var timer: CountDownTimer? = null + override fun getName(): String = "WeightScaleBridge" - private var candidateKg: Double = Double.NaN - private var stableSince: Long = 0L + init { + val manager = + reactContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + bluetoothAdapter = manager.adapter + scanner = bluetoothAdapter?.bluetoothLeScanner + } - private val STABLE_WINDOW_MS = 4000L - private val WEIGHT_TOL = 0.1 - private val MIN_VALID_KG = 5.0 - private val MAX_VALID_KG = 250.0 - private val MEASURE_WINDOW_MS = 20000L // 20 seconds timeout - private val TARGET_MAC = "34:5C:F3:40:2C:D8" // Your scale MAC + private fun sendEvent(name: String, params: WritableMap?) { + reactContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(name, params) + } - private fun sendEvent(eventName: String, params: WritableMap) { - reactApplicationContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - .emit(eventName, params) + @ReactMethod + fun isBluetoothEnabled(promise: Promise) { + try { + val enabled = bluetoothAdapter?.isEnabled ?: false + promise.resolve(enabled) + } catch (e: Exception) { + promise.reject("BLUETOOTH_CHECK_ERROR", e.message, e) + } + } + + @ReactMethod + fun startScanning(promise: Promise) { + try { + if (!hasPermissions()) { + promise.reject("PERMISSION", "Bluetooth permissions not granted") + return + } + + if (bluetoothAdapter?.isEnabled != true) { + promise.reject("BLUETOOTH", "Bluetooth disabled") + return + } + + if (isScanning) { + promise.resolve(true) + return + } + + isScanning = true + currentWeight = 0.0 + + scanner?.startScan(scanCallback) + + sendEvent( + "onWeightScaleStatus", + Arguments.createMap().apply { putString("status", "scanning") } + ) + + timer = object : CountDownTimer(20000, 1000) { + override fun onTick(ms: Long) {} + override fun onFinish() { + stopScanning(null) + } + }.start() + + promise.resolve(true) + } catch (e: Exception) { + promise.reject("SCAN_ERROR", e.message, e) + } + } + + @ReactMethod + fun stopScanning(promise: Promise?) { + try { + scanner?.stopScan(scanCallback) + } catch (_: Exception) {} + + timer?.cancel() + isScanning = false + + sendEvent( + "onWeightScaleStatus", + Arguments.createMap().apply { putString("status", "stopped") } + ) + + promise?.resolve(true) + } + + private val scanCallback = object : ScanCallback() { + override fun onScanResult(type: Int, result: ScanResult) { + val record = result.scanRecord ?: return + val data = record.manufacturerSpecificData + + if (data.size() == 0) return + + val raw = data.valueAt(0) + if (raw.size < 2) return + + val weight = (((raw[0].toInt() and 0xff) shl 8) or + (raw[1].toInt() and 0xff)) / 10.0 + + currentWeight = weight + + sendEvent( + "onWeightData", + Arguments.createMap().apply { + putDouble("weight", weight) + putBoolean("isStable", true) + } + ) + + sendEvent( + "onWeightScaleStatus", + Arguments.createMap().apply { + putString("status", "complete") + putString("message", "$weight kg") + } + ) + + stopScanning(null) } - @ReactMethod - fun startMeasuring() { - if (isScanning) return - - val bluetoothManager = reactApplicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - bluetoothAdapter = bluetoothManager.adapter - - if (bluetoothAdapter == null || !bluetoothAdapter!!.isEnabled) { - val params = Arguments.createMap().apply { - putString("message", "Bluetooth is not enabled. Please turn it on in settings.") - } - sendEvent("onScaleError", params) - return + override fun onScanFailed(errorCode: Int) { + super.onScanFailed(errorCode) + + sendEvent( + "onWeightScaleStatus", + Arguments.createMap().apply { + putString("status", "error") + putString("message", "Scan failed with code: $errorCode") } - - if (!hasRequiredPermissions()) { - val params = Arguments.createMap().apply { - putString("message", "Required permissions not granted.") - } - sendEvent("onScaleError", params) - return - } - - scanner = bluetoothAdapter!!.bluetoothLeScanner - - // Reset stability tracking - candidateKg = Double.NaN - stableSince = 0L - isScanning = true - - // Send initial status - sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "scanning") }) - - // Use filter for your specific scale MAC (more efficient) - val scanFilter = ScanFilter.Builder() - .setDeviceAddress(TARGET_MAC) - .build() - val scanFilters = listOf(scanFilter) - - val scanSettings = ScanSettings.Builder() - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .build() - - try { - scanner!!.startScan(scanFilters, scanSettings, scanCallback) - } catch (e: Exception) { - val params = Arguments.createMap().apply { putString("message", e.message ?: "Scan start failed") } - sendEvent("onScaleError", params) - stopMeasuring() - return - } - - // 20-second timeout - timer = object : CountDownTimer(MEASURE_WINDOW_MS, 1000) { - override fun onTick(millisUntilFinished: Long) { - // Optional: send remaining seconds if needed - } - - override fun onFinish() { - stopMeasuring() - sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "timeout") }) - } - }.start() + ) + + isScanning = false } + } - @ReactMethod - fun stopMeasuring() { - if (!isScanning) return - - try { - scanner?.stopScan(scanCallback) - } catch (e: Exception) { - // Ignore - } - timer?.cancel() - timer = null - isScanning = false - - sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "stopped") }) + @ReactMethod + fun calculateBMI(weight: Double, heightCm: Double, promise: Promise) { + try { + if (heightCm <= 0) { + promise.reject("INVALID_HEIGHT", "Height must be greater than 0") + return + } + + val bmi = weight / (heightCm / 100).pow(2) + promise.resolve(round(bmi * 10) / 10) + } catch (e: Exception) { + promise.reject("BMI_ERROR", e.message, e) } + } - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result ?: return - val scanRecord = result.scanRecord ?: return - val manufacturerData = scanRecord.manufacturerSpecificData + private fun hasPermissions(): Boolean { + val perms = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + arrayOf( + Manifest.permission.BLUETOOTH_SCAN, + Manifest.permission.BLUETOOTH_CONNECT + ) + else + arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION + ) - if (manufacturerData != null && manufacturerData.size() > 0) { - for (i in 0 until manufacturerData.size()) { - val data = manufacturerData.valueAt(i) ?: continue - if (data.size >= 2) { - val tenths = ((data[0].toInt() and 0xFF) shl 8) or (data[1].toInt() and 0xFF) - val kg = tenths / 10.0 - if (kg in MIN_VALID_KG..MAX_VALID_KG) { - processWeight(kg) - } - } - } - } - } - - override fun onScanFailed(errorCode: Int) { - val params = Arguments.createMap().apply { - putString("message", "Scan failed with code: $errorCode") - } - sendEvent("onScaleError", params) - stopMeasuring() - } - } - - private fun processWeight(kg: Double) { - // Send live weight update - val liveParams = Arguments.createMap().apply { putDouble("weight", kg) } - sendEvent("onLiveWeight", liveParams) - - // Update status to measuring - sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "measuring") }) - - val now = System.currentTimeMillis() - - // Stability detection - if (candidateKg.isNaN() || abs(kg - candidateKg) > WEIGHT_TOL) { - candidateKg = kg - stableSince = now - } else if (now - stableSince >= STABLE_WINDOW_MS) { - // Stable weight achieved - val stableParams = Arguments.createMap().apply { putDouble("weight", candidateKg) } - sendEvent("onStableWeight", stableParams) - sendEvent("onStatusChange", Arguments.createMap().apply { putString("status", "stable") }) - stopMeasuring() - } - } - - private fun hasRequiredPermissions(): Boolean { - val perms = mutableListOf() - perms.add(android.Manifest.permission.ACCESS_FINE_LOCATION) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - perms.add(android.Manifest.permission.BLUETOOTH_SCAN) - perms.add(android.Manifest.permission.BLUETOOTH_CONNECT) - } - - return perms.all { - ContextCompat.checkSelfPermission(reactApplicationContext, it) == PackageManager.PERMISSION_GRANTED - } - } - - override fun onCatalystInstanceDestroy() { - super.onCatalystInstanceDestroy() - stopMeasuring() // Cleanup when RN instance destroys + return perms.all { + ContextCompat.checkSelfPermission(reactContext, it) == + PackageManager.PERMISSION_GRANTED } + } } \ No newline at end of file diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt index 364be9b..90fd8c0 100644 --- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt +++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt @@ -1,16 +1,19 @@ -package com.cureselect.weightpluse +package com.weightscalebridge import com.facebook.react.ReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.uimanager.ViewManager -class WeightScalePackage : ReactPackage { - override fun createNativeModules(reactContext: ReactApplicationContext): List { - return listOf(WeightScaleModule(reactContext)) - } +class WeightScaleBridgePackage : ReactPackage { - override fun createViewManagers(reactContext: ReactApplicationContext): List> { - return emptyList() - } -} \ No newline at end of file + override fun createNativeModules( + reactContext: ReactApplicationContext + ): List { + return listOf(WeightScaleModule(reactContext)) + } + + override fun createViewManagers( + reactContext: ReactApplicationContext + ): List> = emptyList() +} diff --git a/src/index.tsx b/src/index.tsx index 34b188d..c3d4088 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,5 +1,26 @@ -import WeightScaleBridge from './NativeWeightScaleBridge'; +import { NativeModules, Platform } from 'react-native'; -export function multiply(a: number, b: number): number { - return WeightScaleBridge.multiply(a, b); +const LINKING_ERROR = + `The package 'react-native-weight-scale-bridge' doesn't seem to be linked. Make sure:\n\n` + + Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + + '- You rebuilt the app after installing the package\n' + + '- You are not using Expo Go\n'; + +// Changed to match the native module name +const WeightScaleBridge = NativeModules.WeightScaleBridge; + +if (!WeightScaleBridge) { + throw new Error(LINKING_ERROR); } + +export const startScanning = () => + WeightScaleBridge.startScanning(); + +export const stopScanning = () => + WeightScaleBridge.stopScanning(); + +export const calculateBMI = (weight: number, heightCm: number) => + WeightScaleBridge.calculateBMI(weight, heightCm); + +export const isBluetoothEnabled = () => + WeightScaleBridge.isBluetoothEnabled(); \ No newline at end of file -- 2.49.1