Commit c3a6ede0 authored by Martin Cífka's avatar Martin Cífka
Browse files

Commander now executes commands asynchronously from the queue

parent 21fb1fd8
Loading
Loading
Loading
Loading
Loading
+107 −4
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ bool Commander::getCameraSettings()

bool Commander::setISO(Codes::ISO iso)
{
    cout << "Setting ISO" << endl;
    if (_iso != iso)
    {
        if (setParam(Codes::MsgId::GetSetISO, iso))
@@ -126,12 +127,14 @@ bool Commander::setISO(Codes::ISO iso)
            return false;
        
    }
    cout << "ISO set" << endl;
    return true;
}


bool Commander::setSpeed(Codes::Speed speed)
{
    cout << "Setting speed" << endl;
    if (_speed != speed)
    {
        if (setParam(Codes::MsgId::GetSetSpeed, speed))
@@ -139,6 +142,7 @@ bool Commander::setSpeed(Codes::Speed speed)
        else
            return false;
    }
    cout << "Speed set" << endl;
    return true;
}

@@ -219,6 +223,7 @@ bool Commander::setBracketing(size_t evStep, size_t halfCount)
        }
    }
    
    cout << "Bracketing set" << endl;
    return true;
}

@@ -227,11 +232,13 @@ void Commander::setTimelapse(size_t interval, size_t count)
{
    _timelapseInterval = interval;
    _timelapseCount = count;
    cout << "Timelapse set" << endl;
}


bool Commander::shootNormal()
{
    cout << "Taking picture" << endl;
    vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr;
    if (!_sock.sendRecvVerify(
            generateJSON(Codes::MsgId::ShootNormal),
@@ -256,6 +263,7 @@ bool Commander::shootNormal()

bool Commander::shootBracketing()
{
    cout <<  endl << "***** Start shooting bracketing *****" << endl;
    auto s = _speed;
    
    // shoot bracketing
@@ -283,6 +291,7 @@ bool Commander::shootBracketing()
    if (!setSpeed(s))
        return false;
    
    cout << endl <<  "==== Bracketing done =====" << endl;
    return true;
}

@@ -325,6 +334,7 @@ bool Commander::shootBracketingBuiltIn()

bool Commander::shootTimelapse(bool bracketing)
{
    cout << endl <<  "***** Start shooting timelapse  *****" << endl;
    auto interval = chrono::seconds(_timelapseInterval);
    auto next = chrono::steady_clock::now();
    
@@ -333,9 +343,15 @@ bool Commander::shootTimelapse(bool bracketing)
        next += interval;
        
        if (bracketing)
            shootBracketing();
        {
            if (!shootBracketing())
                return false;
        }
        else
            shootNormal();
        {
            if (!shootNormal())
                return false;
        }
        
        unique_lock lock(_stopShootingMutex);
        if (_stopShootingCV.wait_until(lock, next, [this](){return _stopShooting;}))
@@ -346,6 +362,7 @@ bool Commander::shootTimelapse(bool bracketing)
        }
        // else (timeout): continue shooting
    }
    cout << endl << "===== Timelapse done =====" << endl;
    return true;
}

@@ -382,6 +399,7 @@ bool Commander::shoot()
bool Commander::start()
{
    _receiverThr = thread(&Commander::runReceiver, this);
    _executorThr = thread(&Commander::runExecutor, this);
    this_thread::sleep_for(chrono::milliseconds(50));
    
    if (!isReceiverRunning() || !getToken() || !getCameraSettings())
@@ -389,10 +407,10 @@ bool Commander::start()
    
    return true;
}
void Commander::stop()
void Commander::join()
{
    _sock.stopReceiver();
    _receiverThr.join();
    _executorThr.join();
}

bool Commander::connect()
@@ -447,5 +465,90 @@ bool Commander::runReceiver()
    _receiverRunning = false;
    }
    
    disconnect();
    
    return true;
}


void Commander::enqueueCommand(std::string cmd)
{
    lock_guard lock(_executorQueueMutex);
    _executorQueue.push(cmd);
    cout << "(Enqueued: " << cmd << ")" << endl;
    _executorQueueCV.notify_all();
}


void Commander::runExecutor()
{
    while (true)
    {
        string msg;
        {
            // wait until some command is in the queue
            unique_lock lock(_executorQueueMutex);
            _executorQueueCV.wait(lock, [this](){
                if (_executorQueue.empty())
                    {cout << "EXECUTOR GOING TO SLEEP..." << endl; return false;}
                else
                    return true;
            });
            msg = move(_executorQueue.front());
            _executorQueue.pop();
        }
        cout << endl << "Executing: " << msg << endl;
        DynamicJsonDocument json(JSON_OBJECT_SIZE(7+90)); //TODO: find needed json capacity
        auto err = deserializeJson(json, msg);
        
        
        if (err)
        {
            cerr << err.c_str() << " : " << msg << endl; 
            continue;
        }
        
        string key = "cmd";
        if(!json[key].is<string>())
        {
            cerr << "Invalid data from user: " << msg << endl; 
            continue;
        }
        
        
        if (json[key] == "SHOOT")
        {
            if (!(json["speed"].is<int>() &&
                  json["iso"].is<int>() &&
                  json["bracketingHalf"].is<int>() &&
                  json["bracketingEV"].is<int>() && 
                  json["timelapseCount"].is<int>() &&
                  json["timelapseInterval"].is<int>()))
                  // whitebalance
                  // compensation
                  //
            {
                cerr << "Invalid data from user: " << msg << endl; 
                continue;
            }
            if ( !(setISO((Codes::ISO)(int)json["iso"]) && setSpeed((Codes::Speed)(int)json["speed"])))
            {
                //TODO: send warning
                continue;
            }
            setBracketing((int)json["bracketingEV"], (int)json["bracketingHalf"]);
            setTimelapse((int)json["timelapseInterval"], (int)json["timelapseCount"]);

            if (!shoot())
            {
                //TODO: send warning
            }

        }
        else
        {
            
        }
        
    }
}
 No newline at end of file
+48 −38
Original line number Diff line number Diff line
@@ -18,49 +18,21 @@ class Commander
public:
    Commander();
    
    
    bool setISO(Codes::ISO iso);
    bool setSpeed(Codes::Speed speed);
    bool setBracketingBuiltIn(Codes::ParamBracketingBuiltIn);
    
    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);
    void setTimelapse(size_t interval, size_t count);
    
    void stopShooting();//TODO
    bool shoot();
    
    bool getToken();
    bool getCameraSettings();
    
    
    bool runReceiver();
    bool stopReceiver();
    bool isReceiverRunning();
    
    bool start();
    void stop();
    void join();

    void enqueueCommand(std::string cmd);
    
private:
    std::thread _receiverThr;
    bool _receiverRunning;
    std::mutex _receiverRunningMutex;
    
    std::thread _executorThr;
    std::queue<std::string> _executorQueue;
    std::mutex _executorQueueMutex;
    std::condition_variable _executorQueueCV;
    
    CustomReader _reader;
    TcpSocket _sock;
    int _token;
@@ -82,22 +54,60 @@ private:
    std::condition_variable _stopShootingCV;
    
    
    
    
    
    
    
    
    bool connect();
    void disconnect();
    
    void handleNotification(DynamicJsonDocument& json);
    void runExecutor();
    bool runReceiver();
    bool isReceiverRunning();
    
    bool shoot();
    void stopShooting();//TODO
    
    bool shootNormal();
    bool shootBracketing();
    
    bool shootBracketing(const std::vector<Codes::Speed>& speeds);
    bool shootBracketingBuiltIn();
    bool shootTimelapse(bool bracketing);
    
    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 setBracketingBuiltIn(Codes::ParamBracketingBuiltIn);
    bool setISO(Codes::ISO iso);
    bool setSpeed(Codes::Speed speed);
    void setTimelapse(size_t interval, size_t count);
    
    bool getToken();
    bool getCameraSettings();
    
    
    
    template <typename T>
    std::string generateJSON(Codes::MsgId msg, T param);
    std::string generateJSON(Codes::MsgId msg);
    

    std::vector<Codes::Speed> speedOrder =
    {
        Codes::Speed::S1_6400,
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <queue>
#include "tcpSocket.h"
//#include "App.h"

class TcpSocket;

+4 −18
Original line number Diff line number Diff line
@@ -9,24 +9,10 @@ using namespace std;
int main(int argc , char *argv[])
{
    Commander comm;
    comm.start() &&
    comm.setISO(Codes::ISO::Auto)
            && cout << "====== ISO set ======\n\n" &&
    comm.setSpeed(Codes::Speed::S1_120)
            && cout << "===== Speed set =====\n\n";
    comm.start();
    
    comm.setBracketing(1, 1)
        && cout << "====== Bracketing set =====\n\n";
    comm.setTimelapse(10, 3);
    cout << "====== Timelapse set =====\n\n";
    comm.enqueueCommand("{\"cmd\":\"SHOOT\",\"speed\":32772,\"iso\":100,\"bracketingHalf\":1,\"bracketingEV\":1,\"timelapseCount\":2,\"timelapseInterval\":5}");
    comm.enqueueCommand("{\"cmd\":\"SHOOT\",\"speed\":32772,\"iso\":100,\"bracketingHalf\":1,\"bracketingEV\":1,\"timelapseCount\":2,\"timelapseInterval\":5}");
    
    comm.shoot()
        && cout << "====== Bracketing OK =====\n\n";
    
    /*comm.setBracketingBuiltIn(Codes::ParamBracketingBuiltIn::EV2)
        && cout << "====== Bracketing set =====\n\n" &&
    comm.shootBracketingBuiltIn()
        && cout << "====== Bracketing OK =====\n\n";*/
    
    comm.stop();
    comm.join();
}
 No newline at end of file
+10 −4
Original line number Diff line number Diff line
@@ -46,12 +46,15 @@ void TcpSocket::setTimeout(int sec, int microsec)

bool TcpSocket::sendString(const string& msg)
{
    errno = 0;
    if(net::send(_socket_desc , msg.c_str(), msg.size(), 0) < 0)
    {
        cerr << "send failed\n";
        cerr << "send failed: " << msg << endl;
        cout << "errno = " << errno << endl;
        return false;
    }
    cout << "    Sent: " << msg << endl;
    
    return true;
}

@@ -101,7 +104,9 @@ size_t attempts
            cerr << "trying again\n\n";
        
        if (!sendString(msg))
        {
            continue;
        }
        
        unique_lock ulock(recvQueueMutex);
        if (!recvQueueCV.wait_for(ulock, wait, [this](){return !recvQueue.empty();} ))
@@ -427,5 +432,6 @@ bool TcpSocket::runReceiver()
            }
        }//unlock revExpectedMutex
    }//while
    
    return true;
}
 No newline at end of file