鸿蒙6星闪(SLE)设备发现流程说明
近期正好业务涉及到星闪模块,就写个学习文档吧。本文档将详细描述了基于 OpenHarmony 的星闪(StarLink Express, SLE)设备发现、连接和交互的完整流程。
近期正好业务涉及到星闪模块,就写个学习文档吧。
各位看官们点个赞,走过路过不要错过
本文档将详细描述了基于 OpenHarmony 的星闪(StarLink Express, SLE)设备发现、连接和交互的完整流程。
流程概览
检测星闪状态 → 请求权限 → 开始扫描 → 发现设备 → 连接设备 → 获取服务 → 数据交互
第一步:检测星闪是否打开
接口说明
|
项目 |
说明 |
|
方法 |
|
|
所属模块 |
|
|
返回类型 |
|
返回值说明
|
返回值 |
枚举名称 |
含义 |
|
0 |
|
已关闭 |
|
1 |
|
正在打开 |
|
2 |
|
已打开 |
|
3 |
|
正在关闭 |
代码示例
import { manager } from '@kit.NearLinkKit';
export function getSleState(): manager.NearlinkState {
let sleState = manager.NearlinkState.STATE_OFF;
try {
sleState = manager.getState();
console.debug(`当前星闪状态: ${sleState}`);
} catch (err) {
// 无权限或其他异常
console.error(`getSleState errCode: ${err.code}, errMessage: ${err.message}`);
}
return sleState;
}
状态判断逻辑
const state = getSleState();
if (state === manager.NearlinkState.STATE_ON) {
// 星闪已打开,可以进行下一步操作
} else if (state === manager.NearlinkState.STATE_TURNING_ON) {
// 星闪正在打开,等待状态变化
} else {
// 星闪未打开,需要引导用户开启
}
第二步:监听星闪状态变化
接口说明
|
项目 |
说明 |
|
方法 |
|
|
所属模块 |
|
|
回调参数 |
|
|
取消监听 |
|
代码示例
import { manager } from '@kit.NearLinkKit';
export async function enableSle(bleOnCallback: Function = null) {
manager.on('stateChange', state => {
if (state == manager.NearlinkState.STATE_ON) {
manager.off('stateChange'); // 状态已开启,取消监听
if (bleOnCallback) {
bleOnCallback();
}
}
console.debug(`星闪状态变化: ${state}`);
});
}
第三步:请求星闪访问权限
接口说明
|
项目 |
说明 |
|
方法 |
|
|
所属模块 |
|
|
所需权限 |
|
|
返回值 |
|
权限结果说明
|
authResults值 |
含义 |
|
0 |
用户同意授权 |
|
-1 |
用户拒绝授权 |
代码示例
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
const permissions: Array<Permissions> = ['ohos.permission.ACCESS_NEARLINK'];
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
// 用户授权成功,可以继续访问星闪功能
console.info('权限授权成功');
} else {
// 用户拒绝授权,需引导用户到系统设置开启权限
console.warn('用户拒绝授权');
return;
}
}
}).catch((err: BusinessError) => {
console.error(`请求权限失败. Code: ${err.code}, Message: ${err.message}`);
});
}
第四步:开始扫描设备
接口说明
|
项目 |
说明 |
|
注册扫描回调 |
|
|
开始扫描 |
|
|
停止扫描 |
|
|
取消回调 |
|
|
所属模块 |
|
扫描过滤器 (ScanFilters)
|
字段 |
类型 |
说明 |
|
|
string |
按设备名称过滤 |
扫描选项 (ScanOptions)
|
字段 |
类型 |
说明 |
|
|
number |
扫描模式 |
扫描模式说明
|
值 |
枚举名称 |
说明 |
|
0 |
|
低功耗模式 |
|
1 |
|
低延迟模式 |
|
2 |
|
平衡模式 |
扫描结果 (ScanResults)
|
字段 |
类型 |
说明 |
|
|
string |
设备名称 |
|
|
string |
设备地址(MAC) |
|
|
number |
信号强度 |
|
|
boolean |
是否可连接 |
代码示例
import { scan } from '@kit.NearLinkKit';
import { BusinessError } from '@kit.BasicServicesKit';
@State scanResults: Array<scan.ScanResults> = [];
@State isScanning: boolean = false;
startScan() {
// 清空之前的扫描结果
this.scanResults = [];
this.isScanning = true;
// 1. 注册扫描结果回调
scan.on('deviceFound', (data: Array<scan.ScanResults>) => {
for (let i = 0; i < data.length; i++) {
let device = data[i];
// 检查设备是否已存在(根据地址判断去重)
let exists = this.scanResults.some(item => item.address === device.address);
if (!exists) {
this.scanResults.push(device);
console.info(`发现设备: ${device.deviceName}, 地址: ${device.address}`);
}
}
});
// 2. 配置扫描过滤器(可选)
let scanFilter: scan.ScanFilters = {};
// scanFilter.deviceName = "设备名称"; // 可选:按名称过滤
// 3. 配置扫描选项
let scanOptions: scan.ScanOptions = {
scanMode: 2 // SCAN_MODE_BALANCED
};
// 4. 开始扫描
scan.startScan([scanFilter], scanOptions)
.then(() => {
console.info('扫描已开始');
})
.catch((err: BusinessError) => {
console.error(`扫描启动失败. errCode: ${err.code}, errMessage: ${err.message}`);
this.isScanning = false;
});
}
stopScan() {
scan.stopScan()
.then(() => {
console.info('扫描已停止');
this.isScanning = false;
})
.catch((err: BusinessError) => {
console.error(`停止扫描失败. errCode: ${err.code}, errMessage: ${err.message}`);
});
// 取消监听
scan.off('deviceFound');
}
第五步:连接设备
接口说明
|
项目 |
说明 |
|
创建客户端 |
|
|
连接设备 |
|
|
断开连接 |
|
|
关闭客户端 |
|
|
所属模块 |
|
连接状态监听
|
项目 |
说明 |
|
注册回调 |
|
|
回调参数 |
|
|
取消监听 |
|
连接状态说明
|
值 |
枚举名称 |
说明 |
|
0 |
|
已断开 |
|
1 |
|
正在连接 |
|
2 |
|
已连接 |
|
3 |
|
正在断开 |
代码示例
import { ssap, constant } from '@kit.NearLinkKit';
import { BusinessError } from '@kit.BasicServicesKit';
let client: ssap.Client | undefined = undefined;
async function connectDevice(address: string) {
try {
// 1. 创建客户端
client = ssap.createClient(address);
// 2. 注册连接状态变化回调
client.on('connectionStateChange', (data: ssap.ConnectionChangeState) => {
if (data.state === constant.ConnectionState.STATE_CONNECTED) {
console.info('设备已连接');
// 连接成功后获取服务
getServices();
} else if (data.state === constant.ConnectionState.STATE_DISCONNECTED) {
console.info('设备已断开');
client?.close();
client = undefined;
}
});
// 3. 发起连接
await client.connect();
console.info('连接请求已发送');
} catch (err) {
console.error(`连接失败. errCode: ${(err as BusinessError).code}, errMessage: ${(err as BusinessError).message}`);
}
}
async function disconnectDevice() {
try {
await client?.disconnect();
client?.off('connectionStateChange');
client?.close();
client = undefined;
} catch (err) {
console.error(`断开连接失败. errCode: ${(err as BusinessError).code}`);
}
}
第六步:获取服务列表
接口说明
|
项目 |
说明 |
|
方法 |
|
|
返回类型 |
|
服务结构 (Service)
|
字段 |
类型 |
说明 |
|
|
string |
服务UUID |
|
|
Array\<Property\> |
属性列表 |
属性结构 (Property)
|
字段 |
类型 |
说明 |
|
|
string |
所属服务UUID |
|
|
string |
属性UUID |
|
|
number |
支持的操作 |
|
|
ArrayBuffer |
属性值 |
|
|
Array |
描述符列表 |
代码示例
let services: Array<ssap.Service> = [];
async function getServices() {
try {
const result = await client?.getServices();
if (result) {
services = result;
console.info('获取服务成功: ' + JSON.stringify(result));
// 遍历服务和属性
services.forEach(service => {
console.info(`服务UUID: ${service.serviceUuid}`);
service.properties.forEach(property => {
console.info(` 属性UUID: ${property.propertyUuid}`);
});
});
}
} catch (err) {
console.error(`获取服务失败. errCode: ${(err as BusinessError).code}`);
}
}
第七步:数据交互
7.1 读取属性
|
项目 |
说明 |
|
方法 |
|
|
参数 |
|
|
返回类型 |
|
async function readProperty(property: ssap.Property) {
try {
const result = await client?.readProperty(property);
if (result && result.value) {
const data = new Uint8Array(result.value);
console.info(`读取结果: ${Array.from(data).join(',')}`);
}
} catch (err) {
console.error(`读取属性失败. errCode: ${(err as BusinessError).code}`);
}
}
7.2 写入属性
|
项目 |
说明 |
|
方法 |
|
|
写入类型 |
|
|
写入类型 |
说明 |
|
|
写入并等待响应 |
|
|
写入不等待响应 |
async function writeProperty(property: ssap.Property) {
try {
await client?.writeProperty(property, ssap.PropertyWriteType.WRITE_NO_RESPONSE);
console.info('写入成功');
} catch (err) {
console.error(`写入属性失败. errCode: ${(err as BusinessError).code}`);
}
}
7.3 订阅属性通知
|
项目 |
说明 |
|
设置通知 |
|
|
监听变化 |
|
|
取消监听 |
|
async function subscribeProperty(property: ssap.Property) {
// 注册属性变化回调
client?.on('propertyChange', (data: ssap.Property) => {
console.info('属性变化: ' + JSON.stringify(data));
if (data.value) {
const value = new Uint8Array(data.value);
console.info(`通知数据: ${Array.from(value).join(',')}`);
}
});
// 开启通知
try {
await client?.setPropertyNotification(property, true);
console.info('订阅通知成功');
} catch (err) {
console.error(`订阅通知失败. errCode: ${(err as BusinessError).code}`);
}
}
完整流程时序图
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ APP │ │ manager │ │ scan │ │ ssap │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ getState() │ │ │
│───────────────>│ │ │
│ 返回状态(0-3) │ │ │
│<───────────────│ │ │
│ │ │ │
│ on('stateChange') │ │
│───────────────>│ │ │
│ │ │ │
│ requestPermissions │ │
│────────────────────────────────>│ │
│ authResults │ │
│<────────────────────────────────│ │
│ │ │ │
│ on('deviceFound') │ │
│────────────────────────────────>│ │
│ startScan() │ │ │
│────────────────────────────────>│ │
│ ScanResults[] │ │ │
│<────────────────────────────────│ │
│ stopScan() │ │ │
│────────────────────────────────>│ │
│ │ │ │
│ createClient(address) │ │
│─────────────────────────────────────────────────>│
│ client │ │ │
│<─────────────────────────────────────────────────│
│ connect() │ │ │
│─────────────────────────────────────────────────>│
│ ConnectionState │ │
│<─────────────────────────────────────────────────│
│ getServices() │ │ │
│─────────────────────────────────────────────────>│
│ Service[] │ │ │
│<─────────────────────────────────────────────────│
│ read/write/subscribe │ │
│─────────────────────────────────────────────────>│
│ │ │ │
关键模块依赖
import { manager, scan, ssap, constant } from '@kit.NearLinkKit';
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
错误处理建议
- 权限未授予: 引导用户到系统设置页面手动开启权限
- 星闪未开启: 提示用户开启星闪功能或监听状态变化
- 扫描超时: 建议设置扫描超时时间(如20秒),超时后自动停止扫描
- 连接失败: 检查设备是否在范围内,重试连接
- 服务获取失败: 确保连接成功后再获取服务,可适当延迟获取
更多推荐




所有评论(0)