sample code - “control FTP job”¶
usage:
media <1~3(slot)> - get content info on media
add <1~3(slot)> <0~(contentId)> - add FTP job
job - get job info
To exit, please enter 'q'.
This sample code is included in SimpleCli.
1// "FTP job list" sample
2#include <chrono>
3#include <cstdint>
4#include <cstdlib>
5#include <fstream>
6#include <future>
7#include <iostream>
8#include <mutex>
9#include <sstream>
10#include <stdexcept>
11#include <string>
12#include <thread>
13#include <unordered_map>
14#include <vector>
15
16#if !defined(__APPLE__)
17 #if defined(USE_EXPERIMENTAL_FS) // for jetson
18 #include <experimental/filesystem>
19 namespace fs = std::experimental::filesystem;
20 #else
21 #include <filesystem>
22 namespace fs = std::filesystem;
23 #endif
24#endif
25
26#if defined(__APPLE__) || defined(__linux__)
27 #include <unistd.h>
28#endif
29
30// macro for multibyte character
31#if defined(_WIN32) || defined(_WIN64)
32 using CrString = std::wstring;
33 #define CRSTR(s) L ## s
34 #define CrCout std::wcout
35 #define CrCin std::wcin
36 #define CrPrintf std::wprintf
37#else
38 using CrString = std::string;
39 #define CRSTR(s) s
40 #define CrCout std::cout
41 #define CrCin std::cin
42 #define CrPrintf std::printf
43#endif
44
45
46#include "CrDeviceProperty.h"
47#include "CameraRemote_SDK.h"
48#include "IDeviceCallback.h"
49#include "CrDebugString.h" // use CrDebugString.cpp
50
51#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
52#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
53
54bool m_connected = false;
55CrString m_modelId;
56
57std::mutex m_eventPromiseMutex;
58std::promise<void>* m_eventPromise = nullptr;
59void setEventPromise(std::promise<void>* dp)
60{
61 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
62 m_eventPromise = dp;
63}
64
65SCRSDK::CrError _getDeviceProperty(int64_t device_handle, uint32_t code, SCRSDK::CrDeviceProperty* devProp)
66{
67 std::int32_t nprop = 0;
68 SCRSDK::CrDeviceProperty* prop_list = nullptr;
69 SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(device_handle, 1, &code, &prop_list, &nprop);
70 if(err) GotoError("", err);
71 if(prop_list && nprop >= 1) {
72 *devProp = prop_list[0];
73 }
74Error:
75 if(prop_list) SCRSDK::ReleaseDeviceProperties(device_handle, prop_list);
76 return err;
77}
78
79class DeviceCallback : public SCRSDK::IDeviceCallback
80{
81public:
82 DeviceCallback() {};
83 ~DeviceCallback() {};
84
85 void OnConnected(SCRSDK::DeviceConnectionVersioin version)
86 {
87 CrCout << "Connected to " << m_modelId << "\n";
88 m_connected = true;
89 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
90 if(m_eventPromise) {
91 m_eventPromise->set_value();
92 m_eventPromise = nullptr;
93 }
94 }
95
96 void OnError(CrInt32u error)
97 {
98 printf("Connection error:%s\n", CrErrorString(error).c_str());
99 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
100 if(m_eventPromise) {
101 m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
102 m_eventPromise = nullptr;
103 }
104 }
105
106 void OnDisconnected(CrInt32u error)
107 {
108 CrCout << "Disconnected from " << m_modelId << "\n";
109 m_connected = false;
110 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
111 if(m_eventPromise) {
112 m_eventPromise->set_value();
113 m_eventPromise = nullptr;
114 }
115 }
116
117 void OnCompleteDownload(CrChar* filename, CrInt32u type)
118 {
119 CrCout << "OnCompleteDownload:" << filename << "\n";
120 }
121
122 void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
123 {
124 std::cout << "OnNotifyContentsTransfer.\n";
125 }
126
127 void OnWarning(CrInt32u warning)
128 {
129 if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
130 CrCout << "Reconnecting to " << m_modelId << "\n";
131 return;
132 }
133 std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
134 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
135 switch(warning) {
136 case SCRSDK::CrWarning_RequestFTPJobList_Result_Success:
137 case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_OK:
138 if(m_eventPromise) {
139 m_eventPromise->set_value();
140 m_eventPromise = nullptr;
141 }
142 break;
143
144 case SCRSDK::CrWarning_RequestFTPJobList_Result_DeviceBusy:
145 case SCRSDK::CrWarning_RequestFTPJobList_Result_Error:
146 case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_Invalid:
147 case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_NG:
148 case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_DeviceBusy:
149 if(m_eventPromise) {
150 m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
151 m_eventPromise = nullptr;
152 }
153 break;
154 }
155 }
156
157
158 void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3)
159 {
160 std::cout << "OnWarningExt:" << CrWarningExtString(warning, param1, param2, param3).c_str() << "\n";
161 }
162
163 void OnLvPropertyChanged() {}
164 void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
165 void OnPropertyChanged() {}
166 void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
167
168 void OnNotifyFTPTransferResult(CrInt32u notify, CrInt32u numOfSuccess, CrInt32u numOfFail)
169 {
170 std::cout << "OnNotifyFTPTransferResult" << CrErrorString(notify) << "\n";
171 }
172};
173
174CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
175{
176 CrString id;
177 if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
178 id = CrString(objInfo->GetMACAddressChar());
179 } else {
180 id = CrString((CrChar*)objInfo->GetId());
181 }
182 return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
183}
184
185SCRSDK::CrError _getIdPassword(SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
186{
187 char fpBuff[128] = {0};
188 CrInt32u fpLen = 0;
189 SCRSDK::CrError err = SCRSDK::GetFingerprint(objInfo, fpBuff, &fpLen);
190 if(err) GotoError("", err);
191 fingerprint = std::string(fpBuff, fpLen);
192
193 std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
194 std::cout << "id:"; std::getline(std::cin, userId);
195 std::cout << "password:"; std::getline(std::cin, userPassword);
196 return 0;
197Error:
198 return err;
199}
200
201SCRSDK::CrError _getMediaProfile(int64_t device_handle, SCRSDK::CrMediaProfile slot)
202{
203 int result = SCRSDK::CrError_Generic_Unknown;
204 SCRSDK::CrError err = SCRSDK::CrError_None;
205
206 {
207 const std::unordered_map<SCRSDK::CrMediaProfile, SCRSDK::CrDevicePropertyCode> map_DP_status
208 {
209 {SCRSDK::CrMediaProfile_Slot1, SCRSDK::CrDeviceProperty_MediaSLOT1_Status},
210 {SCRSDK::CrMediaProfile_Slot2, SCRSDK::CrDeviceProperty_MediaSLOT2_Status},
211 {SCRSDK::CrMediaProfile_Slot3, SCRSDK::CrDeviceProperty_MediaSLOT3_Status},
212 };
213
214 SCRSDK::CrDeviceProperty devProp;
215
216 auto iter = map_DP_status.find(slot);
217 if(iter == end(map_DP_status)) GotoError("", 0);
218
219 err = _getDeviceProperty(device_handle, (uint32_t)iter->second, &devProp);
220 if(err) GotoError("", err);
221 if(devProp.GetCurrentValue() != (int)SCRSDK::CrSlotStatus_OK) GotoError("not ready", 0);
222 }
223
224 {
225 CrInt32u nums = 0;
226 SCRSDK::CrMediaProfileInfo* mediaProfileList = nullptr;
227 err = SCRSDK::GetMediaProfile(device_handle, slot, &mediaProfileList, &nums);
228 if(err || nums == 0) GotoError("", err);
229
230 for (CrInt32u i = 0; i < nums; i++) {
231 #define _CHAR(a) (a ? (const char*)a : "")
232
233 printf("id:%d\n", i);
234 std::cout << "contentName:" << _CHAR(mediaProfileList[i].contentName) << "\n";
235 std::cout << "contentUrl:" << _CHAR(mediaProfileList[i].contentUrl) << "\n";
236 std::cout << "contentType:" << _CHAR(mediaProfileList[i].contentType) << "\n";
237 std::cout << "contentFrameRate:" << _CHAR(mediaProfileList[i].contentFrameRate) << "\n";
238 std::cout << "contentAspectRatio:" << _CHAR(mediaProfileList[i].contentAspectRatio) << "\n";
239 std::cout << "contentChannel:" << _CHAR(mediaProfileList[i].contentChannel) << "\n";
240 std::cout << "contentVideoType:" << _CHAR(mediaProfileList[i].contentVideoType) << "\n";
241 std::cout << "contentAudioType:" << _CHAR(mediaProfileList[i].contentAudioType) << "\n";
242 if (mediaProfileList[i].proxyUrl != nullptr) {
243 std::cout << "proxyUrl:" << _CHAR(mediaProfileList[i].proxyUrl) << "\n";
244 std::cout << "proxyType:" << _CHAR(mediaProfileList[i].proxyType) << "\n";
245 std::cout << "proxyFrameRate:" << _CHAR(mediaProfileList[i].proxyFrameRate) << "\n";
246 std::cout << "proxyAspectRatio:" << _CHAR(mediaProfileList[i].proxyAspectRatio) << "\n";
247 std::cout << "proxyChannel:" << _CHAR(mediaProfileList[i].proxyChannel) << "\n";
248 std::cout << "proxyVideoType:" << _CHAR(mediaProfileList[i].proxyVideoType) << "\n";
249 std::cout << "proxyAudioType:" << _CHAR(mediaProfileList[i].proxyAudioType) << "\n";
250 }
251 std::cout << "thumbnailUrl:" << _CHAR(mediaProfileList[i].thumbnailUrl) << "\n";
252 std::cout << "metaUrl:" << _CHAR(mediaProfileList[i].metaUrl) << "\n";
253
254 std::cout << "umid:";
255 for(int j = 0; j < 32; j++) {
256 printf("%02x", mediaProfileList[i].umid[j]);
257 }
258 std::cout << "\n";
259
260 printf("duration:%d\n", mediaProfileList[i].duration);
261 printf("restrictionFrame:%d\n", mediaProfileList[i].restrictionFrame);
262 printf("isTrimmingAvailable:%d\n", mediaProfileList[i].isTrimmingAvailable);
263 std::cout << "\n";
264 }
265 SCRSDK::ReleaseMediaProfile(device_handle, mediaProfileList);
266 }
267Error:
268 return err;
269}
270
271SCRSDK::CrError _addMediaProfileToFTPJob(int64_t device_handle, SCRSDK::CrMediaProfile slot, uint32_t mediaIndex, uint32_t proxyFlag)
272{
273 int result = SCRSDK::CrError_Generic_Unknown;
274 SCRSDK::CrError err = SCRSDK::CrError_None;
275
276 SCRSDK::CrDeviceProperty devProp;
277 CrInt32u nums = 0;
278 SCRSDK::CrMediaProfileInfo* mediaProfileList = nullptr;
279 SCRSDK::CrFTPJobSetting* ftpJobSetting = nullptr;
280 std::promise<void> eventPromise;
281 std::future<void> eventFuture = eventPromise.get_future();
282
283 err = SCRSDK::GetMediaProfile(device_handle, slot, &mediaProfileList, &nums);
284 if(err || nums == 0 || mediaIndex >= nums) GotoError("", err);
285
286 err = _getDeviceProperty(device_handle, SCRSDK::CrDeviceProperty_SelectFTPServerID, &devProp);
287 if(err) GotoError("", err);
288
289 if (proxyFlag) {
290 if(mediaProfileList[mediaIndex].proxyUrl == nullptr) GotoError("no proxy", 0);
291
292 ftpJobSetting = new SCRSDK::CrFTPJobSetting(
293 /*trimType*/ SCRSDK::CrFTPJobTrimType_NoTrim,
294 /*serverId*/ (CrInt32u)devProp.GetCurrentValue(),
295 /*slotId*/ (SCRSDK::CrFTPJobSlotId)slot,
296 /*clipPath*/ (char*)mediaProfileList[mediaIndex].proxyUrl,
297 /*metaPath*/ nullptr,
298 /*transferDir*/ nullptr,
299 /*inFrame*/ 0,
300 /*outFrame*/ 0,
301 /*duration*/ 0,
302 /*destClipName*/ nullptr,
303 /*umid*/ nullptr,
304 /*videoType*/ nullptr,
305 /*compJobAction*/ SCRSDK::CrFTPJobCompleteAction_NoAction,
306 /*deleteJobAction*/ SCRSDK::CrFTPJobDeleteAction_NoAction);
307 } else {
308 ftpJobSetting = new SCRSDK::CrFTPJobSetting(
309 /*trimType*/ SCRSDK::CrFTPJobTrimType_NoTrim,
310 /*serverId*/ (CrInt32u)devProp.GetCurrentValue(),
311 /*slotId*/ (SCRSDK::CrFTPJobSlotId)slot,
312 /*clipPath*/ (char*)mediaProfileList[mediaIndex].contentUrl,
313 /*metaPath*/ (char*)mediaProfileList[mediaIndex].metaUrl,
314 /*transferDir*/ nullptr,
315 /*inFrame*/ 0,
316 /*outFrame*/ 0,
317 /*duration*/ 0,
318 /*destClipName*/ nullptr,
319 /*umid*/ nullptr,
320 /*videoType*/ nullptr,
321 /*compJobAction*/ SCRSDK::CrFTPJobCompleteAction_NoAction,
322 /*deleteJobAction*/ SCRSDK::CrFTPJobDeleteAction_NoAction);
323 }
324 setEventPromise(&eventPromise);
325
326 err = SCRSDK::ControlFTPJobList(device_handle, SCRSDK::CrFTPJobControlType_Add, ftpJobSetting, 1, SCRSDK::CrFTPJobDeleteType_Individual);
327 if(err) GotoError("", err);
328
329 try{
330 eventFuture.get();
331 } catch(const std::exception&) GotoError("", 0);
332 result = 0;
333Error:
334 setEventPromise(nullptr);
335 if(ftpJobSetting) delete ftpJobSetting;
336 return result;
337}
338
339
340void _printFTPJobInfo(SCRSDK::CrFTPJobInfo* jobInfo)
341{
342 #define _printChar(msg, dp) { \
343 const char* _dp = dp; \
344 std::cout << msg; \
345 if(_dp) std::cout << _dp; \
346 std::cout << "\n"; \
347 }
348
349 printf("jobId:%d\n", jobInfo->jobId);
350 printf("serverId:%d\n", jobInfo->serverId);
351 printf("slotId:%d\n", jobInfo->slotId);
352 printf("jobStatus:%d\n", jobInfo->jobStatus);
353 printf("chunkNum:%d\n", jobInfo->chunkNum);
354 printf("fileSize:%d\n", (int)jobInfo->fileSize);
355 printf("transferSize:%d\n", (int)jobInfo->transferSize);
356 _printChar("clipName:", jobInfo->GetClipName());
357 _printChar("mainName:", jobInfo->GetMainName());
358 _printChar("metaName:", jobInfo->GetMetaName());
359 return;
360}
361
362SCRSDK::CrError _getFTPJobInfo(int64_t device_handle/*, uint32_t index*/)
363{
364 int result = SCRSDK::CrError_Generic_Unknown;
365 SCRSDK::CrError err = SCRSDK::CrError_None;
366 std::promise<void> eventPromise;
367 std::future<void> eventFuture = eventPromise.get_future();
368
369 // request FTPJobList
370 setEventPromise(&eventPromise);
371
372 err = SCRSDK::RequestFTPJobList(device_handle);
373 if(err) GotoError("", err);
374
375 try{
376 eventFuture.get();
377 } catch(const std::exception&) GotoError("", 0);
378
379 // Get FTPJobList
380 {
381 SCRSDK::CrFTPJobInfo* ftpJobList = nullptr;
382 CrInt32u ftpJobListSize = 0;
383
384 err = SCRSDK::GetFTPJobList(device_handle, &ftpJobList, &ftpJobListSize);
385 if(err || ftpJobListSize == 0) GotoError("", err);
386
387 for(uint32_t i = 0; i < ftpJobListSize; i++) {
388 _printFTPJobInfo(ftpJobList + i);
389 std::cout << "\n";
390 }
391 SCRSDK::ReleaseFTPJobList(device_handle, ftpJobList);
392 }
393
394 result = 0;
395Error:
396 setEventPromise(nullptr);
397 return result;
398}
399
400std::vector<std::string> _split(std::string inputLine, char delimiter)
401{
402 std::vector<std::string> strArray;
403 if (inputLine.empty()) return strArray;
404
405 std::string tmp;
406 std::stringstream ss{inputLine};
407 while (getline(ss, tmp, delimiter)) {
408 strArray.push_back(tmp);
409 }
410 return strArray;
411}
412
413int main(void)
414{
415 int result = -1;
416 SCRSDK::CrError err = SCRSDK::CrError_None;
417 int64_t m_device_handle = 0;
418 SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
419 SCRSDK::ICrCameraObjectInfo* objInfo = nullptr;
420 DeviceCallback deviceCallback;
421
422 #if defined(__APPLE__)
423 #define MAC_MAX_PATH 255
424 char pathBuf[MAC_MAX_PATH] = {0};
425 if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
426 CrString path = pathBuf;
427 #else
428 CrString path = fs::current_path().native();
429 #endif
430
431 bool boolRet = SCRSDK::Init();
432 if(!boolRet) GotoError("", 0);
433
434 // enumeration
435 {
436 uint32_t count = 0;
437 uint32_t index = 1;
438
439 err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
440 if(err || !enumCameraObjectInfo) GotoError("no camera", err);
441
442 count = enumCameraObjectInfo->GetCount();
443 if(count >= 2) {
444 for (uint32_t i = 0; i < count; ++i) {
445 auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
446 CrCout << '[' << i + 1 << "] " << _getModelId(info) << "\n";
447 }
448
449 std::string inputLine;
450 std::cout << "select camera:"; std::getline(std::cin, inputLine);
451 try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
452 if(index < 1 || index > count) GotoError("", 0);
453 }
454 objInfo = (SCRSDK::ICrCameraObjectInfo*)enumCameraObjectInfo->GetCameraObjectInfo(index - 1);
455 m_modelId = _getModelId(objInfo);
456 }
457
458 // connect
459 {
460 std::string fingerprint = "";
461 std::string userId = "";
462 std::string userPassword = "";
463 std::promise<void> eventPromise;
464 std::future<void> eventFuture = eventPromise.get_future();
465
466 if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
467 err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
468 }
469
470 setEventPromise(&eventPromise);
471 err = SCRSDK::Connect(objInfo, &deviceCallback, &m_device_handle,
472 SCRSDK::CrSdkControlMode_Remote,
473 SCRSDK::CrReconnecting_ON,
474 userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
475 if(err) GotoError("", err);
476
477 // std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
478 // if(status != std::future_status::ready) GotoError("timeout",0);
479 try{
480 eventFuture.get();
481 } catch(const std::exception&) GotoError("", 0);
482 }
483
484 // set work directory
485 {
486 CrCout << "path=" << path.data() << "\n";
487 err = SCRSDK::SetSaveInfo(m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
488 if(err) GotoError("", err);
489 }
490
491 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
492
493 std::cout << "usage:\n";
494 std::cout << " media <1~3(slot)> - get content info on media\n";
495 std::cout << " add <1~3(slot)> <0~(contentId)> - add FTP job\n";
496 std::cout << " job - get job info\n";
497 std::cout << "To exit, please enter 'q'.\n";
498
499 while(1) {
500 std::string inputLine;
501 std::getline(std::cin, inputLine);
502 std::vector<std::string> args = _split(inputLine, ' ');
503
504 if(args.size() == 0) {
505
506 } else if((args[0] == "media" || args[0] == "m") && args.size() >= 2) {
507 int slot = 0;
508 try {
509 slot = stol(args[1]);
510 } catch(const std::exception&) { GotoError("", 0); }
511 err = _getMediaProfile(m_device_handle, (SCRSDK::CrMediaProfile)slot);
512 if(err) goto Error;
513
514 } else if((args[0] == "add" || args[0] == "a") && args.size() >= 3) {
515 int slot = 0;
516 int mediaIndex = 0;
517 int proxyFlag = 0;
518 try {
519 slot = stol(args[1]);
520 mediaIndex = stol(args[2]);
521 if(args.size() >= 4) proxyFlag = stol(args[3]);
522 } catch(const std::exception&) { GotoError("", 0); }
523
524 err = _addMediaProfileToFTPJob(m_device_handle, (SCRSDK::CrMediaProfile)slot, mediaIndex, proxyFlag);
525 if(err) goto Error;
526
527 } else if((args[0] == "job" || args[0] == "j") ) {
528 err = _getFTPJobInfo(m_device_handle);
529 if(err) goto Error;
530
531 } else if(args[0] == "q" || args[0] == "Q") {
532 break;
533 } else {
534 std::cout << "unknown command\n";
535 }
536 }
537
538 result = 0;
539Error:
540 if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
541
542 if(m_connected) {
543 std::promise<void> eventPromise;
544 std::future<void> eventFuture = eventPromise.get_future();
545 setEventPromise(&eventPromise);
546 SCRSDK::Disconnect(m_device_handle);
547 eventFuture.wait_for(std::chrono::milliseconds(3000));
548 }
549 if(m_device_handle) SCRSDK::ReleaseDevice(m_device_handle);
550 SCRSDK::Release();
551
552 return result;
553}