控制协议
KY_SendIOCtrlWithChannel
- 功能描述:
- 向已连接的设备发送自定义的控制指令(Command)和数据。这是实现 APP 对设备进行远程控制的核心接口。
接口定义
- (void)KY_SendIOCtrlWithChannel:(NSInteger)channel
type:(ENUM_AVIOCTRL_MSGTYPE)type
data:(NSData * _Nonnull)data;
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| channel | int | 设备连线的通道号,默认值为 0。 |
| type | ENUM_AVIOCTRL_MSGTYPE | 控制指令的类型(Command ID)。开发者需要与设备端约定好自定义指令的值,或使用 SDK 预定义的指令。相关定义通常在 `AVIOCTRLDEFs.h` 头文件中。 |
| data | NSData | 要发送给设备的具体指令数据。通常需要将一个自定义的 C 结构体转换为 `NSData` 对象进行传输。 |
代码示例
// 假设 IOTYPE_USER_IPCAM_GET_PLAYBACK_REQ 是一个自定义的指令类型
// data 是一个包含了播放请求参数的 NSData 对象
[self.camera KY_SendIOCtrlWithChannel:0
type:IOTYPE_USER_IPCAM_GET_PLAYBACK_REQ
data:data];
协议封装示例
下面以“APP 获取设备端灯控开关状态”为例,详细说明如何定义协议、封装数据并发送,以及如何接收和解析设备的响应。
1. 定义协议及结构体
首先,需要在 APP 端和设备端共同约定好指令 ID 和数据结构体的格式。
// 1. 定义指令 ID (Command ID)
// APP -> 设备:发送获取灯控状态的请求
#define IOTYPE_GET_LED_REQ 0x30000001
// 设备 -> APP:回复灯控状态
#define IOTYPE_GET_LED_RESP 0x30000002
// 2. 定义与指令对应的数据结构体
// (a) APP 发送给设备的请求结构体
typedef struct {
unsigned int channel; // 当前通道号,通常填 0
unsigned char reserved[4]; // 预留字段,用于对齐或未来扩展
} SMsgAVIoctrlGetLedReq;
// (b) 设备回复给 APP 的响应结构体
typedef struct {
int result; // 执行结果:0 表示成功,其他值表示失败
unsigned char isOnOff; // 灯的开关状态:0 表示关闭,1 表示开启
unsigned char reserved[3]; // 预留字段
} SMsgAVIoctrlGetLedResp;
2. 结构体封装与发送 (APP 端)
APP 端需要将请求结构体打包成 `NSData` 对象,然后通过 `KY_SendIOCtrlWithChannel` 接口发送。
// 假设 self.camera 是已连接的设备实例
// (a) 准备请求数据
SMsgAVIoctrlGetLedReq reqData;
reqData.channel = 0; // 设置通道号
memset(reqData.reserved, 0, sizeof(reqData.reserved)); // 初始化预留字段
// (b) 将结构体转换为 NSData
NSData *sendData = [NSData dataWithBytes:&reqData length:sizeof(SMsgAVIoctrlGetLedReq)];
// (c) 发送指令
[self.camera KY_SendIOCtrlWithChannel:0
type:IOTYPE_GET_LED_REQ
data:sendData];
NSLog(@"已发送获取灯控状态的请求...");
3. 数据接收与解析 (APP 端)
设备端收到指令并处理后,会返回响应数据。APP 端需要通过 delegate 回调来接收这些数据,并解析成相应的结构体。
通常,你需要实现类似 `didReceiveIOCtrlData:withType:onChannel:` 这样的 delegate 方法(具体方法名请参考 SDK 文档)。
// 在你的 ViewController 或 Camera 管理类中,实现 delegate 方法
- (void)didReceiveIOCtrlData:(NSData *)data withType:(ENUM_AVIOCTRL_MSGTYPE)type onChannel:(NSInteger)channel {
// 根据指令类型判断是哪种响应
if (type == IOTYPE_GET_LED_RESP) {
NSLog(@"收到灯控状态的响应");
// (a) 检查数据长度是否匹配
if (data.length != sizeof(SMsgAVIoctrlGetLedResp)) {
NSLog(@"响应数据长度不正确!");
return;
}
// (b) 将 NSData 转换回结构体
SMsgAVIoctrlGetLedResp *respData = (SMsgAVIoctrlGetLedResp *)data.bytes;
// (c) 解析数据
int result = respData->result;
BOOL isLedOn = (respData->isOnOff == 1);
if (result == 0) {
NSLog(@"获取灯控状态成功: %@", isLedOn ? @"开启" : @"关闭");
// 在这里更新 UI,例如:self.ledStatusLabel.text = isLedOn ? @"开启" : @"关闭";
} else {
NSLog(@"获取灯控状态失败,错误码: %d", result);
}
}
// 可以在这里处理其他指令的响应...
}
