涂鸦 IP 摄像机移动应用 SDK 开发入门教程 iOS 版

更新时间:2023-06-05 02:49:54下载pdf

涂鸦智能 iOS 版摄像机(IP Camera,简称 IPC)SDK 是基于智能生活 App SDK 开发而成。通过移动应用控制物理网设备是常见的使用场景,但由于设备的品类丰富,增大了应用开发难度。因此 智能生活 App SDK 提供了常见的垂直品类 SDK,例如 IPC SDK,将网络摄像机设备特有的功能抽离,提供了与其通讯的接口封装,加速应用开发过程。

您可以通过本教程,在一小时内快速开发一款自己的 IoT App,并实现如下功能:

  • 通过 App 连接一个智能摄像头。
  • 预览摄像机实时采集的影像。
  • 播放摄像机存储卡中录制的视频。
  • 手机端录制摄像机采集的影像。

您可以单击下方按钮下载 Sample 查看本教程中的示例代码。本次教程按功能模块进行分类,您可以快速找到对应的代码参考学习。

前往 App 开发平台 点击查看 GitHub Sample

效果展示

学习完本教程,结合一定的面板开发您可以创建一个类似以下 iOS App 的 Demo。

涂鸦 IP 摄像机移动应用 SDK 开发入门教程 iOS 版

准备工作

在您开始本教程前,请先确保您已经 :

  1. 在涂鸦 IoT 平台,注册账号并创建 App 应用,拿到 SDK 的 AppKey,AppSecret。参考 准备工作

    由于 IPC SDK 依赖于 智能生活 App SDK,您需要首先实现如创建账号、添加家庭的操作后才能借助 IPC SDK 实现摄像机相关功能。详情请参考 智能生活 App SDK 快速入门教程

  2. 准备一个涂鸦赋能的智能摄像机产品,本教程以摄像头为例。关于如何获取涂鸦赋能的产品,可访问 涂鸦智选
  3. 使用 CocoaPods 将涂鸦智能生活 App SDK 和 IPC SDK 集成到您的项目中。参考 快速集成

设备配网

由涂鸦赋能的智能摄像机支持智能生活 App SDK 中的所有 配网方式,例如 Wi-Fi 热点配网和蓝牙配网等。此外,涂鸦为 IPC 设备提供了独有的扫描二维码配网功能。

获取 Token

和 Wi-Fi 快连和 Wi-Fi 热点模式类似,开始配网之前,SDK 需要在手机已联网的状态下从涂鸦 获取配网 Token,然后才可以开始配网。

配网 Token 的有效期为 10 分钟,且配置成功后就会失效,再次配网需要重新获取。获取 Token 需要上传当前的 homeId,因此您需要确保用户处于登录状态,并至少创建了一个家庭。

[[ThingSmartActivator sharedInstance] getTokenWithHomeId:homeId
                                                success:^(NSString *token) {
                                            // NSLog(@"getToken success: %@", token);
                                        // you could start ConfigWi-Fi now
                                        } failure:^(NSError *error) {
                                        //NSLog(@"getToken failure: %@", error.localizedDescription);
                                        }
];

iOS 版本适配

iOS 14 版本适配

从 iOS 14 版本开始,在设备配网、局域网本地控制时会触发 本地网络 权限弹窗。

  • 如果用户单击了允许,App 才能够向本地局域网发送数据。
  • 如果用户单击了拒绝,将无法使用相关功能。

目前苹果没有提供任何 API 对此权限进行判断,建议您在相关功能无法正常使用时提示、引导用户检查 系统设置 中的 App 设置,确认用户手机是否开启了 本地网络 权限。

iOS 13 版本适配

从 iOS 13 版本开始,如果用户没有开启地理位置权限,在已开启 Wi-Fi 权限的前提下,[[ThingSmartActivator sharedInstance] currentWifiSSID] 将查询不到有效的 Wi-Fi SSID 或 BSSID。在此情况下,iOS 会返回下列默认值:

  • SSID:WLAN 或 Wi-Fi,针对中国大陆地区则是 WLAN
  • BSSID:“00:00:00:00:00:00”

生成配网二维码

获取到配网 Token 后,您还需要当前 Wi-Fi 的名称(SSID)和密码,通过下面的方式拼接成字符串,然后根据这个字符串生成一个二维码图片。

NSDictionary *dictionary = @{
                            @"s": self.ssid,
                            @"p": self.pwd,
                            @"t": self.token
                            };
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
self.wifiJsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

生成二维码的功能需要您自己实现,也可参考 Original GitHub Sample 中的代码。

上述代码中的 key [s p t] 为固定值,不可随意设置。否则云端将无法准确解析配网信息。

开始配网

开始配网前,请确保设备处于待配网状态。操作方法可参考设备的使用说明书。

在成功生成二维码后,引导用户将二维码对准摄像头,捕捉到二维码信息后会发出提示音。开始配网操作后,SDK 会持续广播配网信息,直到配网成功或是超时才停止。

调用 配网接口,需要提供路由器的 Wi-Fi SSID、密码、从云端获取的 Token 等。

[ThingSmartActivator sharedInstance].delegate = self;
[[ThingSmartActivator sharedInstance] startConfigWiFi:TYActivatorModeQRCode ssid:ssid password:password token:token timeout:100];

timeout 单位为秒,默认为 100,您可以设置为任意值。但不建议将此值设置得过小,否则将影响配网结果。

监听配网结果

开始配网后,您需要实现 ThingSmartActivatorDelegate 协议,以监听配网结果的回调。

@interface xxxViewController () <ThingSmartActivatorDelegate>
- (void)activator:(ThingSmartActivator *)activator didReceiveDevice:(ThingSmartDeviceModel *)deviceModel error:(NSError *)error {
    if (deviceModel && error == nil) {
            //success
            // NSLog(@"connected success: %@", deviceModel.name);
    }

    if (error) {
        //fail
    }

// stop config
}

停止配网

如果需要中途取消配网,如离开配网页面,或配网完成,请调用 停止配网 接口。

[ThingSmartActivator sharedInstance].delegate = nil;
[[ThingSmartActivator sharedInstance] stopConfigWi-Fi];

视频实时预览(视频直播)

IPC SDK 提供智能摄像机的实时视频播放、设备存储卡录像播放、对当前正在播放的视频截图、录制视频、与摄像机实时通话等基础能力。

SDK 开发时,页面内存由您控制,请保证页面正常销毁,避免内存泄漏问题。如果页面没有释放,则会一直占据资源。

第一步:对象初始化

您需要首先初始化一个 ThingSmartCameraType 对象。该对象用于读取智能摄像机设备的相关属性和方法。

初始化后,您可以直接通过该对象的 videoView 属性获取视频的渲染页。

//初始化设备
self.device = [ThingSmartDevice deviceWithDeviceId:devId];

// delegate: ThingSmartCameraDelegate 用于监听 P2P 通道连接状态
self.cameraType = [ThingSmartCameraFactory cameraWithP2PType:@(self.device.deviceModel.p2pType) deviceId:self.device.deviceModel.devId delegate:self];

//初始化视频预览页面
self.videoView = self.cameraType.videoView;

建议不要为一个设备同时创建两个 ThingSmartCameraType 对象,否则会导致资源错误释放出现异常情况。

第二步:连接 P2P 通道

初始化 ThingSmartCameraType对象后,您需要先连接 P2P (Peer-to-peer,对等)通道。P2P 的连接状态需要您自行维护。

开始连接 P2P 通道,参数 ThingSmartCameraConnectMode 可以指定优先选择的连接模式,是通过局域网还是公网来连接。如果指定局域网连接优先,但是 App 和设备没有在同一个局域网内建立 TCP 连接,或者设备不支持局域网连接优先,SDK 会自动使用外网连接模式。

  • 建立通道

    [self.cameraType connectWithMode:ThingSmartCameraConnectAuto];
    
  • 断开通道

    在关闭通道或离开当前页面时,您需要调用接口关闭通道。

    [self.cameraType disConnect];
    
  • 状态监听

    若您需要在过程中监听通道的连接和断开,需要实现下面两个代理ThingSmartCameraDelegate 中的事件。

    - (void)cameraInitFailed:(ThingSmartCameraErrorCode)errorCode {
    //camera 初始化失败,请查看具体错误码
    }
    - (void)cameraDidConnected:(id<ThingSmartCameraType>)camera {
        //...
    }
    
    // 该方法只有被动断开时才会调用,如网络环境比较差,或者设备主动断开连接
    - (void)cameraDisconnected:(id<ThingSmartCameraType>)camera specificErrorCode:(NSInteger)errorCode {
        //...
    }
    

errorCode 为 -3 或 -105,请根据业务需要进行重连,建议只进行一次重连

第三步:预览实时视频

在建立通道后,您就可以预览在线视频了。

  • 开始预览

    [self.cameraType startPreview];
    
  • 结束预览

    [self.cameraType stopPreview];
    
  • 状态监听

    - (void)cameraDidBeginPreview:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidStopPreview:(id<ThingSmartCameraType>)camera {
    
    }
    

视频录制与实时对讲

在预览实时视频的同时,您还可以对录制在线视频或通过摄像机实时对讲。更多接口的使用说明,可参考 音视频功能

录制的视频会自动保存至相册,因此需要添加相关应用权限:

<key>NSMicrophoneUsageDescription</key>
<string>应用想访问您的麦克风,以便使用摄像机对讲功能</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>应用想访问您的相册,以便录制视频和保存图片</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>应用想访问您的相册,以便录制视频和保存图片</string>
  • 开始录制或对讲

    [self.cameraType startTalk];
    [self.cameraType startRecord];
    
  • 结束录制或对讲

    [self.cameraType stopTalk];
    [self.cameraType stopRecord];
    
  • 监听状态

    通过实现代理事件监听录制和实时对讲的状态。

    - (void)cameraDidBeginTalk:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidStopTalk:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidStartRecord:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidStopRecord:(id<ThingSmartCameraType>)camera {
    
    }
    

回放历史视频

设备在存储卡中保存视频录像后,可以通过 IPC SDK 在 App 端播放视频录像。

和视频预览一样,在开始回放前,您需要先连接上 P2P 通道。

IPC SDK 支持以天为单位查看和播放视频录像,并且提供查询某年某月中,哪几天保存有视频录像,以便于用户查看。查询结果通过 ThingSmartCameraDelegate 中的代理方法返回。

设备端保存在存储卡中的视频片段,最长为 10 分钟一段,最短为 10 秒钟一段。有关存储卡的录制功能和相关设置,请参考 存储卡功能

查询视频列表

您需要监听代理 ThingSmartCameraDelegate 中的相关方法来查询返回结果。

第一步:查询特定月份保存过视频的日期

  • 方法请求

    [self.cameraType queryRecordDaysWithYear:2021 month:8];
    
  • 监听回调

    - (void)camera:(id<ThingSmartCameraType>)camera didReceiveRecordDayQueryData:(NSArray<NSNumber *> *)days {
    //   days    有视频录像的日期数组,如@[@(1), @(2)] 表示查询的当月的 1、2 号有视频录像,失败则返回空数组
    }
    

第二步:查询特定日期已保存的视频

您可以根据上一步返回的日期查询当天的视频信息列表。

  • 方法请求

    [self.cameraType queryRecordTimeSliceWithYear:2021 month:8 day:30];
    
  • 监听回调

    - (void)camera:(id<ThingSmartCameraType>)camera didReceiveTimeSliceQueryData:(NSArray<NSDictionary *> *)timeSlices {
    //...
    }
    

    timeSlices 字段不会直接返回视频数据本身。字典中存放的是每段视频的起止时间。具体结构如下:

    @{
        @"kThingSmartPlaybackPeriodStartDate" : NSDate   视频片段开始时间
        @"kThingSmartPlaybackPeriodStopDate" :  NSDate   视频片段结束时间
        @"kThingSmartPlaybackPeriodStartTime" : NSNumber 视频片段开始时间的 Unix 时间戳
        @"kThingSmartPlaybackPeriodStopTime" :  NSNumber 视频片段结束时间的 Unix 时间戳
    }
    

播放视频

成功查询到某天中的视频录像片段后,就可以开始播放录像视频了。

在以下场景中,您需要重新 查询当天的视频录像片段,避免出现播放异常:

  • 停止播放视频录像片段后,再实时播放视频。
  • 断开 P2P 连接,重新连接上 P2P 通道后。
  • 初始化播放页

    //初始化设备
    self.device = [ThingSmartDevice deviceWithDeviceId:devId];
    
    // delegate: ThingSmartCameraDelegate 用于监听 P2P 通道连接状态
    self.cameraType = [ThingSmartCameraFactory cameraWithP2PType:@(self.device.deviceModel.p2pType) deviceId:self.device.deviceModel.devId delegate:self];
    
    //初始化视频预览页面
    self.videoView = self.cameraType.videoView;
    
  • 开始播放

    [self.cameraType startPlayback:playTime startTime:startTime stopTime:stopTime];
    

    该方法的三个参数均为时间戳:

    • playTime 为播放的初始帧时间,可以与startTime 设置为同一值。
    • startTime 为播放的开始时间,为上一步查询的 timeSlices 数组项中 kThingSmartPlaybackPeriodStartTime 相对应的值。
    • stopTime 为播放的结束时间,为上一步查询的 timeSlices 数组项中 kThingSmartPlaybackPeriodStopTime 相对应的值。
  • 暂停播放

    [self.cameraType pausePlayback];
    
  • 继续播放

    [self.cameraType resumePlayback];
    
  • 停止播放

    [self.cameraType stopRecord];
    
  • 监听回调(ThingSmartCameraDelegate

    - (void)cameraDidBeginPlayback:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidPausePlayback:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidResumePlayback:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraDidStopPlayback:(id<ThingSmartCameraType>)camera {
    
    }
    
    - (void)cameraPlaybackDidFinished:(id<ThingSmartCameraType>)camera {
    
    }
    

    pausePlaybackstopPlayback都能达到停止播放视频的目的,它们之间的区别和联系是:

    • 调用stopPlayback后,无法调用resumePlayback来恢复播放。停止播放后,如果想要继续之前的进度开始播放,那么必须保存停止播放时,最后一帧视频的时间戳,以及播放的视频录像的时间片段,以重新调用 startPlayback 方法来继续播放。
    • 在成功查询到视频录像片段时间数据后,无论是正在播放录像视频,还是暂停播放,都可以直接调用 startPlayback 重新播放另一个视频录像片段,而不必先调用 stopPlayback 停止播放。

退出登录

退出登录时,请您务必调用:

[ThingSmartCameraFactory userDidLogOut];

相关概念

涂鸦智能摄像机的视频录像分为 连续录像事件录像

  • 连续录像:视频录像会是 10 分钟一个片段,且所有视频片段是连续的,但是如果中间有停止过视频录像,那么连续录像模式下的视频片段间也可能会有间隔。

    如果某天的视频录像片段是连续的,那么播放录像时,会自动播放下一段。也就是说,即使调用开始播放接口,传入的是当天第一个视频片段的时间点,视频也会一直播放到当天最后一个视频片段的最后一帧视频,才会回调视频播放结束的代理方法。

  • 事件录像:每个录像片段长度不等,且片段间的间隔时间也长短不一。

    如果某天的视频录像片段是不连续的,即视频录像片段 A 结束后隔了一段时间才有视频录像片段 B,在播放到断开的地方(即播放到视频片段 A 的最后一帧),视频流会自动停止。

下一步

IPC SDK 还提供了更多功能,您可以根据 Sample 工程和 IPC SDK 文档了解如何构建 App。