Memory Card Management

Last Updated on : 2024-06-27 09:23:57download

Memory card management is implemented using a data point (DP) that can be accessed from the camera control module. For information about DP query and control, see Device Control in the Smart Life App SDK.

Query memory card status

DPName DPCode DPId Description
ThingSmartCameraSDCardStatusDPName sd_status 110 See the ThingSmartCameraSDCardStatus enumeration description.

Before managing the memory card or playing videos from it, check its status. If the device does not detect a memory card, you cannot proceed to the next step. If there is an issue with the memory card, format it.

ThingSmartCameraSDCardStatus enum

Enum value Description
ThingSmartCameraSDCardStatusNormal 1: The memory card works fine.
ThingSmartCameraSDCardStatusException 2: The memory card has an anomaly, such as damage or an incorrect format.
ThingSmartCameraSDCardStatusMemoryLow 3: The memory card has insufficient space.
ThingSmartCameraSDCardStatusFormatting 4: The memory card is being formatted.
ThingSmartCameraSDCardStatusNone 5: No memory card is detected.
ThingSmartCameraSDCardStatusLoading 7: The memory card is loading. Wait for status reporting.

When sending this DP command to the device, set the parameter to null because it is unnecessary.

Format memory card

DPName DPCode DPId Description
ThingSmartCameraSDCardFormatDPName sd_format 111 -

When formatting the memory card, two scenarios are possible depending on the camera features.

  • Most cameras’ firmware proactively reports the formatting progress. After formatting, it automatically reports the current capacity.
  • Some cameras’ firmware does not proactively report the formatting progress. Therefore, you need to regularly check the formatting progress. When the formatting progress reaches 100, check the memory card capacity.

Check formatting progress

DPName DPCode DPId Description
ThingSmartCameraSDCardFormatStateDPName sd_format_state 117 Valid values range from -20,000 to 200,000. Positive numbers indicate formatting progress.

When the formatting progress reaches 100, you can check the memory card capacity.

Query memory card capacity

DPName DPCode DPId Description
ThingSmartCameraSDCardStorageDPName sd_storge 109 The memory card capacity is represented as a string in the format of total/used/free, measured in KB.

Turn on/off recording

DPName DPCode DPId Description
ThingSmartCameraSDCardRecordDPName record_switch 150 Enable or disable recording to the memory card.
  • YES: Enable
  • NO: Disable

Modify recording mode

DPName DPCode DPId Description
ThingSmartCameraRecordModeDPName record_mode 151 The mode of recording to the memory card.
  • 1: Event recording. Record to the memory card when motion is detected.
  • 2: Continuous recording.

The camera can record and save the captured audio and video to the installed memory card. You can use the Smart Camera SDK to enable or disable video recording and set the mode.

Value Description
1 Change to event recording mode. The camera starts recording only when a detection alert is triggered. The video length varies by the type and duration of the event.
2 Change to continuous recording mode. The camera continuously records and saves the captured audio and video to the memory card. When the storage is full, it will overwrite the oldest video recordings.

Example

Objective-C

- (void)viewDidLoad {
    [super viewDidLoad];
    // Get the memory card status
    [self.dpManager valueForDP:ThingSmartCameraSDCardStatusDPName success:^(id result) {
        [self checkStatus:[result integerValue]];
    } failure:^(NSError *error) {

    }];
}

- (void)changeToEventRecordMode {
      // Determine if the camera supports recording to a memory card.
    if (![self.dpManager isSupportDP:ThingSmartCameraSDCardRecordDPName]) {
        return;
    }
    BOOL isRecordOn = [[self.dpManager valueForDP:ThingSmartCameraSDCardRecordDPName] boolValue];
      // If the camera has memory card recording enabled and supports recording mode settings.
    if (isRecordOn && [self.dpManager isSupportDP:ThingSmartCameraRecordModeDPName]) {
        ThingSmartCameraRecordMode recordMode = [self.dpManager valueForDP:ThingSmartCameraRecordModeDPName];
          // If continuous recording is being used
        if (recordMode == ThingSmartCameraRecordModeAlways) {
              // Set to event recording mode
            [self.dpManager setValue:ThingSmartCameraRecordModeEvent forDP:ThingSmartCameraRecordModeDPName success:^(id result) {
                NSLog(@"Current recording mode is %@", result);
            } failure:^(NSError *error) {
                // Network error
            }];
        }
    }
}

- (void)checkStatus:(ThingSmartCameraSDCardStatus)status {
    if (status == ThingSmartCameraSDCardStatusNone) {
          // No memory card detected
        return;
    }else if (status == ThingSmartCameraSDCardStatusException) {
          // Memory card error, starting to format.
        [self formatAction];
    }else if (status == ThingSmartCameraSDCardStatusFormatting) {
          // Memory card is being formatted.
        [self handleFormatting];
    }else {
          // Get memory card capacity
        [self getStorageInfo];
          // Set the recording mode to event recording.
          [self changeToEventRecordMode];
    }
}

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

- (void)handleFormatting {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          // Proactively check the formatting progress, as some manufacturers' devices do not automatically report it.
        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, request the device's capacity information.
                [self getStorageInfo];
            } else {
                                //Formatting failed
            }
        });
    });
}

- (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);
    }];
    // Formatting a large volume SD card is relatively slow, so the timeout is set to 5 minutes.
    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) {
              // Data anomaly
            return;
        }
          // Total capacity
        weakSelf.total = [[components firstObject] integerValue];
          // Used space
        weakSelf.used = [[components objectAtIndex:1] integerValue];
          // Free space
        weakSelf.left = [[components lastObject] integerValue];
    } failure:^(NSError *error) {
        // Network error
    }];
}

Swift

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

func checkStatus(status: ThingSmartCameraSDCardStatus) {
    switch status {
    case .exception:
        // Memory card error, starting to format.
        self.formatSDCard()
        break
    case .formatting:
        // Memory card is being formatted.
        self.handleFormatting()
        break
    case .none:
        // No memory card detected
        return
    default:
        // Get memory card capacity
        self.getStorageInfo()
        // Set the recording mode to event recording.
        self.changeToEventRecordMode()
    }
}

func formatSDCard() {
    self.dpManager.setValue(true, forDP: .sdCardFormatDPName, success: { [weak self] _ in
        // Formatting started successfully, monitoring progress.
        self?.handleFormatting()
    }) { _ in
        // Network error
    }
}

func handleFormatting() {
    DispatchQueue.global().async {
        // Proactively check the formatting progress, as some manufacturers' devices do not automatically report it.
        let status = self.getFormatStatus()
        DispatchQueue.main.async {
            if status >= 0, status < 100 {
                self.handleFormatting()
            }else if status == 100 {
                // After formatting, request the device's capacity information.
                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()
    }
    // Formatting a large volume SD card is relatively slow, so the timeout is set to 5 minutes.
    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 anomaly
            return
        }
        // Total capacity
        let total = Int(components[0])
        // Used space
        let used = Int(components[1])
        // Free space
        let left = Int(components[2])
    }) { _ in
        // Network error
    }
}

func changeToEventRecordMode() {
    // Determine if the camera supports recording to a memory card.
    guard self.dpManager.isSupportDP(.sdCardRecordDPName) else {
        return
    }
    let isRecordOn = self.dpManager.value(forDP: .sdCardRecordDPName) as! Bool
    // If the camera has memory card recording enabled and supports recording mode settings.
    guard self.dpManager.isSupportDP(.recordModeDPName), isRecordOn else {
        return
    }

    let recordMode = self.dpManager.value(forDP: .recordModeDPName) as! String
    // If continuous recording is being used
    if recordMode == ThingSmartCameraRecordMode.always.rawValue {
        // Set to event recording mode
        self.dpManager.setValue(ThingSmartCameraRecordMode.event.rawValue, forDP: .recordModeDPName, success: { result in
            print("Current recording mode ", result as! String)
        }) { _ in
            // Network error
        }
    }

}