扫地机 P2P 功能

更新时间:2025-12-16 07:22:06下载pdf

概述

扫地机的 P2P 能力是依托于 IPC 的 P2P 和文件传输实现的,除了基础的涂鸦 SDK,还需要额外依赖这两个库,即可直接使用。

SDK 包:

  • @thingsmart/thingp2pfiletranssdk - P2P 文件传输核心库
  • @thingsmart/ipcsdk - IPC功能库

平台: HarmonyOS (ArkTS)

模块导入

// IPC SDK 管理器
import { ThingIPCSdk } from '@thingsmart/ipcsdk'

// P2P 文件传输核心
import { 
  ThingP2pFileTransManager,      // 文件传输管理器(静态类)
  ThingP2pFileTransInterface,    // 文件传输接口
  ThingP2pFileTransListener      // 文件传输监听器
} from '@thingsmart/thingp2pfiletranssdk'



1. ThingIPCSdk 模块

1.1 getP2P

功能描述

获取 P2P 管理实例,用于管理 P2P 连接的生命周期。这是一个单例模式的静态方法。

函数签名

static getP2P(): IThingP2P

参数说明

返回值

类型 说明
IThingP2P P2P 管理实例,包含初始化、连接、断开等方法

注意事项

  • 这是一个静态方法,直接通过类名调用
  • 返回的是单例对象,多次调用返回同一实例

使用示例

const p2pManager = ThingIPCSdk.getP2P()

1.2 initP2P

功能描述

初始化 P2P SDK,这是使用 SDK 所有功能前的必要步骤。初始化会配置 SDK 运行环境、注册必要的服务和组件。

函数签名

initP2P(userId: string): number

参数说明

参数 类型 必填 说明
userId string 用户 ID,用于标识当前用户

返回值

类型 说明
number 调用结果:0=成功,其他值=失败

注意事项

  • ⚠️ 必须在所有 P2P 操作前调用此方法
  • 建议在应用启动时尽早执行初始化
  • 此方法为同步调用,返回值表示初始化结果
  • 重复初始化会被忽略,建议使用标志位控制

使用示例

const result = ThingIPCSdk.getP2P().initP2P('user_12345')
if (result === 0) {
  L.i('P2PDemo', 'SDK 初始化成功')
} else {
  L.e('P2PDemo', `SDK 初始化失败: ${result}`)
}

1.3 connectWithDevId

功能描述

连接指定的设备,建立 P2P 会话。连接成功后会通过回调返回 sessionId(handle),用于后续文件传输操作。

函数签名

connectWithDevId(remoteId: string, lanMode: number, timeout: number, callback: IThingP2PCallback): string

参数说明

参数 类型 必填 说明
remoteId string 设备 ID(远程设备标识符)
lanMode number 连接模式:0=互联网模式,1=局域网模式
timeout number 超时时间(毫秒),建议不低于 10000ms
callback IThingP2PCallback P2P 回调接口

IThingP2PCallback 接口定义

interface IThingP2PCallback {
  onResult(handle: number): void
}
回调方法 参数 说明
onResult handle: number 连接结果回调,handle 即 sessionId
• handle > 0: 连接成功,值为 sessionId
• handle = 0: 初始状态
• handle < 0: 连接失败或断开

返回值

类型 说明
string 连接请求的追踪 ID(traceId)

会话句柄(handle)值说明

说明
> 0 连接成功,值为 sessionId(需要设置到文件传输实例)
0 初始状态
-1 连接失败
-2 连接断开
-3 连接超时

注意事项

  • ⚠️ 连接前必须先调用 initP2P 初始化
  • 🔥 onResult 回调中的 handle 参数(当 >0 时)就是 sessionId,需要设置到文件传输实例中
  • 互联网模式(0)适用于远程连接,局域网模式(1)适用于同一网络内的快速连接
  • 超时时间根据网络环境调整,建议不低于 10 秒
  • 同一设备重复连接会先断开旧连接
  • onResult 会被多次调用,用于通知会话状态变化

使用示例

// 定义回调
const callback: IThingP2PCallback = {
  onResult: (handle: number) => {
    L.i('P2PDemo', `P2P 连接结果: handle=${handle}`)
    
    if (handle > 0) {
      // 连接成功,handle 即为 sessionId,需要设置到文件传输实例
      p2pFileTransfer.session = handle
      L.i('P2PDemo', `连接成功,已设置 sessionId: ${handle}`)
    } else if (handle === 0) {
      L.i('P2PDemo', '连接初始化中...')
    } else {
      // handle < 0 表示连接失败或断开
      L.e('P2PDemo', `连接失败或断开: ${handle}`)
    }
  }
}

// 发起连接
ThingIPCSdk.getP2P().connectWithDevId(
  'device_abc123',  // 设备 ID
  0,                // 互联网模式
  15000,            // 15 秒超时
  callback          // 回调接口
)

完整示例(结合文件传输)

class P2PManager {
  private p2pFileTransfer: ThingP2pFileTransInterface | null = null
  private sessionId: number = -1
  
  async connectDevice(deviceId: string) {
    // 1. 创建文件传输监听器
    const listener: ThingP2pFileTransListener = {
      onSessionStatusChanged: (sessionId, sessionStatus) => {
        L.i('P2PDemo', `会话状态: ${sessionStatus}`)
        return 0
      },
      // ... 其他回调
    }
    
    // 2. 创建文件传输实例
    this.p2pFileTransfer = ThingP2pFileTransManager.createP2pFileTransfer(
      deviceId,
      listener
    )
    
    // 3. 定义连接回调
    const callback: IThingP2PCallback = {
      onResult: (handle: number) => {
        if (handle > 0) {
          // 🔥 保存 sessionId 并设置到文件传输实例
          this.sessionId = handle
          if (this.p2pFileTransfer) {
            this.p2pFileTransfer.session = handle
            L.i('P2PDemo', `✅ 已设置 sessionId: ${handle}`)
          }
        } else if (handle < 0) {
          L.e('P2PDemo', `连接失败: ${handle}`)
          this.sessionId = -1
        }
      }
    }
    
    // 4. 发起连接
   ThingIPCSdk.getP2P().connectWithDevId(
      deviceId,
      0,      // 互联网模式
      15000,  // 超时时间
      callback
    )
    
  }
}

1.4 disConnect

功能描述

断开指定设备的 P2P 连接,释放相关资源。

函数签名

disConnect(handle: number, reason: number, forced: boolean): number

参数说明

参数 类型 必填 说明
handle number 会话句柄(sessionId),从 connectWithDevId 的回调中获取
reason number 断开原因码:0=正常断开,其他值表示异常断开
forced boolean 是否强制断开:true=立即断开,false=优雅断开

返回值

类型 说明
number 调用结果:0=成功,其他值=失败

注意事项

  • 断开连接前应先销毁对应的文件传输实例
  • handle 参数必须是有效的 sessionId(>0)
  • 强制断开会立即释放资源,可能导致数据丢失
  • 优雅断开会等待当前传输任务完成
  • 建议在不需要使用设备时及时断开连接

使用示例

// 假设从连接回调中获取到的 sessionId
const sessionId = 12345

// 方式1:正常断开(优雅关闭)
const result = ThingIPCSdk.getP2P().disConnect(
  sessionId,  // 会话句柄
  0,          // 正常断开
  false       // 优雅断开
)

if (result === 0) {
  L.i('P2PDemo', '设备断开成功')
} else {
  L.e('P2PDemo', `设备断开失败: ${result}`)
}

// 方式2:强制断开
const forceResult = ThingIPCSdk.getP2P().disConnect(
  sessionId,  // 会话句柄
  1,          // 异常断开
  true        // 强制断开
)

1.5 deInitP2P

功能描述

反初始化 P2P SDK,释放所有资源。通常在应用退出时调用。

函数签名

deInitP2P(): number

参数说明

返回值

类型 说明
number 调用结果:0=成功,其他值=失败

注意事项

  • 反初始化前必须先断开所有设备连接
  • 反初始化后需要重新调用 initP2P 才能使用
  • 通常在应用退出或长时间不使用时调用
  • 此方法为同步调用,返回值表示反初始化结果

使用示例

// 先断开所有连接
const disconnectResult = ThingIPCSdk.getP2P().disConnect(sessionId, 0, false)
if (disconnectResult !== 0) {
  L.e('P2PDemo', `断开连接失败: ${disconnectResult}`)
}

// 反初始化 SDK
const result = ThingIPCSdk.getP2P().deInitP2P()
if (result === 0) {
  L.i('P2PDemo', 'SDK 反初始化成功')
} else {
  L.e('P2PDemo', `SDK 反初始化失败: ${result}`)
}

2. ThingP2pFileTransManager 模块

2.1 createP2pFileTransfer

功能描述

创建 P2P 文件传输实例。每个设备需要创建独立的文件传输实例,用于查询文件索引、上传下载文件等操作。

函数签名

static createP2pFileTransfer(
  deviceId: string, 
  listener: ThingP2pFileTransListener
): ThingP2pFileTransInterface

参数说明

参数 类型 必填 说明
deviceId string 设备 ID,必须与连接时使用的设备 ID 一致
listener ThingP2pFileTransListener 文件传输监听器,用于接收各种回调事件

返回值

类型 说明
ThingP2pFileTransInterface 文件传输实例,提供查询、上传、下载等方法

注意事项

  • 每个设备必须创建独立的文件传输实例
  • 创建实例后,必须在连接成功的状态回调中将 sessionId 设置到实例的 session 属性
  • 实例与监听器绑定,不能共享监听器
  • 销毁实例时需调用 destroyP2pFileTransfer() 方法

使用示例

// 1. 创建监听器
const listener: ThingP2pFileTransListener = {
  onSessionStatusChanged: (sessionId, status) => {
    L.i('P2PDemo', `会话状态: ${status}`)
    return 0
  },
  onFileFinished: (event, filename, index, errCode) => {
    L.i('P2PDemo', `文件完成: ${filename}`)
    return 0
  },
  // ... 其他回调
}

// 2. 创建文件传输实例
const p2pFileTransfer = ThingP2pFileTransManager.createP2pFileTransfer(
  'device_abc123',
  listener
)

// 3. 连接设备后设置 sessionId(重要!)
ThingIPCSdk.getP2P().connectWithDevId(
  { deviceId: 'device_abc123' },
  (event) => {
    if (event.status > 0) {
      //  关键步骤:设置 sessionId
      p2pFileTransfer.session = event.status
      L.i('P2PDemo', `已设置 sessionId: ${event.status}`)
    }
  },
  () => L.i('P2PDemo', '连接成功'),
  (code, msg) => L.e('P2PDemo', `连接失败: ${msg}`)
)

2.2 getSDKVersion

功能描述

获取 P2P 文件传输 SDK 的版本号。

函数签名

static getSDKVersion(): string

参数说明

返回值

类型 说明
string SDK 版本号,格式如 “1.0.0”

注意事项

  • 用于调试和兼容性检查

使用示例

const version = ThingP2pFileTransManager.getSDKVersion()
L.i('P2PDemo', `SDK 版本: ${version}`)

3. ThingP2pFileTransInterface 实例方法

3.1 session(属性)

功能描述

会话 ID 属性,必须在连接成功后设置。这是 P2P 文件传输的核心标识。

属性类型

session: number

说明

属性 类型 说明
session number 会话 ID,从 connectWithDevId 的状态回调中获取

注意事项

  • 这是最关键的步骤!必须在连接成功后立即设置
  • sessionId 来自 connectWithDevIdonStatusChange 回调中的 event.status(当 status > 0 时)
  • 如果不设置,后续的查询和传输操作将失败

使用示例

// 在连接状态回调中设置
ThingIPCSdk.getP2P().connectWithDevId(
  { deviceId: 'device_abc123' },
  (event) => {
    if (event.status > 0) {
      //  设置 sessionId 到文件传输实例
      p2pFileTransfer.session = event.status
      L.i('P2PDemo', `已设置 session: ${event.status}`)
    }
  },
  () => {},
  (code, msg) => {}
)

3.2 queryFileIndexs

功能描述

查询指定相册的文件索引列表。返回的文件索引包含文件名、类型、时间等信息,可用于后续的下载操作。

函数签名

queryAlbumFile(
  albumName: string,
): number

参数说明

参数 类型 必填 说明
albumName string 相册名称,如 “Camera”、“Maps” 等

返回值

类型 说明
number 调用结果:0=成功,其他值=失败

注意事项

  • 查询前必须先连接设备并设置 sessionId
  • 实际的查询结果数据在监听器的 onP2pResponse 回调中返回(event=12)
  • callback 参数可能不会被调用,仅用于兼容性
  • 查询结果的数据格式为 P2PAlbumFileIndexs,包含 countitems 字段

使用示例

// 方式一:使用监听器接收数据(推荐)
const listener: ThingP2pFileTransListener = {
  onP2pResponse: (event, errCode, data) => {
    if (event === 12) {  // 查询文件索引事件
      if (errCode === 0 && data) {
        const result: P2PAlbumFileIndexs = JSON.parse(data)
        L.i('P2PDemo', `查询成功: count=${result.count}, items=${result.items.length}`)
        
        // 处理文件列表
        result.items.forEach(file => {
          L.i('P2PDemo', `文件: ${file.filename}, 类型: ${file.type}`)
        })
      }
    }
    return 0
  },
  // ... 其他回调
}

// 调用查询方法
const result = p2pFileTransfer.queryFileIndexs('Camera', (indexes) => {
  // 注意:这个回调可能不会被调用
  L.i('P2PDemo', `查询回调: ${indexes.length}`)
})

if (result !== 0) {
  L.e('P2PDemo', `查询调用失败: ${result}`)
}

3.3 startDownloadFiles

功能描述

开始下载指定的文件列表到本地目录。支持批量下载,下载进度通过监听器回调通知。

函数签名

startDownloadFiles(
  albumName: string,
  savePath: string,
  fileIndexes: string
): number

参数说明

参数 类型 必填 说明
albumName string 相册名称,必须与查询时使用的相册名一致
savePath string 保存路径,必须是绝对路径且目录必须存在
fileIndexes string 文件索引数组的 JSON 字符串,通过 JSON.stringify(FileIndex[]) 生成

返回值

类型 说明
number 调用结果:0=成功启动,其他值=失败

注意事项

  • 下载前必须先查询文件索引
  • 保存路径必须是已存在的目录,否则下载失败
  • 建议使用 HarmonyOS 的 fs.mkdirSync() 确保目录存在
  • 应该在监听器的 onP2pResponse 回调中(查询成功后)调用此方法
  • 下载进度通过 onFileProgress 回调通知
  • 下载完成通过 onFileFinished 回调通知

使用示例

// 在 onP2pResponse 中接收查询结果并自动下载
onP2pResponse: (event, errCode, data) => {
  if (event === 12 && errCode === 0 && data) {
    const result: P2PAlbumFileIndexs = JSON.parse(data)
    
    // 准备保存路径
    const savePath = '/data/storage/el2/base/haps/entry/files/downloads'
    if (!fs.accessSync(savePath)) {
      fs.mkdirSync(savePath, true)
    }
    
    // 在查询成功回调中调用下载
    const fileIndexesJson = JSON.stringify(result.items)
    const downloadResult = p2pFileTransfer.startDownloadFiles(
      'ipc_sweeper_robot',
      savePath,
      fileIndexesJson
    )
    
    if (downloadResult === 0) {
      L.i('P2PDemo', `开始下载 ${result.items.length} 个文件`)
    } else {
      L.e('P2PDemo', `下载启动失败: ${downloadResult}`)
    }
  }
  return 0
}

3.4 startDownloadStream

功能描述

以流式方式下载文件,适用于地图等需要实时处理的数据。数据通过监听器的 onStreamRecved 回调逐包返回。

函数签名

startDownloadStream(
  albumName: string,
  fileIndexes: string
): number

参数说明

参数 类型 必填 说明
albumName string 相册名称
fileIndexes string 文件索引数组的 JSON 字符串

返回值

类型 说明
number 调用结果:0=成功启动,其他值=失败

注意事项

  • 流式下载不保存到文件,数据在 onStreamRecved 回调中处理
  • 适用于需要实时处理的场景,如地图渲染
  • 数据包按顺序返回,需要自行组装

使用示例

const fileIndexesJson = JSON.stringify([
  { idx: 0, channel: 0, type: 2, filename: 'map.dat', /* ... */ }
])

const result = p2pFileTransfer.startDownloadStream('Maps', fileIndexesJson)
if (result === 0) {
  L.i('P2PDemo', '流式下载已启动')
}

3.5 destroy

功能描述

销毁文件传输实例,释放相关资源。在断开设备连接前应调用此方法。

函数签名

destroy(): void

参数说明

返回值

注意事项

  • 断开设备连接前必须先销毁文件传输实例
  • 销毁后实例不可再使用,需要重新创建

使用示例

// 销毁文件传输实例
p2pFileTransfer.destroy()

// 然后断开设备连接
ThingIPCSdk.getP2P().disconnect({ deviceId: 'device_abc123' }, () => {}, () => {})

4. ThingP2pFileTransListener 监听器回调

4.1 onSessionStatusChanged

功能描述

会话状态变化回调。当设备连接状态发生变化时触发,可用于监控连接状态。

函数签名

onSessionStatusChanged(sessionId: number, sessionStatus: number): number

参数说明

参数 类型 说明
sessionId number 会话 ID
sessionStatus number 会话状态(>0: 连接成功,<0: 断开/失败)

返回值

类型 说明
number 固定返回 0 或 sessionId

状态值说明

状态值 说明
> 0 连接成功,值为 sessionId
0 初始状态
< 0 连接断开或失败

使用示例

onSessionStatusChanged: (sessionId, sessionStatus) => {
  if (sessionStatus > 0) {
    L.i('P2PDemo', `连接成功,sessionId: ${sessionStatus}`)
  } else if (sessionStatus < 0) {
    L.e('P2PDemo', '连接断开')
  }
  return 0
}

4.2 onFileFinished

功能描述

文件传输完成回调。当单个文件上传或下载完成时触发。

函数签名

onFileFinished(
  event: number, 
  filename: string, 
  index: number, 
  errCode: number
): number

参数说明

参数 类型 说明
event number 事件类型(0: 下载, 2: 上传)
filename string 文件名
index number 文件索引
errCode number 错误码(0: 成功,其他值: 失败)

返回值

类型 说明
number 固定返回 0

使用示例

onFileFinished: (event, filename, index, errCode) => {
  if (event === 0) {
    L.i('P2PDemo', `文件下载完成: ${filename}, 结果: ${errCode === 0 ? '成功' : '失败'}`)
  } else if (event === 2) {
    L.i('P2PDemo', `文件上传完成: ${filename}`)
  }
  return 0
}

4.3 onProgress

功能描述

总体传输进度回调。用于显示整体传输进度。

函数签名

onProgress(event: number, progress: number): number

参数说明

参数 类型 说明
event number 事件类型(0: 下载, 2: 上传)
progress number 进度百分比(0-100)

返回值

类型 说明
number 固定返回 0

使用示例

onProgress: (event, progress) => {
  L.i('P2PDemo', `${event === 0 ? '下载' : '上传'}进度: ${progress}%`)
  return 0
}

4.4 onFileProgress

功能描述

单个文件传输进度回调。提供更细粒度的进度信息。

函数签名

onFileProgress(
  event: number, 
  progress: number, 
  filename: string
): number

参数说明

参数 类型 说明
event number 事件类型(0: 下载, 2: 上传)
progress number 进度百分比(0-100)
filename string 文件名

返回值

类型 说明
number 固定返回 0

使用示例

onFileProgress: (event, progress, filename) => {
  L.i('P2PDemo', `${filename} ${event === 0 ? '下载' : '上传'}进度: ${progress}%`)
  return 0
}

4.5 onP2pResponse

功能描述

P2P 响应回调。用于接收查询等命令的响应数据,这是接收文件索引查询结果的关键回调

函数签名

onP2pResponse(event: number, errCode: number, data: string): number

参数说明

参数 类型 说明
event number 事件类型(12: 查询文件索引)
errCode number 错误码(0: 成功,其他值: 失败)
data string 响应数据(JSON 字符串)

返回值

类型 说明
number 固定返回 0

事件类型说明

事件值 说明
12 查询文件索引响应

响应数据格式(event=12 时)

interface P2PAlbumFileIndexs {
  count: number          // 文件总数
  items: FileIndex[]     // 文件索引数组
}

注意事项

  • 这是接收查询文件索引结果的唯一回调
  • 建议在此回调中解析数据后直接调用下载方法
  • data 需要通过 JSON.parse() 解析

使用示例

onP2pResponse: (event, errCode, data) => {
  L.i('P2PDemo', `P2P 响应: event=${event}, errCode=${errCode}`)
  
  // 处理查询文件索引的响应
  if (event === 12) {
    if (errCode === 0 && data) {
      try {
        const result: P2PAlbumFileIndexs = JSON.parse(data)
        L.i('P2PDemo', `查询成功: count=${result.count}, items=${result.items.length}`)
        
        // 🔥 在此处调用下载方法
        const savePath = '/data/storage/el2/base/haps/entry/files'
        const fileIndexesJson = JSON.stringify(result.items)
        p2pFileTransfer.startDownloadFiles('Camera', savePath, fileIndexesJson)
        
      } catch (err) {
        L.e('P2PDemo', `解析失败: ${err}`)
      }
    } else {
      L.e('P2PDemo', `查询失败: ${errCode}`)
    }
  }
  
  return 0
}

4.6 onStreamRecved

功能描述

流式数据接收回调。用于地图等实时数据传输,数据逐包返回。

函数签名

onStreamRecved(
  event: number, 
  sessionId: number, 
  totalfiles: number, 
  fileIndex: number, 
  fileLength: number, 
  pack: ArrayBuffer, 
  packageLength: number, 
  packageType: number
): number

参数说明

参数 类型 说明
event number 事件类型
sessionId number 会话 ID
totalfiles number 总文件数
fileIndex number 当前文件索引
fileLength number 文件总长度
pack ArrayBuffer 数据包内容
packageLength number 数据包长度
packageType number 数据包类型(1: 新文件开始)

返回值

类型 说明
number 固定返回 0

数据包类型说明

类型值 说明
1 新文件开始(第一个数据包)
其他 后续数据包

使用示例

onStreamRecved: (event, sessionId, totalfiles, fileIndex, fileLength, pack, packageLength, packageType) => {
  if (packageType === 1) {
    L.i('P2PDemo', `开始接收新文件: 文件${fileIndex}/${totalfiles}`)
  }
  
  L.d('P2PDemo', `收到数据包: 长度=${packageLength}, 总长度=${fileLength}`)
  
  // 处理数据包...
  // 例如:保存到本地、实时渲染等
  
  return 0
}