Loading sdk/src/codes.h +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ public: GetCameraSettings = 4364, GetCameraState = 4362, QuerySessionHolder = 1793, }; enum class ParamCameraState Loading sdk/src/commander.cpp +133 −300 Original line number Diff line number Diff line #include <cerrno> #include <climits> #include <iostream> #include <vector> #include <thread> #include <unistd.h> #include "commander.h" #include <iostream> using namespace std; Commander::Commander() : _sock(TcpSocket(&_reader)), _token(0), _sock(TcpSocket()), _reader(CustomReader(&_sock)), _iso((Codes::ISO)-1), _speed((Codes::Speed)-1), Loading @@ -21,6 +22,7 @@ Commander::Commander() : _bracketingBuiltIn((Codes::ParamBracketingBuiltIn)-1) {}; string Commander::generateJSON(Codes::MsgId msg) { DynamicJsonDocument json(JSON_OBJECT_SIZE(2)); Loading @@ -33,6 +35,7 @@ string Commander::generateJSON(Codes::MsgId msg) return str; } template <typename T> string Commander::generateJSON(Codes::MsgId msg, T param) { Loading @@ -47,6 +50,7 @@ string Commander::generateJSON(Codes::MsgId msg, T param) return str; } template <> string Commander::generateJSON(Codes::MsgId msg, string param) { Loading @@ -61,200 +65,46 @@ string Commander::generateJSON(Codes::MsgId msg, string param) return str; } void Commander::handleMsgId(DynamicJsonDocument& json) { cout << "NOTIFICATION: "; //TODO: add more ids switch ((int)json["msg_id"]) { case (int)Codes::MsgId::GetCameraState: { cout << "Camera state: "; string key = "param"; if (!json.containsKey(key) || !json[key].is<int>()) cout << "invalid" << endl; else cout << Codes::stateToString(json[key]) << endl; break; } case (int)Codes::MsgId::GetSetMode: { cout << "Camera mode set to: "; string key = "param"; if (!json.containsKey(key) || !json[key].is<int>() || json[key] < 0 || json[key] > 1) cout << "invalid" << endl; else cout << (json[key] == (int)Codes::ParamMode::Video ? "video" : "photo" ) << endl; break; } default: cout << _reader.history << endl; break; } } bool Commander::getJSON(DynamicJsonDocument& json, int& rval, Codes::MsgId expected_msg_id) { // Get response for (int i = 0; i < 3; ++i) // make 3 attempts to receive json { _reader.resetHistory(); errno = 0; auto err = deserializeJson(json, _reader); if (errno == EAGAIN || errno == EWOULDBLOCK) { cerr << "recv timed out\n"; continue; } switch (err.code()) { case DeserializationError::Ok: break; case DeserializationError::NoMemory: //TODO cerr << "Error: couldn't parse JSON (" << err.c_str() << "): " << _reader.history << endl; return false; //these shouldn't happen case DeserializationError::InvalidInput: case DeserializationError::TooDeep: case DeserializationError::NotSupported: case DeserializationError::IncompleteInput: // this won't happen, as recv (deserializeJson) would time out cerr << "Error: couldn't parse JSON (" << err.c_str() << "): " << _reader.history << endl; cerr << "Restarting socket..."; _sock.close(); close(); connect(); //TODO: try again? return false; } string key = "msg_id"; if (!json.containsKey(key) || !json[key].is<int>()) { cerr << "Unexpected JSON response: " << _reader.history << endl; continue; } else if (json[key] != (int)expected_msg_id) { handleMsgId(json); continue; } key = "rval"; if (!json.containsKey(key) || !json[key].is<int>()) { //TODO: Handle message without rval cerr << "Error: unexpected rval (\"" << key << "\" = " << json[key] << ")" << endl; break; } rval = json[key]; return true; } return false; } bool Commander::str2int (const char* s, int& i, int base) { char *end; long l; errno = 0; l = strtol(s, &end, base); if (errno != 0 || *s == '\0' || *end != '\0' || l > INT_MAX || l < INT_MIN) return false; i = l; return true; } bool Commander::connect() { _sock.setTimeout(3); if (!_sock.connect("127.0.0.1", 7878) || !getToken() || !getCameraSettings()) return false; return true; } bool Commander::getToken() { if (!_sock.send(generateJSON(Codes::MsgId::GetToken))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::GetToken)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(Codes::MsgId::GetToken), jsonPtr, make_pair(Codes::MsgId::GetToken,Codes::Rval::CommandOk))) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<int>() || json[key] == 0) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _token = json[key]; _token = (*jsonPtr)[key]; return true; } bool Commander::getCameraSettings() { if (!_sock.send(generateJSON(Codes::MsgId::GetCameraSettings))) return false; DynamicJsonDocument json(JSON_OBJECT_SIZE(26) + 370); int rval; if (!getJSON(json, rval, Codes::MsgId::GetCameraSettings)) return false; switch(rval) bool Commander::getCameraSettings() { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(Codes::MsgId::GetCameraSettings), jsonPtr, make_pair(Codes::MsgId::GetCameraSettings,Codes::Rval::CommandOk))) return false; } string key = "still_iso"; if (!json.containsKey(key) || !json[key].is<int>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _iso = (Codes::ISO)(int)json[key]; _iso = (Codes::ISO)(int)(*jsonPtr)[key]; key = "still_shutter"; if (!json.containsKey(key) || !json[key].is<int>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _speed = (Codes::Speed)(int)json[key]; _speed = (Codes::Speed)(int)(*jsonPtr)[key]; return true; } Loading Loading @@ -303,22 +153,9 @@ bool Commander::setBracketingBuiltIn(Codes::ParamBracketingBuiltIn bracketing) template <typename T> bool Commander::setParam(Codes::MsgId msgid, T param) { if (!_sock.send(generateJSON(msgid, (int)param))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, msgid)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(msgid, (int)param), jsonPtr, make_pair(msgid,Codes::Rval::CommandOk))) return false; } return true; } Loading @@ -326,47 +163,22 @@ bool Commander::setParam(Codes::MsgId msgid, T param) template <typename T> bool Commander::getParam(Codes::MsgId msgid, T& param_out) { if (!_sock.send(generateJSON(msgid))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, msgid)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(msgid), jsonPtr, make_pair(msgid,Codes::Rval::CommandOk))) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<T>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<T>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } param_out = json[key]; param_out = (*jsonPtr)[key]; return true; } /** * Set commander's bracketing settings - * * Computes and saves 'halfCount' shutter speeds above and below currently set * shutter speed, so each two 'adjecent' speeds differ !APPROXIMATELY! by 'evStep' EV * (shutter speeds supported by camera does not always differ exactly by 1EV, * e.g. ... 1/3200s,1/2000s,1/1000s ... 1/4s,1s,2s ...) * * @param evStep number of exposure steps between two images * @param halfCount number of pictures to be taken above and below currently set exposure * @return true if setting was successful, otherwise false */ bool Commander::setBracketing(size_t evStep, size_t halfCount) { if (_bracketingStep != evStep || _bracketingHalfCount != halfCount) Loading Loading @@ -409,46 +221,25 @@ bool Commander::setBracketing(size_t evStep, size_t halfCount) bool Commander::shootNormal() { if (!_sock.send(generateJSON(Codes::MsgId::ShootNormal))) return false; // await "capture was enqueued" DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::ShootNormal)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: return false; } // await "capture has finished" json = DynamicJsonDocument(JSON_OBJECT_SIZE(9) + 140); if (!getJSON(json, rval, Codes::MsgId::ImgCaptured)) return false; switch(rval) vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr; if (!_sock.sendRecvVerify( generateJSON(Codes::MsgId::ShootNormal), vectorJsonPtr, { case (int)Codes::Rval::NotificationOk: break; default: make_pair(Codes::MsgId::ShootNormal, Codes::Rval::CommandOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk) }) ) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<string>()) if (!vectorJsonPtr[1]->containsKey(key) || !(*vectorJsonPtr[1])[key].is<string>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*vectorJsonPtr[1])[key] << endl; return false; } cout << "Image captured: " << json[key] << endl; cout << "Image captured: " << (*vectorJsonPtr[1])[key] << endl; return true; } Loading @@ -464,7 +255,7 @@ bool Commander::shootBracketing() if (!shootNormal()) return false; usleep(300000); //wait for 300ms this_thread::sleep_for(chrono::milliseconds(300)); } // set back shutter speed Loading @@ -474,68 +265,110 @@ bool Commander::shootBracketing() return true; } bool Commander::shootBracketingBuiltIn() { if (!_sock.send(generateJSON(Codes::MsgId::ShootBracketing))) return false; vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr; if (!_sock.sendRecvVerify( generateJSON(Codes::MsgId::ShootBracketing), vectorJsonPtr, { make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::CommandOk), make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), // await "bracketing was enqueued" DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::ShootBracketing)) make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), }) ) return false; switch(rval) for (int i = 2; i < 7; i+=2) { case (int)Codes::Rval::CommandOk: break; default: string key = "param"; if (!vectorJsonPtr[i]->containsKey(key) || !(*vectorJsonPtr[i])[key].is<string>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*vectorJsonPtr[i])[key] << endl; return false; } string key = "param"; for (int i = 0; i < 3; ++i) cout << "Image captured: " << (*vectorJsonPtr[i])[key] << endl; } return true; } bool Commander::start() { json = DynamicJsonDocument(minCapacity); if (!getJSON(json, rval, Codes::MsgId::ShootBracketing)) receiverThr = thread(&Commander::runReceiver, this); this_thread::sleep_for(chrono::milliseconds(50)); if (!isReceiverRunning() || !getToken() || !getCameraSettings()) return false; switch(rval) return true; } void Commander::stop() { case (int)Codes::Rval::NotificationOk: break; default: return false; _sock.stopReceiver(); receiverThr.join(); } json = DynamicJsonDocument(JSON_OBJECT_SIZE(10) + 140); // await "capture has finished" if (!getJSON(json, rval, Codes::MsgId::ImgCaptured)) bool Commander::connect() { if (!_sock.connectTo("127.0.0.1", 7878)) return false; switch(rval) _sock.setTimeout(1); return true; } void Commander::disconnect() { case (int)Codes::Rval::NotificationOk: break; default: return false; _token = 0; _sock.closeSocket(); } if (!json.containsKey(key) || !json[key].is<string>()) bool Commander::isReceiverRunning() { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; return false; lock_guard lock(receiverRunningMutex); return receiverRunning; } cout << "Image captured: " << json[key] << endl; bool Commander::runReceiver() { while (true) { if (!connect()) return false; { lock_guard lock(receiverRunningMutex); receiverRunning = true; } return true; if (_sock.runReceiver()) break; { lock_guard lock(receiverRunningMutex); receiverRunning = false; } //if TcpSocket::runReceiver() returns false, reconnect cerr << "Restarting socket..." << endl; disconnect(); } void Commander::close() { _token = 0; _sock.close(); lock_guard lock(receiverRunningMutex); receiverRunning = false; } return true; } No newline at end of file sdk/src/commander.h +41 −17 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ #define COMMANDER_H #include <map> #include <queue> #include <memory> #include <vector> #include <thread> #include <ArduinoJson.h> Loading @@ -16,7 +17,7 @@ class Commander { public: Commander(); bool connect(); bool setISO(Codes::ISO iso); bool setSpeed(Codes::Speed speed); Loading @@ -25,20 +26,44 @@ public: template <typename T> bool setParam(Codes::MsgId msgid, T param); template <typename T> bool getParam(Codes::MsgId msgid, T& param_out); /** * Set commander's bracketing settings - * * Computes and saves 'halfCount' shutter speeds above and below currently set * shutter speed, so each two 'adjecent' speeds differ !APPROXIMATELY! by 'evStep' EV * (shutter speeds supported by camera does not always differ exactly by 1EV, * e.g. ... 1/3200s,1/2000s,1/1000s ... 1/4s,1s,2s ...) * * @param evStep number of exposure steps between two images * @param halfCount number of pictures to be taken above and below currently set exposure * @return true if setting was successful, otherwise false */ bool setBracketing(size_t evStep, size_t halfCount); bool shootNormal(); bool shootBracketing(); bool shootBracketingBuiltIn(); void close(); bool getToken(); bool getCameraSettings(); bool runReceiver(); bool stopReceiver(); bool isReceiverRunning(); bool start(); void stop(); private: const int minCapacity = (JSON_OBJECT_SIZE(5) + 50); int _token; TcpSocket _sock; std::thread receiverThr; bool receiverRunning; std::mutex receiverRunningMutex; CustomReader _reader; TcpSocket _sock; int _token; Codes::ISO _iso; Codes::Speed _speed; Loading @@ -48,19 +73,18 @@ private: Codes::ParamBracketingBuiltIn _bracketingBuiltIn; bool getToken(); bool getCameraSettings(); bool getJSON(DynamicJsonDocument& json, int& rval, Codes::MsgId expected_msg_id); void handleMsgId(DynamicJsonDocument& json); static bool str2int (const char* s, int& i, int base = 0); bool connect(); void disconnect(); void handleNotification(DynamicJsonDocument& json); std::string generateJSON(Codes::MsgId msg); bool shootBracketing(const std::vector<Codes::Speed>& speeds); template <typename T> std::string generateJSON(Codes::MsgId msg, T param); std::string generateJSON(Codes::MsgId msg); bool shootBracketing(const std::vector<Codes::Speed>& speeds); std::vector<Codes::Speed> speedOrder = { Loading sdk/src/customReader.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -2,14 +2,15 @@ using namespace std; CustomReader::CustomReader(TcpSocket* sock) : sock(sock) {}; CustomReader::CustomReader(){}; // Reads one byte, or returns -1 int CustomReader::read() { if (q.empty()) { string str; if (!sock->recv(str)) if (!sock->receive(str)) return -1; for (size_t i = 0; i < str.size(); ++i) Loading @@ -32,7 +33,7 @@ size_t CustomReader::readBytes(char* buffer, size_t length) while (q.size() < length) { std::string str; if (!sock->recv(str)) if (!sock->receive(str)) break; for (size_t i = 0; i < str.size(); ++i) Loading sdk/src/customReader.h +3 −1 Original line number Diff line number Diff line Loading @@ -4,9 +4,11 @@ #include <queue> #include "tcpSocket.h" class TcpSocket; struct CustomReader { CustomReader(TcpSocket* sock); CustomReader(); // Reads one byte, or returns -1 int read(); Loading Loading
sdk/src/codes.h +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ public: GetCameraSettings = 4364, GetCameraState = 4362, QuerySessionHolder = 1793, }; enum class ParamCameraState Loading
sdk/src/commander.cpp +133 −300 Original line number Diff line number Diff line #include <cerrno> #include <climits> #include <iostream> #include <vector> #include <thread> #include <unistd.h> #include "commander.h" #include <iostream> using namespace std; Commander::Commander() : _sock(TcpSocket(&_reader)), _token(0), _sock(TcpSocket()), _reader(CustomReader(&_sock)), _iso((Codes::ISO)-1), _speed((Codes::Speed)-1), Loading @@ -21,6 +22,7 @@ Commander::Commander() : _bracketingBuiltIn((Codes::ParamBracketingBuiltIn)-1) {}; string Commander::generateJSON(Codes::MsgId msg) { DynamicJsonDocument json(JSON_OBJECT_SIZE(2)); Loading @@ -33,6 +35,7 @@ string Commander::generateJSON(Codes::MsgId msg) return str; } template <typename T> string Commander::generateJSON(Codes::MsgId msg, T param) { Loading @@ -47,6 +50,7 @@ string Commander::generateJSON(Codes::MsgId msg, T param) return str; } template <> string Commander::generateJSON(Codes::MsgId msg, string param) { Loading @@ -61,200 +65,46 @@ string Commander::generateJSON(Codes::MsgId msg, string param) return str; } void Commander::handleMsgId(DynamicJsonDocument& json) { cout << "NOTIFICATION: "; //TODO: add more ids switch ((int)json["msg_id"]) { case (int)Codes::MsgId::GetCameraState: { cout << "Camera state: "; string key = "param"; if (!json.containsKey(key) || !json[key].is<int>()) cout << "invalid" << endl; else cout << Codes::stateToString(json[key]) << endl; break; } case (int)Codes::MsgId::GetSetMode: { cout << "Camera mode set to: "; string key = "param"; if (!json.containsKey(key) || !json[key].is<int>() || json[key] < 0 || json[key] > 1) cout << "invalid" << endl; else cout << (json[key] == (int)Codes::ParamMode::Video ? "video" : "photo" ) << endl; break; } default: cout << _reader.history << endl; break; } } bool Commander::getJSON(DynamicJsonDocument& json, int& rval, Codes::MsgId expected_msg_id) { // Get response for (int i = 0; i < 3; ++i) // make 3 attempts to receive json { _reader.resetHistory(); errno = 0; auto err = deserializeJson(json, _reader); if (errno == EAGAIN || errno == EWOULDBLOCK) { cerr << "recv timed out\n"; continue; } switch (err.code()) { case DeserializationError::Ok: break; case DeserializationError::NoMemory: //TODO cerr << "Error: couldn't parse JSON (" << err.c_str() << "): " << _reader.history << endl; return false; //these shouldn't happen case DeserializationError::InvalidInput: case DeserializationError::TooDeep: case DeserializationError::NotSupported: case DeserializationError::IncompleteInput: // this won't happen, as recv (deserializeJson) would time out cerr << "Error: couldn't parse JSON (" << err.c_str() << "): " << _reader.history << endl; cerr << "Restarting socket..."; _sock.close(); close(); connect(); //TODO: try again? return false; } string key = "msg_id"; if (!json.containsKey(key) || !json[key].is<int>()) { cerr << "Unexpected JSON response: " << _reader.history << endl; continue; } else if (json[key] != (int)expected_msg_id) { handleMsgId(json); continue; } key = "rval"; if (!json.containsKey(key) || !json[key].is<int>()) { //TODO: Handle message without rval cerr << "Error: unexpected rval (\"" << key << "\" = " << json[key] << ")" << endl; break; } rval = json[key]; return true; } return false; } bool Commander::str2int (const char* s, int& i, int base) { char *end; long l; errno = 0; l = strtol(s, &end, base); if (errno != 0 || *s == '\0' || *end != '\0' || l > INT_MAX || l < INT_MIN) return false; i = l; return true; } bool Commander::connect() { _sock.setTimeout(3); if (!_sock.connect("127.0.0.1", 7878) || !getToken() || !getCameraSettings()) return false; return true; } bool Commander::getToken() { if (!_sock.send(generateJSON(Codes::MsgId::GetToken))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::GetToken)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(Codes::MsgId::GetToken), jsonPtr, make_pair(Codes::MsgId::GetToken,Codes::Rval::CommandOk))) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<int>() || json[key] == 0) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _token = json[key]; _token = (*jsonPtr)[key]; return true; } bool Commander::getCameraSettings() { if (!_sock.send(generateJSON(Codes::MsgId::GetCameraSettings))) return false; DynamicJsonDocument json(JSON_OBJECT_SIZE(26) + 370); int rval; if (!getJSON(json, rval, Codes::MsgId::GetCameraSettings)) return false; switch(rval) bool Commander::getCameraSettings() { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(Codes::MsgId::GetCameraSettings), jsonPtr, make_pair(Codes::MsgId::GetCameraSettings,Codes::Rval::CommandOk))) return false; } string key = "still_iso"; if (!json.containsKey(key) || !json[key].is<int>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _iso = (Codes::ISO)(int)json[key]; _iso = (Codes::ISO)(int)(*jsonPtr)[key]; key = "still_shutter"; if (!json.containsKey(key) || !json[key].is<int>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<int>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } _speed = (Codes::Speed)(int)json[key]; _speed = (Codes::Speed)(int)(*jsonPtr)[key]; return true; } Loading Loading @@ -303,22 +153,9 @@ bool Commander::setBracketingBuiltIn(Codes::ParamBracketingBuiltIn bracketing) template <typename T> bool Commander::setParam(Codes::MsgId msgid, T param) { if (!_sock.send(generateJSON(msgid, (int)param))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, msgid)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(msgid, (int)param), jsonPtr, make_pair(msgid,Codes::Rval::CommandOk))) return false; } return true; } Loading @@ -326,47 +163,22 @@ bool Commander::setParam(Codes::MsgId msgid, T param) template <typename T> bool Commander::getParam(Codes::MsgId msgid, T& param_out) { if (!_sock.send(generateJSON(msgid))) return false; // Get response DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, msgid)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: shared_ptr<DynamicJsonDocument> jsonPtr; if (!_sock.sendRecvVerify(generateJSON(msgid), jsonPtr, make_pair(msgid,Codes::Rval::CommandOk))) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<T>()) if (!jsonPtr->containsKey(key) || !(*jsonPtr)[key].is<T>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*jsonPtr)[key] << endl; return false; } param_out = json[key]; param_out = (*jsonPtr)[key]; return true; } /** * Set commander's bracketing settings - * * Computes and saves 'halfCount' shutter speeds above and below currently set * shutter speed, so each two 'adjecent' speeds differ !APPROXIMATELY! by 'evStep' EV * (shutter speeds supported by camera does not always differ exactly by 1EV, * e.g. ... 1/3200s,1/2000s,1/1000s ... 1/4s,1s,2s ...) * * @param evStep number of exposure steps between two images * @param halfCount number of pictures to be taken above and below currently set exposure * @return true if setting was successful, otherwise false */ bool Commander::setBracketing(size_t evStep, size_t halfCount) { if (_bracketingStep != evStep || _bracketingHalfCount != halfCount) Loading Loading @@ -409,46 +221,25 @@ bool Commander::setBracketing(size_t evStep, size_t halfCount) bool Commander::shootNormal() { if (!_sock.send(generateJSON(Codes::MsgId::ShootNormal))) return false; // await "capture was enqueued" DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::ShootNormal)) return false; switch(rval) { case (int)Codes::Rval::CommandOk: break; default: return false; } // await "capture has finished" json = DynamicJsonDocument(JSON_OBJECT_SIZE(9) + 140); if (!getJSON(json, rval, Codes::MsgId::ImgCaptured)) return false; switch(rval) vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr; if (!_sock.sendRecvVerify( generateJSON(Codes::MsgId::ShootNormal), vectorJsonPtr, { case (int)Codes::Rval::NotificationOk: break; default: make_pair(Codes::MsgId::ShootNormal, Codes::Rval::CommandOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk) }) ) return false; } string key = "param"; if (!json.containsKey(key) || !json[key].is<string>()) if (!vectorJsonPtr[1]->containsKey(key) || !(*vectorJsonPtr[1])[key].is<string>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*vectorJsonPtr[1])[key] << endl; return false; } cout << "Image captured: " << json[key] << endl; cout << "Image captured: " << (*vectorJsonPtr[1])[key] << endl; return true; } Loading @@ -464,7 +255,7 @@ bool Commander::shootBracketing() if (!shootNormal()) return false; usleep(300000); //wait for 300ms this_thread::sleep_for(chrono::milliseconds(300)); } // set back shutter speed Loading @@ -474,68 +265,110 @@ bool Commander::shootBracketing() return true; } bool Commander::shootBracketingBuiltIn() { if (!_sock.send(generateJSON(Codes::MsgId::ShootBracketing))) return false; vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr; if (!_sock.sendRecvVerify( generateJSON(Codes::MsgId::ShootBracketing), vectorJsonPtr, { make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::CommandOk), make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), // await "bracketing was enqueued" DynamicJsonDocument json(minCapacity); int rval; if (!getJSON(json, rval, Codes::MsgId::ShootBracketing)) make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ShootBracketing, Codes::Rval::NotificationOk), make_pair(Codes::MsgId::ImgCaptured, Codes::Rval::NotificationOk), }) ) return false; switch(rval) for (int i = 2; i < 7; i+=2) { case (int)Codes::Rval::CommandOk: break; default: string key = "param"; if (!vectorJsonPtr[i]->containsKey(key) || !(*vectorJsonPtr[i])[key].is<string>()) { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << (*vectorJsonPtr[i])[key] << endl; return false; } string key = "param"; for (int i = 0; i < 3; ++i) cout << "Image captured: " << (*vectorJsonPtr[i])[key] << endl; } return true; } bool Commander::start() { json = DynamicJsonDocument(minCapacity); if (!getJSON(json, rval, Codes::MsgId::ShootBracketing)) receiverThr = thread(&Commander::runReceiver, this); this_thread::sleep_for(chrono::milliseconds(50)); if (!isReceiverRunning() || !getToken() || !getCameraSettings()) return false; switch(rval) return true; } void Commander::stop() { case (int)Codes::Rval::NotificationOk: break; default: return false; _sock.stopReceiver(); receiverThr.join(); } json = DynamicJsonDocument(JSON_OBJECT_SIZE(10) + 140); // await "capture has finished" if (!getJSON(json, rval, Codes::MsgId::ImgCaptured)) bool Commander::connect() { if (!_sock.connectTo("127.0.0.1", 7878)) return false; switch(rval) _sock.setTimeout(1); return true; } void Commander::disconnect() { case (int)Codes::Rval::NotificationOk: break; default: return false; _token = 0; _sock.closeSocket(); } if (!json.containsKey(key) || !json[key].is<string>()) bool Commander::isReceiverRunning() { cerr << "Error: unexpected JSON response: \"" << key << "\" = " << json[key] << endl; return false; lock_guard lock(receiverRunningMutex); return receiverRunning; } cout << "Image captured: " << json[key] << endl; bool Commander::runReceiver() { while (true) { if (!connect()) return false; { lock_guard lock(receiverRunningMutex); receiverRunning = true; } return true; if (_sock.runReceiver()) break; { lock_guard lock(receiverRunningMutex); receiverRunning = false; } //if TcpSocket::runReceiver() returns false, reconnect cerr << "Restarting socket..." << endl; disconnect(); } void Commander::close() { _token = 0; _sock.close(); lock_guard lock(receiverRunningMutex); receiverRunning = false; } return true; } No newline at end of file
sdk/src/commander.h +41 −17 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ #define COMMANDER_H #include <map> #include <queue> #include <memory> #include <vector> #include <thread> #include <ArduinoJson.h> Loading @@ -16,7 +17,7 @@ class Commander { public: Commander(); bool connect(); bool setISO(Codes::ISO iso); bool setSpeed(Codes::Speed speed); Loading @@ -25,20 +26,44 @@ public: template <typename T> bool setParam(Codes::MsgId msgid, T param); template <typename T> bool getParam(Codes::MsgId msgid, T& param_out); /** * Set commander's bracketing settings - * * Computes and saves 'halfCount' shutter speeds above and below currently set * shutter speed, so each two 'adjecent' speeds differ !APPROXIMATELY! by 'evStep' EV * (shutter speeds supported by camera does not always differ exactly by 1EV, * e.g. ... 1/3200s,1/2000s,1/1000s ... 1/4s,1s,2s ...) * * @param evStep number of exposure steps between two images * @param halfCount number of pictures to be taken above and below currently set exposure * @return true if setting was successful, otherwise false */ bool setBracketing(size_t evStep, size_t halfCount); bool shootNormal(); bool shootBracketing(); bool shootBracketingBuiltIn(); void close(); bool getToken(); bool getCameraSettings(); bool runReceiver(); bool stopReceiver(); bool isReceiverRunning(); bool start(); void stop(); private: const int minCapacity = (JSON_OBJECT_SIZE(5) + 50); int _token; TcpSocket _sock; std::thread receiverThr; bool receiverRunning; std::mutex receiverRunningMutex; CustomReader _reader; TcpSocket _sock; int _token; Codes::ISO _iso; Codes::Speed _speed; Loading @@ -48,19 +73,18 @@ private: Codes::ParamBracketingBuiltIn _bracketingBuiltIn; bool getToken(); bool getCameraSettings(); bool getJSON(DynamicJsonDocument& json, int& rval, Codes::MsgId expected_msg_id); void handleMsgId(DynamicJsonDocument& json); static bool str2int (const char* s, int& i, int base = 0); bool connect(); void disconnect(); void handleNotification(DynamicJsonDocument& json); std::string generateJSON(Codes::MsgId msg); bool shootBracketing(const std::vector<Codes::Speed>& speeds); template <typename T> std::string generateJSON(Codes::MsgId msg, T param); std::string generateJSON(Codes::MsgId msg); bool shootBracketing(const std::vector<Codes::Speed>& speeds); std::vector<Codes::Speed> speedOrder = { Loading
sdk/src/customReader.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -2,14 +2,15 @@ using namespace std; CustomReader::CustomReader(TcpSocket* sock) : sock(sock) {}; CustomReader::CustomReader(){}; // Reads one byte, or returns -1 int CustomReader::read() { if (q.empty()) { string str; if (!sock->recv(str)) if (!sock->receive(str)) return -1; for (size_t i = 0; i < str.size(); ++i) Loading @@ -32,7 +33,7 @@ size_t CustomReader::readBytes(char* buffer, size_t length) while (q.size() < length) { std::string str; if (!sock->recv(str)) if (!sock->receive(str)) break; for (size_t i = 0; i < str.size(); ++i) Loading
sdk/src/customReader.h +3 −1 Original line number Diff line number Diff line Loading @@ -4,9 +4,11 @@ #include <queue> #include "tcpSocket.h" class TcpSocket; struct CustomReader { CustomReader(TcpSocket* sock); CustomReader(); // Reads one byte, or returns -1 int read(); Loading