English
English
简体中文
Contact Us
Register
Log In
layoutIndex

Memory Card Management for IPCs on iOS

Last Updated on : 2022-02-09 03:12:01download

Memory card management relies on data points (DPs). For more information about DPs, see DPs.

Status

Before memory card management, you must get the status of memory cards. If the device does not detect a memory card, you cannot proceed to the next step. If the memory card is abnormal, you need to format the memory card first.

enum TuyaSmartCameraSDCardStatus

Value Description
TuyaSmartCameraSDCardStatusNormal Memory card is normal working
TuyaSmartCameraSDCardStatusException Memory card is abnormal and needs to be formatted
TuyaSmartCameraSDCardStatusMemoryLow Memory card is low on memory
TuyaSmartCameraSDCardStatusFormatting Memory card is being formatted
TuyaSmartCameraSDCardStatusNone The device did not detect the memory card

Format

When the memory card is formatted, there are two cases according to the implementation of the camera manufacturer. The firmware implemented by some manufacturers will actively report the progress of formatting, and will also actively report the current capacity status after formatting is completed. However, there is a few manufacturers’ firmware that will not actively report, so it is necessary to periodically and actively query the formatting progress, when the progress reaches %100, and then actively query the current capacity status, you need to use the following interface to query the value of the function point:

- (void)valueForDP:(TuyaSmartCameraDPKey)dpName success:(TYSuccessID)success failure:(TYFailureError)failure;

Memory card recording

After a memory card is inserted into a Powered by Tuya (PBT) camera, the captured images can be saved to the memory card, and the video recording switch and mode can be set based on the SDK. There are two recording modes:

  • Continuous recording: The IPC will continuously record the collected audio and videos and save them to the memory card. When the capacity of the memory card is insufficient, the earliest recorded video data will be overwritten.
  • Event recording: The IPC will only start recording video when an alarm is triggered. The length of the video footage will change according to the type and duration of the event.

Example

Objective-C

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.dpManager valueForDP:TuyaSmartCameraSDCardStatusDPName success:^(id result) {
        [self checkStatus:[result integerValue]];
    } failure:^(NSError *error) {
        
    }];
}

- (void)changeToEventRecordMode {
    if (![self.dpManager isSupportDP:TuyaSmartCameraSDCardRecordDPName]) {
        return;
    }
    BOOL isRecordOn = [[self.dpManager valueForDP:TuyaSmartCameraSDCardRecordDPName] boolValue];
    if (isRecordOn && [self.dpManager isSupportDP:TuyaSmartCameraRecordModeDPName]) {
        TuyaSmartCameraRecordMode recordMode = [self.dpManager valueForDP:TuyaSmartCameraRecordModeDPName];
        if (recordMode == TuyaSmartCameraRecordModeAlways) {
            [self.dpManager setValue:TuyaSmartCameraRecordModeEvent forDP:TuyaSmartCameraRecordModeDPName success:^(id result) {
                NSLog(@"current recording mode is %@", result);
            } failure:^(NSError *error) {
								// Network error
            }];
        }
    }
}

- (void)checkStatus:(TuyaSmartCameraSDCardStatus)status {
    if (status == TuyaSmartCameraSDCardStatusNone) {
        return;
    }else if (status == TuyaSmartCameraSDCardStatusException) {
        [self formatAction];
    }else if (status == TuyaSmartCameraSDCardStatusFormatting) {
        [self handleFormatting];
    }else {
        [self getStorageInfo];
      	[self changeToEventRecordMode];
    }
}

- (void)formatAction {
    __weak typeof(self) weakSelf = self;
    [self.dpManager setValue:@(YES) forDP:TuyaSmartCameraSDCardFormatDPName success:^(id result) {
        [weakSelf handleFormatting];
    } failure:^(NSError *error) {
        // Network error
    }];
}

- (void)handleFormatting {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
	      // Query the formatting progress, because some manufacturers' devices will not automatically report the progress
        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) {
              	// After formatting successfully, query the capacity information of the device
                [self getStorageInfo];
            } else {
								// Formatting failed
            }
        });
    });
}

- (int)getFormatStatus {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    __block int status = -1;
    [self.dpManager valueForDP:TuyaSmartCameraSDCardFormatStateDPName success:^(id result) {
        status = [result intValue];
        dispatch_semaphore_signal(semaphore);
    } failure:^(NSError *error) {
        dispatch_semaphore_signal(semaphore);
    }];
		// timeout
    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:TuyaSmartCameraSDCardStorageDPName success:^(id result) {
        NSArray *components = [result componentsSeparatedByString:@"|"];
        if (components.count < 3) {
          	// Data invalid
            return;
        }
        weakSelf.total = [[components firstObject] integerValue];
        weakSelf.used = [[components objectAtIndex:1] integerValue];
        weakSelf.left = [[components lastObject] integerValue];
    } failure:^(NSError *error) {
        // Network error
    }];
}

Swift

override func viewDidLoad() {
    super.viewDidLoad()
    self.dpManager.value(forDP: .sdCardStatusDPName, success: { result in
        self.checkStatus(status: TuyaSmartCameraSDCardStatus(rawValue: result as! UInt)!)
    }) { _ in
        // Network error
    }
}

func checkStatus(status: TuyaSmartCameraSDCardStatus) {
    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
        // Network error
    }
}

func handleFormatting() {
    DispatchQueue.global().async {
        // Query the formatting progress, because some manufacturers' devices will not automatically report the progress
        let status = self.getFormatStatus()
        DispatchQueue.main.async {
            if status >= 0, status < 100 {
                self.handleFormatting()
            }else if status == 100 {
                // After formatting successfully, query the capacity information of the device
                self.getStorageInfo()
            }else {
                // Formatting failed
            }
        }
    }
}

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()
    }
    // timeout
    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 {
            // Data invalid
            return
        }
        let total = Int(components[0])
        let used = Int(components[1])
        let left = Int(components[2])
    }) { _ in
        // Network error
    }
}

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 == TuyaSmartCameraRecordMode.always.rawValue {
        self.dpManager.setValue(TuyaSmartCameraRecordMode.event.rawValue, forDP: .recordModeDPName, success: { result in
            print("current recording mode is ", result as! String)
        }) { _ in
            // Network error
        }
    }

}