medcase-sdk
v2.1.0
Published
React Native Bluetooth SDK for MedCase medical device communication
Downloads
87
Maintainers
Readme
MedCase Bluetooth SDK
A React Native Bluetooth SDK for communicating with MedCase medical devices. Works with both Expo and standard React Native projects, with optional TypeScript support.
Features
- 📱 Works with both Expo and React Native
- 🔧 Automatic platform detection and adapter selection
- 📦 Built-in connection management
- 🔀 Data transformation and encoding (URL-encoded UTF-8 format)
- 🎯 Manual connection mode for advanced users
- 📝 Full TypeScript support (optional)
- 🔄 Event-driven architecture
- ⚡ Error handling and retry logic
- 📊 Comprehensive logging
- 🔄 Flutter-compatible data format
Installation
npm install medcase-sdk
# or
yarn add medcase-sdkDependencies
The SDK automatically detects your environment and uses the appropriate Bluetooth library:
- Expo:
react-native-ble-plx - React Native:
react-native-ble-manager
Install the required dependency for your platform:
# For Expo
npm install react-native-ble-plx
# For React Native
npm install react-native-ble-managerPlatform Setup
Expo
Add the plugin to your app.json or app.config.js:
{
"expo": {
"plugins": [
[
"react-native-ble-plx",
{
"isBackgroundEnabled": true,
"modes": ["bluetooth"]
}
]
]
}
}React Native
iOS
Add to your Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs Bluetooth access to communicate with medical devices</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs Bluetooth access to communicate with medical devices</string>Android
Add to your AndroidManifest.xml:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />Quick Start
Recommended Usage (Auto-Connect and Discover)
The SDK now provides a streamlined auto-connect approach that eliminates the need for manual scanning and connection steps:
import { MedCaseBluetoothSDK } from 'medcase-sdk';
const sdk = new MedCaseBluetoothSDK({
boxId: '2A:DC:C3:AF:B9:90', // Specific device to connect to
});
async function connectAndSendData() {
try {
// Initialize SDK and request permissions
const initialized = await sdk.initialize();
if(!initialized) return;
// Auto-connect to device and discover services/characteristics
const result = await sdk.autoConnectAndDiscover();
// Send WiFi credentials with location data
await sdk.sendData({
ssid: 'MyWiFiNetwork',
password: 'MyPassword123',
time: '2023-12-01 10:30:00 123',
lat: '40.7128',
lng: '-74.0060'
});
await sdk.disconnectFromDevice();
} catch (error) {
console.error('Error:', error);
}
}API Reference
Configuration
The Configuration class provides utilities for generating and opening admin URLs for MedCase devices.
Constructor
const config = new Configuration(boxId: string, phoneNumber: string);Parameters:
boxId(string): The Bluetooth device ID or MAC addressphoneNumber(string): The phone number associated with the device
Example:
import { Configuration } from 'medcase-sdk';
const config = new Configuration('C8:F0:9E:7A:79:70', '7908075918');Methods
link(): string
Returns the admin URL as a string.
Returns: string - The complete admin URL
Example:
const config = new Configuration('C8:F0:9E:7A:79:70', '7908075918');
const url = config.link();
console.log(url);
// Output: https://admin.medcase.in/admin/partner/C8:F0:9E:7A:79:70/7908075918openInBrowser(): Promise<void>
Opens the admin URL in the device's default browser.
Throws: Error if the URL cannot be opened
Example:
const config = new Configuration('C8:F0:9E:7A:79:70', '7908075918');
try {
await config.openInBrowser();
console.log('Browser opened successfully');
} catch (error) {
console.error('Failed to open browser:', error.message);
}Getter Methods
getBoxId(): string- Returns the current box IDgetPhoneNumber(): string- Returns the current phone number
Setter Methods
updateBoxId(boxId: string): void- Updates the box IDupdatePhoneNumber(phoneNumber: string): void- Updates the phone number
Example:
const config = new Configuration('C8:F0:9E:7A:79:70', '7908075918');
// Get current values
console.log(config.getBoxId()); // 'C8:F0:9E:7A:79:70'
console.log(config.getPhoneNumber()); // '7908075918'
// Update values
config.updateBoxId('D1:E2:F3:G4:H5:76');
config.updatePhoneNumber('9876543210');
console.log(config.link());
// Output: https://admin.medcase.in/admin/partner/D1:E2:F3:G4:H5:76/9876543210URL Format
The generated URLs follow this pattern:
https://admin.medcase.in/admin/partner/{boxId}/{phoneNumber}Where:
{boxId}is the device ID/MAC address{phoneNumber}is the associated phone number
MedCaseBluetoothSDK
Constructor Options
interface MedCaseSDKConfig {
autoManageConnection?: boolean; // Default: true
serviceUUID?: string; // Default: '1800'
characteristicUUID?: string; // Default: '2A00'
enableLogging?: boolean; // Default: false
connectionTimeout?: number; // Default: 30000 (ms)
boxId?: string; // Optional: for device name filtering
deviceNamePrefix?: string; // Default: 'MedCase'
dataTransformation?: {
encoding?: 'utf8' | 'base64' | 'hex'; // Default: 'utf8'
delimiter?: string; // Default: '|'
prefix?: string;
suffix?: string;
};
}Methods
Connection Management
initialize(): Promise<boolean>- Initialize SDK and request permissionsautoConnectAndDiscover(): Promise<{connection, services, characteristics}>- Auto-connect and discover services/characteristics (Recommended)scanForDevices(serviceUUIDs?, timeoutMs?): Promise<MedCaseDevice[]>- Scan for devices (Manual approach)connectToDevice(deviceId, options?): Promise<BluetoothConnection>- Connect to specific devicedisconnectFromDevice(deviceId?): Promise<void>- Disconnect from devicegetCurrentConnection(): BluetoothConnection | null- Get current connectionisConnected(): boolean- Check if connected
Data Transmission
sendData(values, deviceId?): Promise<void>- Send data with automatic connectionsendDataToCharacteristic(connection, serviceUUID, characteristicUUID, values): Promise<void>- Send to specific characteristic
Configuration
updateConfig(newConfig): void- Update configurationgetConfig(): MedCaseSDKConfig- Get current configurationcleanup(): Promise<void>- Clean up resources
Events
on(event, listener): void- Add event listeneroff(event, listener): void- Remove event listener
Events
device-discovered- When a matching device is found during scanningdevice-connected- When a device is connecteddevice-disconnected- When a device is disconnectederror- When an error occurs
Note: The data-received event and notification listening methods are kept for internal use only and are not exposed in the public API.
Data Format
The SDK uses URL-encoded UTF-8 format that's fully compatible with Flutter apps. When you send data:
// Input data
{
ssid: 'MyWiFiNetwork',
password: 'MyPassword123',
time: '2023-12-01 10:30:00 123',
lat: '40.7128',
lng: '-74.0060'
}It gets transformed to: MyWiFiNetwork/MyPassword123/CT:2023-12-01%2010%3A30%3A00%20123/LT:40.7128/LG:-74.0060
This matches the Flutter Uri.encodeComponent() behavior exactly, ensuring seamless communication between React Native and Flutter MedCase apps.
Data Structure
The SDK expects data with these fields:
ssid: WiFi network namepassword: WiFi passwordtime: Timestamp with millisecondslat: Latitude coordinatelng: Longitude coordinate
Format Details
The transmitted format follows this pattern:
{encodedSSID}/{encodedPassword}/CT:{encodedTime}/LT:{encodedLat}/LG:{encodedLng}Where:
- All values are URL-encoded using
encodeURIComponent() CT:prefix for Current TimeLT:prefix for LatitudeLG:prefix for Longitude- Separated by
/and:characters
Format Explanation:
$encodedSSID/$encodedPassword/CT:$encodedTime/LT:$encodedLat/LG:$encodedLng- All values are URL encoded to handle special characters
- CT: Current Time, LT: Latitude, LG: Longitude
- Time format should be:
yyyy-MM-dd HH:mm:ss SSS
Device Name Filtering
The SDK can automatically filter devices by name during scanning:
// Default behavior - searches for devices starting with 'MedCase'
const sdk = new MedCaseBluetoothSDK();
// Custom prefix
const sdk = new MedCaseBluetoothSDK({
deviceNamePrefix: 'CustomDevice'
});
// Exact match with boxId
const sdk = new MedCaseBluetoothSDK({
deviceNamePrefix: 'MedCase',
boxId: '12345' // Will search for exact name 'MedCase12345'
});Usage Workflow
Recommended Workflow (Auto-Connect)
- Initialize SDK - Request permissions and set up Bluetooth
- Auto-Connect - Use
autoConnectAndDiscover()to automatically find, connect to, and discover services/characteristics - Send Data - Use
sendData()to transmit information to the device - Cleanup - Call
cleanup()when done
Manual Workflow (Legacy)
- Initialize SDK - Request permissions and set up Bluetooth
- Scan - Use
scanForDevices()to find available devices - Connect - Use
connectToDevice()to establish connection - Discover Services (Optional) - Use
discoverServices()anddiscoverCharacteristics() - Send Data - Use
sendData()to transmit information - Disconnect - Use
disconnectFromDevice()when done
Examples
Configuration Usage
import { Configuration } from 'medcase-sdk';
// Create configuration instance
const config = new Configuration('C8:F0:9E:7A:79:70', '7908075918');
// Generate URL link
const adminUrl = config.link();
console.log(adminUrl);
// https://admin.medcase.in/admin/partner/C8:F0:9E:7A:79:70/7908075918
// Open in browser
await config.openInBrowser();
// Update configuration
config.updateBoxId('D1:E2:F3:G4:H5:76');
config.updatePhoneNumber('9876543210');React Native Integration
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
import { Configuration } from 'medcase-sdk';
const ConfigScreen = () => {
const [boxId, setBoxId] = useState('C8:F0:9E:7A:79:70');
const [phoneNumber, setPhoneNumber] = useState('7908075918');
const handleOpenAdmin = async () => {
try {
const config = new Configuration(boxId, phoneNumber);
await config.openInBrowser();
} catch (error) {
Alert.alert('Error', error.message);
}
};
const handleGenerateLink = () => {
try {
const config = new Configuration(boxId, phoneNumber);
const url = config.link();
Alert.alert('Generated URL', url);
} catch (error) {
Alert.alert('Error', error.message);
}
};
return (
<View>
<TextInput
value={boxId}
onChangeText={setBoxId}
placeholder="Box ID"
/>
<TextInput
value={phoneNumber}
onChangeText={setPhoneNumber}
placeholder="Phone Number"
keyboardType="phone-pad"
/>
<Button title="Generate Link" onPress={handleGenerateLink} />
<Button title="Open in Browser" onPress={handleOpenAdmin} />
</View>
);
};See the example/ directory for a complete working example app that demonstrates both the auto-connect and manual connection approaches, plus the Configuration class usage.
TypeScript Support
The SDK includes full TypeScript definitions. Import types as needed:
import {
MedCaseBluetoothSDK,
MedCaseDevice,
BluetoothConnection,
MedCaseData,
Configuration
} from 'medcase-sdk';Error Handling
The SDK provides comprehensive error handling:
sdk.on('error', (error) => {
console.error('SDK Error:', error.message);
// Handle specific errors
if (error.message.includes('Connection timeout')) {
// Handle timeout
} else if (error.message.includes('Bluetooth permissions')) {
// Handle permission issues
}
});Troubleshooting
Common Issues and Solutions
"Cannot read property 'createClient' of null"
Cause: This error occurs when the Bluetooth library is not properly installed or linked.
Solutions:
Ensure correct library is installed:
# For Expo projects npm install react-native-ble-plx expo-constants # For React Native projects npm install react-native-ble-managerFor React Native - Link the library:
cd ios && pod install && cd ..For Expo - Configure plugin in app.json:
{ "expo": { "plugins": [ ["react-native-ble-plx", { "isBackgroundEnabled": true, "modes": ["bluetooth"] }] ] } }Clean and rebuild:
# Expo expo start -c # React Native npx react-native run-android --reset-cache npx react-native run-ios --reset-cache
Bluetooth Support Check Failed
Cause: The Bluetooth library failed to initialize properly.
Solutions:
Check platform compatibility:
- iOS: Ensure iOS 10+ device
- Android: Ensure Bluetooth Low Energy support
Verify permissions:
- iOS: Check Info.plist has Bluetooth permissions
- Android: Check AndroidManifest.xml has all required permissions
Restart Bluetooth:
- Toggle device Bluetooth off/on
- Restart the app
Library Version Mismatches
Cause: Using incompatible versions of Bluetooth libraries.
Solution: Use the recommended versions:
{
"dependencies": {
"react-native-ble-manager": "^12.4.1",
"react-native-ble-plx": "^3.5.0",
"expo-constants": "^16.0.2"
}
}Debug Mode
Enable detailed logging to troubleshoot issues:
const sdk = new MedCaseBluetoothSDK({
enableLogging: true // Enables detailed console logs
});Platform Detection Issues
If the SDK detects the wrong platform, you can manually check:
import { getPlatformInfo } from 'medcase-sdk';
const platformInfo = getPlatformInfo();
console.log('Platform:', platformInfo);
// Output: { isExpo: boolean, isReactNative: boolean, platform: 'ios'|'android'|'web' }Platform Differences
| Feature | Expo | React Native | |---------|------|--------------| | Library | react-native-ble-plx | react-native-ble-manager | | Permissions | Automatic | Manual setup required | | iOS Setup | Automatic | Info.plist required | | Android Setup | Plugin configuration | Manifest permissions required |
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
For support, please open an issue on GitHub or contact the MedCase team.
