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

More comments, refactoring, renaming etc...

parent 337f7df7
Loading
Loading
Loading
Loading
Loading
−4 KiB (9.38 MiB)

File changed.

No diff preview for this file type.

+1 −4
Original line number Diff line number Diff line
#include "codes.h"
using namespace std;




using namespace std;

int Codes::getSpeedMs(Speed speed)
{
+1 −3
Original line number Diff line number Diff line
@@ -2,8 +2,6 @@
#define CODES_H

#include <string>
#include <algorithm>
#include <vector>

/**
 * Class containing various constant (and related functions) used for comunication with camera
@@ -40,7 +38,7 @@ public:
        QuerySessionHolder = 1793,

        PowerOff = 6155,
        GetSetAutoPowerOff = 6151, //TODO
        GetSetAutoPowerOff = 6151,

        CameraOverheated = 6158

+21 −23
Original line number Diff line number Diff line
#include <cerrno>
#include <climits>
#include <cmath>
#include <iostream>
#include <vector>
#include <thread>
#include <iterator>
#include <experimental/filesystem>

#include "commander.h"
#include "server.h"
#include "exif.h"

using namespace std;


Commander::Commander() :
    _isReceiverRunning(false),
    _sock(TcpSocket(&_reader, this)),
    _isReceiverEnabled(false),
    _sock(TcpSocket(this)),

    _bracketingStep(0),
    _bracketingHalfCount(0),
@@ -518,13 +516,13 @@ bool Commander::setPhotoWB(Codes::ParamWB wb)
    return true;
}

bool Commander::shootNormal()
bool Commander::shootNormal(bool notify)
{
    string path;
    return shootNormal(path);
    return shootNormal(notify, path);
}

bool Commander::shootNormal(string& imagePath, bool notify)
bool Commander::shootNormal(bool notify, string& imagePath)
{   
    cout << "Taking picture" << endl;
    vector<shared_ptr<DynamicJsonDocument>> vectorJsonPtr;
@@ -826,14 +824,14 @@ void Commander::runReceiver()
    {
        // wait until receiver should be running
        {
            unique_lock ulock(_isReceiverRunningMutex);
            _isReceiverRunningCV.wait(ulock, [this](){return _isReceiverRunning;});
            unique_lock ulock(_isReceiverEnabledMutex);
            _isReceiverEnabledCV.wait(ulock, [this](){return _isReceiverEnabled;});
        }

        // if cannot connect or _sock.runReceiver() exits correctly, stop receiver
        if (!connectSocket() || _sock.runReceiver())
        {
            stopReceiver();
            disableReceiver();
        }
        else
        {
@@ -844,27 +842,27 @@ void Commander::runReceiver()
    }
}

void Commander::startReceiver()
void Commander::enableReceiver()
{
    cout << "Starting receiver" << endl;
    lock_guard lock(_isReceiverRunningMutex);
    _isReceiverRunning = true;
    _isReceiverRunningCV.notify_all();
    lock_guard lock(_isReceiverEnabledMutex);
    _isReceiverEnabled = true;
    _isReceiverEnabledCV.notify_all();
}

void Commander::stopReceiver()
void Commander::disableReceiver()
{
    cout << "Stopping receiver" << endl;
    lock_guard lock(_isReceiverRunningMutex);
    _isReceiverRunning = false;
    lock_guard lock(_isReceiverEnabledMutex);
    _isReceiverEnabled = false;
    _server->wsClose();
}


bool Commander::isReceiverRunning()
bool Commander::isReceiverEnabled()
{
    lock_guard lock(_isReceiverRunningMutex); 
    return _isReceiverRunning;
    lock_guard lock(_isReceiverEnabledMutex); 
    return _isReceiverEnabled;
}


@@ -1057,7 +1055,7 @@ bool Commander::measureExposureExif(double& speed, double& iso)

    // Take one picture
    string path;
    if (!shootNormal(path, false))
    if (!shootNormal(false, path))
    {
        cerr << "Couldn't take photo." << endl;
        return false;
+151 −31
Original line number Diff line number Diff line
#ifndef COMMANDER_H
#define COMMANDER_H

#include <map>
#include <queue>
#include <memory>
#include <thread>
@@ -9,24 +8,51 @@
#include <ArduinoJson.h>

#include "tcpSocket.h"
#include "customReader.h"
#include "codes.h"
#include "server.h"

class Server;

/**
 * Class responsible for running commands received from user on the cammera.
 * Enqueues commands from user, send commands to cammera, checks responses
 * and stores information about camera state.
 * 
 * To be able to run properly, one has to create also an instance of class Server and give it
 * a pointer to the Commander instance, then start both instances by running start() method on them
 */
class Commander
{
public:
    /**
     * Construct new Commander
     */
    Commander();

    /**
     * Start executing commands from user and reading response from camera. 
     * An instance of Commander can do nothing until an instance of Server (with pointer to Commander)
     * has been created and started by running its start() method
     */
    void start();

    void startReceiver();
    void stopReceiver();

    /**
     * 
     * Check whether commander is shooting
     * 
     * @return true iff commander is currently executing a shooting command
     */
    bool isShooting();

    /**
     * Push a command in the queue.
     * 
     * @param cmd String containing command in one of following formats:
     * @param cmd {"cmd": "APP_OFF"} - Disconnect the MiPhoto app from the camera. 
     * @param cmd {"cmd": "POWER_OFF"} - Turn camera off. 
     * @param cmd {"cmd": "WIFI_OFF"} - Turn off WiFi. 
     * @param cmd {"cmd": "STOP"} - Stop shooting. 
     * @param cmd {"cmd": "SHOOT", "speed":_, "iso":_, "bracketingHalf":_, "bracketingEV":_, "timelapseCount":_, "timelapseInterval":_, "photoWB":_} - Shoot.
     */
    void enqueueCommand(const std::string& cmd);

private:
@@ -34,19 +60,20 @@ private:
    friend class TcpSocket;

    std::thread _receiverThr; // thread for receiving messages from camera
    bool _isReceiverRunning;
    std::mutex _isReceiverRunningMutex;
    std::condition_variable _isReceiverRunningCV;

    std::thread _executorThr; // thread for executiong commands from user
    std::queue<std::shared_ptr<DynamicJsonDocument>> _executorQueue;
    bool _isReceiverEnabled;
    std::mutex _isReceiverEnabledMutex;
    std::condition_variable _isReceiverEnabledCV;

    std::thread _executorThr; // thread executiong commands from user

    std::queue<std::shared_ptr<DynamicJsonDocument>> _executorQueue; //Queue with commands
    std::mutex _executorQueueMutex;
    std::condition_variable _executorQueueCV;

    CustomReader _reader;
    TcpSocket _sock;
    int _token;
    int _autoPowerOff;
    TcpSocket _sock;    // Scoket for comunication with the camera
    int _token;         // Token used to identify connection with camera
    int _autoPowerOff;  // Time in minutes before camera turns off when idle

    Codes::ISO _iso;
    Codes::Speed _speed;
@@ -54,9 +81,13 @@ private:
    Codes::ParamMode _mode;

    size_t _bracketingStep;
    size_t _bracketingHalfCount;
    bool _bracketingVectorInvalid;;
    std::vector<Codes::Speed> _bracketingVector;
    size_t _bracketingHalfCount;    // number of pictures taken with bracketing is '2 * _bracketingHalfCount + 1'
    /**
     * Indicate that _bracketingVector has to be recomputed 
     * (i.e. shutter speed or any parameter of bracketing changes, or shutter speed is auto)
     */
    bool _bracketingVectorInvalid;
    std::vector<Codes::Speed> _bracketingVector; // vector containing shutter speeds used for bracketing

    Codes::ParamBracketingBuiltIn _bracketingBuiltIn;

@@ -66,6 +97,7 @@ private:
    bool _isShooting;
    std::mutex _isShootingMutex;

    // Flag telling commander to stop shooting
    bool _stopShooting;
    std::mutex _stopShootingMutex;
    std::condition_variable _stopShootingCV;
@@ -78,36 +110,82 @@ private:
    static std::vector<std::pair<Codes::ISO, double>> isoOrderedMapping;


    // Blocking function which starts executing commands from _executorQueue
    void runExecutor();

    /**
     * Start shooting with parameters given by json
     * 
     * @param json contains parameters for shooting
     * @return true iff shooting was successful
     */
    bool executorShoot(std::shared_ptr<DynamicJsonDocument> json);

    // Blocking function which starts receiving messages from camera
    void runReceiver();


    bool isReceiverEnabled();
    
    // Enable receiving messages from camera via socket
    void enableReceiver();

    // Disable receiving messages from camera via socket
    void disableReceiver();


    /**
     * Create socket and connect to camera
     * 
     * @return true iff connecting was successful
     */
    bool connectSocket();

    // Close socket used for communication with camera
    void disconnectSocket();


    /**
     * Estabilish connection with commander by "handshaking"
     * (i.e. request a token from camera & get required settings)
     * 
     * @return true iff connecting was successful
     */
    bool connectCommander();
    void disconnectCommander();
    void invalidateCachedSettings();

    void runExecutor();
    bool executorShoot(std::shared_ptr<DynamicJsonDocument> json);

    void runReceiver();
    bool isReceiverRunning();
    // Invalidate camera settings that are stored locally
    void invalidateCachedSettings();

    /**
     * Generate string with json in format:
     * {"token":_token, "msg_id": msg, "param":param}
     */
    template <typename T>
    std::string generateJSON(Codes::MsgId msg, T param);
    std::string generateJSON(Codes::MsgId msg);
    
    /**
     * Generate string with json in format:
     * {"token":_token, "msg_id": msg}
     */
    std::string generateJSON(Codes::MsgId msg);

    ////// Commands //////¨

    ////////// Commands //////////
    bool shoot();

    // set the _stopShooting variable
    void stopShooting(bool stop = true);

    // turn off/on wifi
    bool wifiControl(bool on);
    bool powerOff();
    bool setAutoPowerOff(size_t minutes);
    bool getAutoPowerOff();

    bool shootNormal();
    bool shootNormal(std::string& imagePath, bool notify = true);
    // take single picture
    bool shootNormal(bool notify = true);
    bool shootNormal(bool notify, std::string& imagePath);
    bool shootBracketing();

    bool shootBracketing(const std::vector<Codes::Speed>& speeds);
@@ -128,13 +206,27 @@ private:
    bool setPhotoWB(Codes::ParamWB wb);
    bool setMode(Codes::ParamMode mode);

    /**
     * Request a token from camera and save it.
     * Token will then be used as identifiaction for every message between camera & commander
     * 
     * @return true iff request was successful
     */
    bool getToken();

    /**
     * Request common settings from camera and save them.
     * Currently only ISO and shutter speed is being saved.
     * 
     * @return true iff getting settings was successful
     */
    bool getCameraSettings();
    bool getMode();
    bool getAutoTurnOff();//TODO
    bool getMode(); // Photo/video

    // send message that reassures the camera that we sill want to be connected
    bool holdSession();

    //////////////////////////////

    /**
    * Set commander's bracketing settings
@@ -174,17 +266,45 @@ private:
        size_t halfCount,
        size_t evStep);

    /**
     * Take picture, read ISO & speed from exif data
     * 
     * @param speed 
     * @param iso 
     * @return true iff measuring was successful
     */
    bool measureExposureExif(double& speed, double& iso);


    /**
     * Find supported speed that is closest to the one passed as parameter.
     * Speed if first adjusted by 'inputError' exposure steps, then the closest supported one is found.
     * 
     * @param speed Speed we want to find between the supported ones
     * @param inputError exposure steps to adjust the speed before search
     * @param outputError The difference [in exposure steps] between adjusted speed and the selected one
     * @return iterator to the speed found in speedOrderedMapping
     */
    std::vector<std::pair<Codes::Speed, double>>::iterator findClosestSpeed(
        double speed,
        double inputError,
        double& outputError);

    /**
     * Find supported ISO that is closest to the one passed as parameter.
     * ISO if first adjusted by 'inputError' exposure steps, then closest supported one is found.
     * 
     * @param iso ISO we want to find between the supported ones
     * @param inputError exposure steps to adjust the ISO before search
     * @param outputError The difference [in exposure steps] between adjusted ISO and the selected one
     * @return iterator to the speed found in isoOrderedMapping
     */
    std::vector<std::pair<Codes::ISO, double>>::iterator findClosestISO(
        double iso,
        double inputError,
        double& outputError);

    // check if vector iterator is in valid range
    // check if vector iterator is in valid range [begin, end)
    template <typename T>
    inline static bool isValidIter(typename std::vector<T>::iterator it, const std::vector<T>& vector)
    {
Loading