# 固件升級(jí)示例-FirmwareUpgrade
功能描述:本示例演示如何用固件文件給設(shè)備升級(jí)。
> 本示例基于C++ Low Level API進(jìn)行演示
在main函數(shù)接口通過(guò)命令參數(shù)獲取固件文件
// checkFirmwareFilePath()函數(shù)用于檢查文件是否存在,實(shí)際代碼中最好檢查后綴是否為bin或者img, 以及固件文件是否與目標(biāo)設(shè)備相匹配
std::string checkFirmwareFilePath(int argc, char **argv) {
if(argc < 2) {
std::cout << "Please input firmware path." << std::endl;
return "";
}
std::string filePath = std::string(*(argv + 1));
std::ifstream fs(filePath);
if(!fs.is_open()) {
std::cout << "Open Firmware file failed. filePath: " << filePath << std::endl;
return "";
}
fs.close();
return filePath;
}
int main(int argc, char **argv) try {
std::string firmwareFilePath = checkFirmwareFilePath(argc, argv);
if(firmwareFilePath.empty()) {
std::cout << "command: " << std::endl << "$ ./FirmwareUpgrade[.exe] firmwareFile.bin" << std::endl;
return 0;
}
// 接下來(lái)的業(yè)務(wù)代碼
return 0;
}
catch(ob::Error &e) {
// 處理OrbbecSDK接口調(diào)用異常,示例為了簡(jiǎn)潔連續(xù)幾個(gè)接口一起try-catch,實(shí)際業(yè)務(wù)中推薦單獨(dú)一個(gè)接口一個(gè)try-catch
std::cerr << "function:" << e.getName() << "\nargs:" << e.getArgs() << "\nmessage:" << e.getMessage() << "\ntype:" << e.getExceptionType() << std::endl;
exit(EXIT_FAILURE);
}
創(chuàng)建ob::Context并通過(guò)ob::Context獲取設(shè)備,本示例假設(shè)運(yùn)行FirmwareUpgrade[.exe]之前上位機(jī)(Windows、Ubuntu、Android平臺(tái))已經(jīng)插入設(shè)備。ob::DeviceChangedCallback用于固件升級(jí)后監(jiān)聽(tīng)device重啟后獲取被升級(jí)設(shè)備的業(yè)務(wù)處理
// 構(gòu)建ob::Context對(duì)象
ob::Context ctx;
// 設(shè)置設(shè)備變化監(jiān)聽(tīng)器,device_changed_callback是管理device聲明周期的關(guān)鍵函數(shù),開(kāi)發(fā)者必須關(guān)注該回調(diào)
ctx.setDeviceChangedCallback([](std::shared_ptr<ob::DeviceList> removedList, std::shared_ptr<ob::DeviceList> addedList) {
if(isWaitRebootComplete_) {
if(addedList && addedList->deviceCount() > 0) {
auto device = addedList->getDevice(0);
if(isDeviceRemoved_ && deviceSN_ == std::string(device->getDeviceInfo()->serialNumber())) {
rebootedDevice_ = device;
isWaitRebootComplete_ = false;
std::unique_lock<std::mutex> lk(waitRebootMutex_);
waitRebootCondition_.notify_all();
}
}
if(removedList && removedList->deviceCount() > 0) {
if(deviceUid_ == std::string(removedList->uid(0))) {
isDeviceRemoved_ = true;
}
}
} // if isWaitRebootComplete_
});
// 查詢(xún)當(dāng)前已經(jīng)接入的設(shè)備
auto devList = ctx.queryDeviceList();
// 從ob::DeviceList中獲取當(dāng)前接入設(shè)備的數(shù)量
if(devList->deviceCount() == 0) {
// 固件升級(jí)示例默認(rèn)設(shè)備已經(jīng)接入到上位機(jī)(Windows、Ubuntu、Android平臺(tái))
std::cerr << "Device not found!" << std::endl;
return -1;
}
// 獲取第一個(gè)設(shè)備,index=0
auto dev = devList->getDevice(0);
// 打印設(shè)備信息
dumpDeviceInfo(dev);
獲取設(shè)備當(dāng)前的固件版本信息
// 打印設(shè)備名稱(chēng),SN,VID,PID以及固件版本
void dumpDeviceInfo(std::shared_ptr<ob::Device> device) {
// 獲取ob::DeviceInfo對(duì)象,通過(guò)ob::DeviceInfo可以獲取目標(biāo)設(shè)備的基本信息
auto devInfo = device->getDeviceInfo();
// 設(shè)備名稱(chēng)
std::cout << "Device name: " << devInfo->name() << std::endl;
// 設(shè)備VID,PID,UID
std::cout << "Device pid: " << devInfo->pid() << " vid: " << devInfo->vid() << " uid: " << devInfo->uid() << std::endl;
// 設(shè)備當(dāng)前的固件版本號(hào)
auto fwVer = devInfo->firmwareVersion();
std::cout << "Firmware version: " << fwVer << std::endl;
// 設(shè)備SN
auto sn = devInfo->serialNumber();
std::cout << "Serial number: " << sn << std::endl;
// devInfo資源會(huì)自動(dòng)釋放
給目標(biāo)設(shè)備升級(jí)固件
a. 實(shí)現(xiàn)C API的固件升級(jí)回調(diào)接口;
b. 調(diào)用固件升級(jí)接口進(jìn)行升級(jí);
// 對(duì)目標(biāo)設(shè)備進(jìn)行固件升級(jí)
bool upgradeFirmware(std::shared_ptr<ob::Device> device, std::string firmwarePath) {
auto index = firmwarePath.find_last_of(".img");
bool isImgFile = index != std::string::npos;
index = firmwarePath.find_last_of(".bin");
bool isBinFile = index != std::string::npos;
if(!(isImgFile || isBinFile)) {
// 固件升級(jí)文件一般為bin或者img,實(shí)際業(yè)務(wù)中最好通過(guò)文件名稱(chēng)、文件MD5等信息做防呆
std::cout << "Upgrade Fimware failed. invalid firmware file: " << firmwarePath << std::endl;
return false;
}
bool isUpgradeSuccess = false;
try {
// 調(diào)用固件升級(jí)接口進(jìn)行升級(jí);
device->deviceUpgrade(
firmwarePath.c_str(),
[=, &isUpgradeSuccess](OBUpgradeState state, const char *message, uint8_t percent) {
if(state == STAT_START) {
std::cout << "Upgrade Firmware start" << std::endl;
}
else if(state == STAT_FILE_TRANSFER) {
std::cout << "Upgrade Firmware file transfer, percent: " << (uint32_t)percent << std::endl;
}
else if(state == STAT_IN_PROGRESS) {
std::cout << "Upgrade Firmware in progress, percent: " << (uint32_t)percent << std::endl;
}
else if(state == STAT_DONE) {
// 固件升級(jí)成功
std::cout << "Upgrade Firmware done, percent: " << (uint32_t)percent << std::endl;
isUpgradeSuccess = true;
}
else if(state == STAT_VERIFY_IMAGE) {
std::cout << "Upgrade Firmware verify image" << std::endl;
}
else {
// 固件升級(jí)失敗
std::string errMsg = (nullptr != message ? std::string(message) : "");
std::cout << "Upgrade Firmware failed. state: " << std::to_string(state) << ", errMsg: " << errMsg << ", percent: " << (uint32_t)percent
<< std::endl;
}
},
false);
}
catch(ob::Error &e) {
std::cerr << "Upgrade Firmware ob error. function:" << e.getName() << "\nargs:" << e.getArgs() << "\nmessage:" << e.getMessage()
<< "\ntype:" << e.getExceptionType() << std::endl;
}
catch(std::exception &e) {
if(e.what()) {
std::cout << "Upgrade Firmware Exception. what: " << std::string(e.what()) << std::endl;
}
}
return isUpgradeSuccess;
}
固件升級(jí)成功后,需要重啟設(shè)備。重啟設(shè)備有兩種方式,一種是拔插設(shè)備(或者操作系統(tǒng)重啟),另一種是調(diào)用OrbbecSDK的reboot接口。等設(shè)備上線(xiàn)后,通過(guò)本示例的dump_device_info()函數(shù)可以查詢(xún)當(dāng)前設(shè)備固件版本信息
以下示例演示通過(guò)固件reboot接口重啟設(shè)備
// 重啟設(shè)備
std::cout << "Reboot device" << std::endl;
isDeviceRemoved_ = false;
isWaitRebootComplete_ = true;
dev->reboot();
// 釋放資源,設(shè)備重啟后ob::Device對(duì)象就不能用了
dev = nullptr;
程序正常退出之后資源將會(huì)自動(dòng)釋放
預(yù)期輸出: