收发命令
命令收发是在一条已建立的 TiRTC 连接上发送业务控制数据。它适合表达“让对端做一件事”,例如请求设备状态、下发控制指令、回传处理结果。
命令通道是对等的:发送端和接收端可以是客户端,也可以是设备端。只要两端已经建立连接,Android、iOS、Flutter 和 C 侧拿到的连接对象都可以发送或接收命令。
它和收发流消息不同:流消息附着在某一条 stream_id 上;命令消息不依附音视频流,更适合控制指令和业务状态机。
先约定 cmdw
cmdw 是 command word 的缩写,可以理解成“命令字”:一个由你和对端共同约定的 32 位无符号整数。TiRTC 只负责把这个值和 payload 原样送到对端,不解释它的业务含义。 cmdw 的原始取值范围是闭区间 0x10000 到 0xFFFFFFFF。
下文用这一组命令字演示请求和响应:
cmdw | 作用 |
|---|---|
0x10000 | 请求设备状态 |
0x10002 | 返回设备状态结果 |
下面示例统一使用 UTF-8 文本 payload。真实业务里可以换成 JSON、Protobuf 或你自己的二进制格式,只要两端约定一致。
发送端:发送请求命令
发送端只需要拿到当前连接对象,调用对应平台的发送接口,把 cmdw 和 payload 发出去。
import 'dart:convert';
import 'dart:typed_data';
const int cmdwGetDeviceStatus = 0x10000;
final Uint8List payload = Uint8List.fromList(utf8.encode('status?'));
final int code = conn.sendCommand(commandId: cmdwGetDeviceStatus, data: payload);
if (code != 0) {
debugPrint('send command failed: $code');
}private const val CMDW_GET_DEVICE_STATUS = 0x10000L
val payload = "status?".encodeToByteArray()
val code = conn.sendCommand(command = CMDW_GET_DEVICE_STATUS, data = payload)
if (code != 0) {
Log.w("TiRTC", "send command failed code=$code")
}private let CMDW_GET_DEVICE_STATUS: UInt32 = 0x10000
let payload = Data("status?".utf8)
let code = conn.send(commandId: CMDW_GET_DEVICE_STATUS, data: payload)
if code != 0 {
print("send command failed: \(code)")
}#include <stdint.h>
#include <string.h>
static const uint32_t CMDW_GET_DEVICE_STATUS = 0x10000;
int request_device_status(tirtc_conn_t hconn)
{
const char *payload = "status?";
return TiRtcSendCommand(
hconn,
CMDW_GET_DEVICE_STATUS,
payload,
(uint32_t)strlen(payload));
}接收端:处理命令并返回结果
接收端在命令回调里判断 cmdw,解析 payload,然后按业务约定决定是否回发另一条命令。下面示例收到 0x10000 后,用 0x10002 返回 device-ok。
import 'dart:convert';
import 'dart:typed_data';
const int cmdwGetDeviceStatus = 0x10000;
const int cmdwDeviceStatusResult = 0x10002;
conn.onCommand = (int commandId, Uint8List data) {
if (commandId != cmdwGetDeviceStatus) return;
final String request = utf8.decode(data);
if (request != 'status?') return;
final Uint8List response = Uint8List.fromList(utf8.encode('device-ok'));
final int code = conn.sendCommand(commandId: cmdwDeviceStatusResult, data: response);
if (code != 0) {
debugPrint('send command response failed: $code');
}
};private const val CMDW_GET_DEVICE_STATUS = 0x10000L
private const val CMDW_DEVICE_STATUS_RESULT = 0x10002L
conn.onCommand = TiRtcConnCommandListener { command, data ->
if (command != CMDW_GET_DEVICE_STATUS) return@TiRtcConnCommandListener
val request = data.decodeToString()
if (request != "status?") return@TiRtcConnCommandListener
val response = "device-ok".encodeToByteArray()
val code = conn.sendCommand(command = CMDW_DEVICE_STATUS_RESULT, data = response)
if (code != 0) {
Log.w("TiRTC", "send command response failed code=$code")
}
}private let CMDW_GET_DEVICE_STATUS: UInt32 = 0x10000
private let CMDW_DEVICE_STATUS_RESULT: UInt32 = 0x10002
func conn(_ conn: TiRtcConn, didReceiveCommand commandId: UInt32, data: Data) {
guard commandId == CMDW_GET_DEVICE_STATUS else { return }
let request = String(decoding: data, as: UTF8.self)
guard request == "status?" else { return }
let response = Data("device-ok".utf8)
let code = conn.send(commandId: CMDW_DEVICE_STATUS_RESULT, data: response)
if code != 0 {
print("send command response failed: \(code)")
}
}#include <stdint.h>
#include <string.h>
static const uint32_t CMDW_GET_DEVICE_STATUS = 0x10000;
static const uint32_t CMDW_DEVICE_STATUS_RESULT = 0x10002;
static void on_command(tirtc_conn_t hconn, uint32_t cmdw, const void *data, uint32_t len)
{
const char *request = "status?";
if (cmdw != CMDW_GET_DEVICE_STATUS ||
data == NULL ||
len != (uint32_t)strlen(request) ||
memcmp(data, request, len) != 0) {
return;
}
const char *response = "device-ok";
TiRtcSendCommand(
hconn,
CMDW_DEVICE_STATUS_RESULT,
response,
(uint32_t)strlen(response));
}如果这条命令不需要响应,接收端处理完后可以直接结束,不必再回发另一条命令。需要请求/响应配对、超时重试或乱序应答时,在业务协议里继续定义序号或使用设备端 C SDK 的命令字辅助宏。
常见问题
发送成功,但对端没有进入预期分支
先检查这三项:
- 双端比较的是不是同一个原始
cmdw,例如都使用0x10000。 - payload 编码是否一致,例如两端都按 UTF-8 文本处理。
- 发送使用的是否是当前这条连接对应的
conn或hconn。
cmdw 和客户端 SDK 的 commandId 是不是一回事
是同一个原始值。Flutter 和 iOS 的公开参数名叫 commandId,Android 叫 command,设备端 C SDK 叫 cmdw。写业务协议时建议统一记录为 cmdw,实现时按各平台真实 API 名称传入。
什么时候改用流消息
如果你的数据需要跟某一条 stream_id 一起理解,而不是表达一个明确的业务命令,改看收发流消息。