sample code - “connect to multi-camera”

usage:
   set <camera index> <DP name> <param> [1-blocking,0-no blocking]
   get <camera index> <DP name>
To exit, please enter 'q'.

This sample code is included in SimpleCli.

  1// connect to multi-camera sample
  2#include <chrono>
  3#include <cinttypes>
  4#include <cstdint>
  5#include <cstdlib>
  6#include <fstream>
  7#include <future>
  8#include <iostream>
  9#include <mutex>
 10#include <sstream>
 11#include <stdexcept>
 12#include <string>
 13#include <thread>
 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#else
 36  using CrString = std::string;
 37  #define CRSTR(s) s
 38  #define CrCout std::cout
 39#endif
 40
 41
 42#include "CrDeviceProperty.h"
 43#include "CameraRemote_SDK.h"
 44#include "IDeviceCallback.h"
 45#include "CrDebugString.h"   // use CrDebugString.cpp
 46
 47#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
 48#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
 49
 50CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
 51{
 52    CrString id;
 53    if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
 54        id = CrString(objInfo->GetMACAddressChar());
 55    } else {
 56        id = CrString((CrChar*)objInfo->GetId());
 57    }
 58    return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
 59}
 60
 61std::vector<std::string> _split(std::string inputLine, char delimiter)
 62{
 63    std::vector<std::string> strArray;
 64    if (inputLine.empty()) return strArray;
 65
 66    std::string tmp;
 67    std::stringstream ss{inputLine};
 68    while (getline(ss, tmp, delimiter)) {
 69        strArray.push_back(tmp);
 70    }
 71    return strArray;
 72}
 73
 74int64_t _stoll(std::string inputLine)
 75{
 76    int64_t data = 0;
 77    if(inputLine.empty()) throw std::runtime_error("error");
 78    try {
 79        if (inputLine.compare(0, 2, "0x") == 0 || inputLine.compare(0, 2, "0X") == 0) {
 80            data = std::stoull(inputLine.substr(2), nullptr, 16);
 81        } else {
 82            data = std::stoll(inputLine, nullptr, 10);
 83        }
 84    } catch(const std::exception& ex) {
 85        throw ex;
 86    }
 87    return data;
 88}
 89
 90class CameraDevice : public SCRSDK::IDeviceCallback
 91{
 92public:
 93    int64_t  m_device_handle = 0;
 94    bool  m_connected = false;
 95    CrString m_modelId;
 96
 97    std::mutex m_eventPromiseMutex;
 98    uint32_t m_setDPCode = 0;
 99    std::promise<void>* m_eventPromise = nullptr;
100    void setEventPromise(std::promise<void>* dp)
101    {
102        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
103        m_eventPromise = dp;
104    }
105
106    CameraDevice() {};
107    ~CameraDevice() {};
108
109    // override of IDeviceCallback
110
111    void OnConnected(SCRSDK::DeviceConnectionVersioin version)
112    {
113        CrCout << "Connected to " << m_modelId << "\n";
114        m_connected = true;
115        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
116        if(m_eventPromise) {
117            m_eventPromise->set_value();
118            m_eventPromise = nullptr;
119        }
120    }
121
122    void OnError(CrInt32u error)
123    {
124        printf("Connection error:%s\n", CrErrorString(error).c_str());
125        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
126        if(m_eventPromise) {
127            m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
128            m_eventPromise = nullptr;
129        }
130    }
131
132    void OnDisconnected(CrInt32u error)
133    {
134        CrCout << "Disconnected from " << m_modelId << "\n";
135        m_connected = false;
136        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
137        if(m_eventPromise) {
138            m_eventPromise->set_value();
139            m_eventPromise = nullptr;
140        }
141    }
142
143    void OnCompleteDownload(CrChar* filename, CrInt32u type )
144    {
145        CrCout << "OnCompleteDownload:" << filename << "\n";
146    }
147
148    void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
149    {
150        std::cout << "OnNotifyContentsTransfer.\n";
151    }
152
153    void OnWarning(CrInt32u warning)
154    {
155        if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
156            CrCout << "Reconnecting to " << m_modelId << "\n";
157            return;
158        }
159        std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
160    }
161
162    void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3) {}
163    void OnLvPropertyChanged() {}
164    void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
165    void OnPropertyChanged() {}
166    void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes)
167    {
168        //std::cout << "OnPropertyChangedCodes:\n";
169        for(uint32_t i = 0; i < num; ++i) {
170            std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
171            if(m_setDPCode && m_setDPCode == codes[i]) {
172                m_setDPCode = 0;
173                if(m_eventPromise) {
174                    m_eventPromise->set_value();
175                    m_eventPromise = nullptr;
176                }
177            }
178        }
179    }
180
181    // method
182
183    SCRSDK::CrError _getIdPassword(const SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
184    {
185        char fpBuff[128] = {0};
186        CrInt32u fpLen = 0;
187        SCRSDK::CrError err = SCRSDK::GetFingerprint((SCRSDK::ICrCameraObjectInfo*)objInfo, fpBuff, &fpLen);
188        if(err) GotoError("", err);
189        fingerprint = std::string(fpBuff, fpLen);
190
191        std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
192        std::cout << "id:";       std::getline(std::cin, userId);
193        std::cout << "password:"; std::getline(std::cin, userPassword);
194        return 0;
195    Error:
196        return err;
197    }
198
199    SCRSDK::CrError connect(const SCRSDK::ICrCameraObjectInfo* objInfo)
200    {
201        SCRSDK::CrError err = SCRSDK::CrError_None;
202        int result = SCRSDK::CrError_Generic_Unknown;
203        std::string  fingerprint = "";
204        std::string  userId = "";
205        std::string  userPassword = "";
206        std::promise<void> eventPromise;
207        std::future<void> eventFuture = eventPromise.get_future();
208
209        m_modelId = _getModelId(objInfo);
210
211        if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
212            err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
213        }
214
215        setEventPromise(&eventPromise);
216        err = SCRSDK::Connect((SCRSDK::ICrCameraObjectInfo*)objInfo, this, &m_device_handle,
217            SCRSDK::CrSdkControlMode_Remote,
218            SCRSDK::CrReconnecting_ON,
219            userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
220        if(err) GotoError("", err);
221
222    //  std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
223    //  if(status != std::future_status::ready) GotoError("timeout",0);
224        try{
225            eventFuture.get();
226        } catch(const std::exception&) GotoError("", 0);
227        result = 0;
228    Error:
229        return result;
230    }
231
232    SCRSDK::CrError disconnect(void)
233    {
234        if(m_connected) {
235            std::promise<void> eventPromise;
236            std::future<void> eventFuture = eventPromise.get_future();
237            setEventPromise(&eventPromise);
238            SCRSDK::Disconnect(m_device_handle);
239            eventFuture.wait_for(std::chrono::milliseconds(3000));
240            m_connected = false;
241        }
242        if(m_device_handle) {
243            SCRSDK::ReleaseDevice(m_device_handle);
244            m_device_handle = 0;
245        }
246        return SCRSDK::CrError_None;
247    }
248
249    SCRSDK::CrError getDeviceProperty(uint32_t code, SCRSDK::CrDeviceProperty* devProp)
250    {
251        std::int32_t nprop = 0;
252        SCRSDK::CrDeviceProperty* prop_list = nullptr;
253        SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(m_device_handle, 1, &code, &prop_list, &nprop);
254        if(err) GotoError("", err);
255        if(prop_list && nprop >= 1) {
256            *devProp = prop_list[0];
257        }
258    Error:
259        if(prop_list) SCRSDK::ReleaseDeviceProperties(m_device_handle, prop_list);
260        return err;
261    }
262
263    SCRSDK::CrError setDeviceProperty(uint32_t code, uint64_t data, bool blocking=true)
264    {
265        int result = SCRSDK::CrError_Generic_Unknown;
266        SCRSDK::CrError err = 0;
267        std::promise<void> eventPromise;
268        std::future<void> eventFuture = eventPromise.get_future();
269        std::future_status status;
270
271        SCRSDK::CrDeviceProperty devProp;
272
273        err = getDeviceProperty(code, &devProp);
274        if(err) GotoError("", err);
275        if (devProp.GetValueType() == SCRSDK::CrDataType_STR) GotoError("STR is not supported", 0);
276        if (blocking && devProp.GetCurrentValue() == data) {
277            std::cout << "skipped\n";
278            return 0;
279        }
280
281        if(blocking) {
282            std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
283            m_setDPCode = code;
284            m_eventPromise = &eventPromise;
285        }
286
287        devProp.SetCurrentValue(data);
288        err = SCRSDK::SetDeviceProperty(m_device_handle, &devProp);
289        if(err) GotoError("", err);
290
291        if(!blocking) return 0;
292
293        status = eventFuture.wait_for(std::chrono::milliseconds(3000));
294        if(status != std::future_status::ready) GotoError("timeout", 0);
295
296        try{
297            eventFuture.get();
298        } catch(const std::exception&) GotoError("", 0);
299        std::cout << "OK\n";
300
301        result = 0;
302    Error:
303        setEventPromise(nullptr);
304        return result;
305    }
306};
307
308int main(void)
309{
310    int result = -1;
311    SCRSDK::CrError err = SCRSDK::CrError_None;
312    SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
313    uint32_t count = 0;
314    #define DEVICE_MAX  2
315    CameraDevice devices[DEVICE_MAX];
316    uint32_t device_num = 0;
317    uint32_t i;
318
319  #if defined(__APPLE__)
320    #define MAC_MAX_PATH 255
321    char pathBuf[MAC_MAX_PATH] = {0};
322    if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
323    CrString path = pathBuf;
324  #else
325    CrString path = fs::current_path().native();
326  #endif
327
328    bool boolRet = SCRSDK::Init();
329    if(!boolRet) GotoError("", 0);
330
331    // enumeration & select camera
332
333    err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
334    if(err || !enumCameraObjectInfo) GotoError("no camera", err);
335
336    count = enumCameraObjectInfo->GetCount();
337    for (i = 0; i < count; i++) {
338        auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
339        CrCout << '[' << i << "] " << _getModelId(info) << "\n";
340    }
341
342    device_num = count;
343    if(device_num > DEVICE_MAX) device_num = DEVICE_MAX;
344    for(i = 0; i < device_num; i++) {
345        uint32_t index;
346        std::string inputLine;
347        printf("select camera%d:", i); std::getline(std::cin, inputLine);
348        try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
349        if(index < 0 || index >= count) GotoError("", 0);
350
351        // connect
352        err = devices[i].connect(enumCameraObjectInfo->GetCameraObjectInfo(index));
353        if(err) goto Error;
354
355        // set work directory
356        err = SCRSDK::SetSaveInfo(devices[i].m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
357        if(err) GotoError("", err);
358    }
359
360    CrCout << "path=" << path.data() << "\n";
361
362    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
363
364    std::cout << "usage:\n";
365    std::cout << "   set <camera index> <DP name> <param> [1-blocking,0-no blocking]\n";
366    std::cout << "   get <camera index> <DP name>\n";
367    std::cout << "To exit, please enter 'q'.\n";
368
369    while(1) {
370        uint32_t deviceId = 0;
371        int32_t code;
372        std::string inputLine;
373        std::getline(std::cin, inputLine);
374        std::vector<std::string> args = _split(inputLine, ' ');
375
376        if(args.size() == 0) continue;
377
378        if(args[0] == "q" || args[0] == "Q") break;
379
380        if(args.size() < 3) continue;
381
382        try{ deviceId = (int)_stoll(args[1]); } catch(const std::exception&) {continue;}
383        if(deviceId >= device_num) continue;
384
385        code = CrDevicePropertyCode(args[2]);
386        if(code < 0) continue;
387
388        if(args[0] == "get") {
389            SCRSDK::CrDeviceProperty devProp;
390            err = devices[deviceId].getDeviceProperty(code, &devProp);
391            if(err) continue;
392
393            if(devProp.GetValueType() != SCRSDK::CrDataType_STR) {
394                printf("0x%" PRIx64 "(%" PRId64 ")\n", devProp.GetCurrentValue(), devProp.GetCurrentValue());  // macro for %lld
395            }
396        } else if(args[0] == "set" && args.size() >= 4) {
397            int64_t data = 0;
398            bool blocking = true;
399
400            try{ data = _stoll(args[3]); } catch(const std::exception&) {continue;}
401            if(args.size() >= 5)
402                try{ blocking = _stoll(args[4]); } catch(const std::exception&) {continue;}
403
404            err = devices[deviceId].setDeviceProperty(code, data, blocking);
405            if(err) continue;
406        } else {
407            std::cout << "unknown command\n";
408        }
409    }
410
411    result = 0;
412Error:
413    if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
414    for(i = 0; i < device_num; i++)
415        devices[i].disconnect();
416    SCRSDK::Release();
417
418    return result;
419}