存储卡管理

更新时间:2024-06-17 09:46:05下载pdf

存储卡管理通过设备功能(DP)实现,您可以在 IPC 常规控制 模块中查看设备功能常量。有关如何查询和控制设备功能,请参考智能生活 App SDK 设备控制

查询存储卡状态

DPName DPCode DPId 值说明
ThingSmartCameraSDCardStatusDPName sd_status 110 详情查看 ThingSmartCameraSDCardStatus 枚举说明

在开始管理存储卡或者进行存储卡视频回放前,您需要先查询存储卡的状态。如果设备未检测到存储卡,则无法进行下一步。如果存储卡异常,则需要先格式化存储卡。

ThingSmartCameraSDCardStatus 枚举

枚举值 说明
ThingSmartCameraSDCardStatusNormal 1,存储卡正常
ThingSmartCameraSDCardStatusException 2,存储卡异常,例如存储卡损坏或格式不对
ThingSmartCameraSDCardStatusMemoryLow 3,存储卡空间不足
ThingSmartCameraSDCardStatusFormatting 4,存储卡正在格式化
ThingSmartCameraSDCardStatusNone 5,无存储卡
ThingSmartCameraSDCardStatusLoading 7,存储卡在装载中,等状态上报

下发该 DP 不需要携带参数,设置为 null 值即可。

格式化存储卡

DPName DPCode DPId 值说明
ThingSmartCameraSDCardFormatDPName sd_format 111 -

在格式化存储卡的时候,根据 IPC 产品的具体实现,有两种情况:

  • 大部分 IPC 产品的固件中,会主动上报格式化的进度。格式化完成后,也会主动上报当前的容量状态。
  • 少部分 IPC 产品的固件中,不会主动上报格式化的进度。所以,您需要定时主动查询格式化的进度。当格式化进度达到 100 时,再查询存储卡的容量状态。

查询格式化进度

DPName DPCode DPId 值说明
ThingSmartCameraSDCardFormatStateDPName sd_format_state 117 数值范围:-20000 到 200000,正数为格式化进度

当进度达到 100 时,即格式化结束。可以再去查询存储卡容量。

查询存储卡容量

DPName DPCode DPId 值说明
ThingSmartCameraSDCardStorageDPName sd_storge 109 存储卡容量值返回字符串数据,格式为 总容量/已使用容量/空闲容量,单位为 KB

开启或关闭视频录制

DPName DPCode DPId 值说明
ThingSmartCameraSDCardRecordDPName record_switch 150 SD 卡录像开关
  • YES:打开
  • NO:关闭

修改视频录像模式

DPName DPCode DPId 值说明
ThingSmartCameraRecordModeDPName record_mode 151 SD 卡录像模式选择
  • 1:事件录像(检测到移动再录像到 SD 卡)
  • 2:连续录像

IPC 在插入存储卡后,可以将采集的影像录制保存在存储卡中。您可以通过 IPC SDK 设置视频录制开关和模式。

取值 说明
1 修改为事件录像模式。IPC 只会在触发侦测报警时,才会开始录制视频。视频的长短会根据事件类型和事件持续时间而变化。
2 修改为连续录像模式。IPC 会将采集到的音视频,连续不断地录制保存在存储卡中。存储卡的容量不足的时候,将会覆盖最早录制的视频数据。

示例代码

Objective-C

- (void)viewDidLoad {
    [super viewDidLoad];
    // 获取存储卡状态
    [self.dpManager valueForDP:ThingSmartCameraSDCardStatusDPName success:^(id result) {
        [self checkStatus:[result integerValue]];
    } failure:^(NSError *error) {
        
    }];
}

- (void)changeToEventRecordMode {
      // 判断摄像机是否支持存储卡录像
    if (![self.dpManager isSupportDP:ThingSmartCameraSDCardRecordDPName]) {
        return;
    }
    BOOL isRecordOn = [[self.dpManager valueForDP:ThingSmartCameraSDCardRecordDPName] boolValue];
      // 如果存储卡录像已经开启,并且支持录像模式设置
    if (isRecordOn && [self.dpManager isSupportDP:ThingSmartCameraRecordModeDPName]) {
        ThingSmartCameraRecordMode recordMode = [self.dpManager valueForDP:ThingSmartCameraRecordModeDPName];
          // 如果当前的录像模式是连续录像
        if (recordMode == ThingSmartCameraRecordModeAlways) {
              // 设置为事件录像模式
            [self.dpManager setValue:ThingSmartCameraRecordModeEvent forDP:ThingSmartCameraRecordModeDPName success:^(id result) {
                NSLog(@"当前的存储卡录像模式是:%@", result);
            } failure:^(NSError *error) {
                // 网络错误
            }];
        }
    }
}

- (void)checkStatus:(ThingSmartCameraSDCardStatus)status {
    if (status == ThingSmartCameraSDCardStatusNone) {
          // 未检测到存储卡
        return;
    }else if (status == ThingSmartCameraSDCardStatusException) {
          // 存储卡异常,开始格式化
        [self formatAction];
    }else if (status == ThingSmartCameraSDCardStatusFormatting) {
          // 存储卡正在格式化
        [self handleFormatting];
    }else {
          // 获取存储卡容量信息
        [self getStorageInfo];
          // 设置录像模式为事件录像
          [self changeToEventRecordMode];
    }
}

- (void)formatAction {
    __weak typeof(self) weakSelf = self;
    [self.dpManager setValue:@(YES) forDP:ThingSmartCameraSDCardFormatDPName success:^(id result) {
          // 开始格式化成功,监听格式化进度
        [weakSelf handleFormatting];
    } failure:^(NSError *error) {
        // 网络错误
    }];
}

- (void)handleFormatting {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          // 主动查询格式化进度,因为部分厂商的设备不会自动上报进度
        int status = [self getFormatStatus];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (status >= 0 && status < 100) {
                [self performSelector:@selector(handleFormatting) withObject:nil afterDelay:2.0];
            } else if (status == 100) {
                  // 格式化成功后,主动获取设备的容量信息
                [self getStorageInfo];
            } else {
                                //格式化失败
            }
        });
    });
}

- (int)getFormatStatus {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    __block int status = -1;
    [self.dpManager valueForDP:ThingSmartCameraSDCardFormatStateDPName success:^(id result) {
        status = [result intValue];
        dispatch_semaphore_signal(semaphore);
    } failure:^(NSError *error) {
        dispatch_semaphore_signal(semaphore);
    }];
    //大SD卡格式化上报比较慢,超时时间设置5分钟
    dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 300.0f * NSEC_PER_SEC));
    return status;
}

- (void)getStorageInfo {
    __weak typeof(self) weakSelf = self;
    [self.dpManager valueForDP:ThingSmartCameraSDCardStorageDPName success:^(id result) {
        NSArray *components = [result componentsSeparatedByString:@"|"];
        if (components.count < 3) {
              // 数据异常
            return;
        }
          // 总容量
        weakSelf.total = [[components firstObject] integerValue];
          // 已使用
        weakSelf.used = [[components objectAtIndex:1] integerValue];
          // 空闲
        weakSelf.left = [[components lastObject] integerValue];
    } failure:^(NSError *error) {
        // 网络错误
    }];
}

Swift

override func viewDidLoad() {
    super.viewDidLoad()
    // 获取存储卡状态
    self.dpManager.value(forDP: .sdCardStatusDPName, success: { result in
        self.checkStatus(status: ThingSmartCameraSDCardStatus(rawValue: result as! UInt)!)
    }) { _ in
        // 网络错误
    }
}

func checkStatus(status: ThingSmartCameraSDCardStatus) {
    switch status {
    case .exception:
        // 存储卡异常,开始格式化
        self.formatSDCard()
        break
    case .formatting:
        // 存储卡正在格式化
        self.handleFormatting()
        break
    case .none:
        // 未检测到存储卡
        return
    default:
        // 获取存储卡容量信息
        self.getStorageInfo()
        // 设置录像模式为事件录像
        self.changeToEventRecordMode()
    }
}

func formatSDCard() {
    self.dpManager.setValue(true, forDP: .sdCardFormatDPName, success: { [weak self] _ in
        // 开始格式化成功,监听格式化进度
        self?.handleFormatting()
    }) { _ in
        // 网络错误
    }
}

func handleFormatting() {
    DispatchQueue.global().async {
        // 主动查询格式化进度,因为部分厂商的设备不会自动上报进度
        let status = self.getFormatStatus()
        DispatchQueue.main.async {
            if status >= 0, status < 100 {
                self.handleFormatting()
            }else if status == 100 {
                // 格式化成功后,主动获取设备的容量信息
                self.getStorageInfo()
            }else {
                // 格式化失败
            }
        }
    }
}

func getFormatStatus() -> Int {
    let semaphore = DispatchSemaphore.init(value: 0)
    var status = -1
    self.dpManager.value(forDP: .sdCardFormatStateDPName, success: { result in
        status = result as! Int
        semaphore.signal()
    }) { _ in
        semaphore.signal()
    }
    // 大SD卡格式化上报比较慢,超时时间设置5分钟
    let _ = semaphore.wait(timeout: DispatchTime(uptimeNanoseconds: 300 * NSEC_PER_SEC))
    return status
}

func getStorageInfo() {
    self.dpManager.value(forDP: .sdCardStorageDPName, success: { result in
        let components = (result as! String).split(separator: "|")
        guard components.count == 3 else {
            // 数据异常
            return
        }
        // 总容量
        let total = Int(components[0])
        // 已使用
        let used = Int(components[1])
        // 空闲
        let left = Int(components[2])
    }) { _ in
        // 网络错误
    }
}

func changeToEventRecordMode() {
    // 判断摄像机是否支持存储卡录像
    guard self.dpManager.isSupportDP(.sdCardRecordDPName) else {
        return
    }
    let isRecordOn = self.dpManager.value(forDP: .sdCardRecordDPName) as! Bool
    // 如果存储卡录像已经开启,并且支持录像模式设置
    guard self.dpManager.isSupportDP(.recordModeDPName), isRecordOn else {
        return
    }

    let recordMode = self.dpManager.value(forDP: .recordModeDPName) as! String
    // 如果当前的录像模式是连续录像
    if recordMode == ThingSmartCameraRecordMode.always.rawValue {
        // 设置为事件录像模式
        self.dpManager.setValue(ThingSmartCameraRecordMode.event.rawValue, forDP: .recordModeDPName, success: { result in
            print("当前的录像模式是: ", result as! String)
        }) { _ in
            // 网络错误
        }
    }

}