expo-jl-ota
v0.0.6
Published
My new module
Maintainers
Readme
Expo 杰理OTA插件
针对JL(杰理)芯片的OTA固件更新的Expo插件。支持带有进度回调和错误处理的Android和iOS平台,支持与expo-bluetooth混用。
| | Android | iOS | |----------|---------|-------| | 版本支持 | SDK 21+ | 12.0+ |
安装
与最新的JL OTA插件包集成
- 安卓 SDK V1.9.2
- IOS SDK V2.3.1
Android杰理官方github仓库地址 IOS杰理官方github仓库地址
下载
在裸React Native项目中安装
对于裸React Native项目,您必须确保在继续之前已安装并配置了expo包。
添加包到npm依赖
npm install expo-jl-otaAndroid配置
在android/app/src/main/AndroidManifest.xml中添加必要的权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />iOS配置
安装npm包后运行npx pod-install。
在ios/YourApp/Info.plist中添加蓝牙权限:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>此应用需要蓝牙权限来连接和更新设备固件</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>此应用需要蓝牙权限来连接和更新设备固件</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>此应用需要位置权限来扫描蓝牙设备</string>使用方法
基本用法
import React, { useEffect } from 'react';
import { Alert, Platform, PermissionsAndroid } from 'react-native';
import ExpoJlOta from 'expo-jl-ota';
export default function App() {
useEffect(() => {
setupEventListeners();
requestPermissions();
}, []);
const setupEventListeners = () => {
// 监听OTA进度事件
ExpoJlOta.addListener('otaProgress', (event) => {
console.log(`OTA Progress: ${event.progress}%, Status: ${event.status}`);
});
// 监听连接状态事件
ExpoJlOta.addListener('connectionStatus', (event) => {
console.log('Connection status:', event.connected);
});
// 监听错误事件
ExpoJlOta.addListener('error', (event) => {
Alert.alert('Error', event.message);
});
};
const requestPermissions = async () => {
if (Platform.OS === 'android') {
const permissions = [
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
];
const granted = await PermissionsAndroid.requestMultiple(permissions);
const allGranted = Object.values(granted).every(
(permission) => permission === PermissionsAndroid.RESULTS.GRANTED
);
if (!allGranted) {
Alert.alert('Permissions Required', 'Please grant all required permissions for OTA functionality.');
}
}
};
const startOtaUpdate = async () => {
try {
// 开始扫描设备
await ExpoJlOta.startScan();
// 连接设备(使用实际设备UUID)
const deviceUuid = Platform.OS === 'android'
? '00:00:00:55:FB:D4'
: '2B3681AF-B077-297D-D291-FA4A908CE06A';
const connected = await ExpoJlOta.connectDevice(deviceUuid);
if (!connected) {
Alert.alert('Error', 'Failed to connect to device');
return;
}
// 获取设备信息
await ExpoJlOta.getDeviceInfo();
// 开始OTA升级
const firmwarePath = '/path/to/your/firmware.ufw';
const result = await ExpoJlOta.startOtaUpdate(deviceUuid, firmwarePath);
if (result) {
Alert.alert('Success', 'OTA update started');
} else {
Alert.alert('Error', 'Failed to start OTA update');
}
} catch (error) {
console.error('OTA Error:', error);
Alert.alert('Error', 'OTA operation failed');
}
};
return (
// 你的UI组件
);
}完整示例
import React, { useState, useEffect } from 'react';
import {
Alert,
Button,
SafeAreaView,
ScrollView,
Text,
View,
StyleSheet,
Platform,
PermissionsAndroid
} from 'react-native';
import * as FileSystem from 'expo-file-system';
import ExpoJlOta from 'expo-jl-ota';
export default function App() {
const [otaProgress, setOtaProgress] = useState<number>(0);
const [otaStatus, setOtaStatus] = useState<string>('');
const [isConnected, setIsConnected] = useState<boolean>(false);
const [permissionsGranted, setPermissionsGranted] = useState<boolean>(false);
useEffect(() => {
setupEventListeners();
requestPermissions();
}, []);
const setupEventListeners = () => {
// 监听OTA进度事件
ExpoJlOta.addListener('otaProgress', (event) => {
setOtaProgress(event.progress);
setOtaStatus(event.status);
console.log(`OTA Progress: ${event.progress}%, Status: ${event.status}`);
});
// 监听连接状态事件
ExpoJlOta.addListener('connectionStatus', (event) => {
setIsConnected(event.connected);
console.log('Connection status:', event.connected);
});
// 监听错误事件
ExpoJlOta.addListener('error', (event) => {
Alert.alert('Error', event.message);
console.error('OTA Error:', event.message);
});
// 监听设备信息事件
ExpoJlOta.addListener('deviceInfo', (event) => {
console.log('Device info:', event);
});
};
const requestPermissions = async () => {
try {
if (Platform.OS === 'android') {
const permissions = [
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
];
const granted = await PermissionsAndroid.requestMultiple(permissions);
const allGranted = Object.values(granted).every(
(permission) => permission === PermissionsAndroid.RESULTS.GRANTED
);
setPermissionsGranted(allGranted);
if (!allGranted) {
Alert.alert(
'Permissions Required',
'Please grant all required permissions for OTA functionality.',
[{ text: 'OK' }]
);
}
} else {
// iOS permissions are handled in Info.plist
setPermissionsGranted(true);
}
} catch (error) {
console.error('Error requesting permissions:', error);
setPermissionsGranted(false);
}
};
const startOtaUpdate = async () => {
try {
if (!permissionsGranted) {
Alert.alert('Error', 'Please grant all required permissions first');
return;
}
// 复制固件文件到应用目录
const fileName = 'update.ufw';
const firmwarePath = `${FileSystem.documentDirectory}${fileName}`;
// 检查文件是否已存在
const fileInfo = await FileSystem.getInfoAsync(firmwarePath);
if (!fileInfo.exists) {
Alert.alert(
'Firmware File Required',
'Please place the firmware file in the app directory.',
[{ text: 'OK' }]
);
return;
}
const deviceUuid = Platform.OS === 'android'
? '00:00:00:55:FB:D4'
: '2B3681AF-B077-297D-D291-FA4A908CE06A';
console.log('Starting OTA update with:', { deviceUuid, firmwarePath });
const result = await ExpoJlOta.startOtaUpdate(deviceUuid, firmwarePath);
console.log('OTA update started:', result);
if (result) {
Alert.alert('OTA Update', 'OTA update started successfully');
} else {
Alert.alert('Error', 'Failed to start OTA update');
}
} catch (error) {
console.error('Error starting OTA update:', error);
Alert.alert('Error', 'Failed to start OTA update');
}
};
return (
<SafeAreaView style={styles.container}>
<ScrollView style={styles.scrollView}>
<Text style={styles.header}>Expo JL OTA Example</Text>
<View style={styles.group}>
<Text style={styles.groupHeader}>OTA Status</Text>
<Text style={styles.text}>Progress: {otaProgress}%</Text>
<Text style={styles.text}>Status: {otaStatus || 'Idle'}</Text>
<Text style={styles.text}>Connected: {isConnected ? 'Yes' : 'No'}</Text>
<Text style={styles.text}>Permissions: {permissionsGranted ? 'Granted' : 'Not Granted'}</Text>
</View>
<View style={styles.group}>
<Text style={styles.groupHeader}>OTA Operations</Text>
<Button title="Start OTA Update" onPress={startOtaUpdate} />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#eee',
},
scrollView: {
flex: 1,
},
header: {
fontSize: 24,
fontWeight: 'bold',
margin: 20,
textAlign: 'center',
},
group: {
margin: 20,
backgroundColor: '#fff',
borderRadius: 10,
padding: 20,
},
groupHeader: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 15,
},
text: {
fontSize: 16,
marginBottom: 8,
},
});API参考
方法
startScan(): Promise<boolean>- 开始扫描设备connectDevice(uuid: string): Promise<boolean>- 连接指定UUID的设备getDeviceInfo(): Promise<boolean>- 获取设备信息startOtaUpdate(uuid: string, filePath: string): Promise<boolean>- 开始OTA升级cancelOtaUpdate(): Promise<boolean>- 取消OTA升级
事件
otaProgress- OTA进度更新事件otaStatus- OTA状态更新事件connectionStatus- 连接状态更新事件error- 错误事件deviceInfo- 设备信息事件deviceInfoError- 设备信息错误事件
事件监听
// 添加事件监听器
ExpoJlOta.addListener('otaProgress', (event) => {
console.log(`Progress: ${event.progress}%, Status: ${event.status}`);
});
// 移除事件监听器
const subscription = ExpoJlOta.addListener('otaProgress', callback);
subscription.remove();注意事项
- 权限要求: 确保在Android和iOS上正确配置了蓝牙和位置权限
- 固件文件: 确保UFW固件文件路径正确且文件存在
- 设备UUID: 使用正确的设备UUID进行连接
- 错误处理: 始终监听错误事件并适当处理
- 内存管理: 在组件卸载时移除事件监听器
贡献
欢迎贡献!请参考贡献指南中描述的指导原则。
