Compare commits
	
		
			66 Commits
		
	
	
		
			v2
			...
			galtuer-fi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c153652b3d | |||
| d7e185006f | |||
| c3c888dc04 | |||
| 2ecaa0545f | |||
| a849f953bd | |||
| 24df8e995a | |||
| b5f818848a | |||
| fc94e603c5 | |||
| bc00d25ded | |||
| 4e783ee6fd | |||
| 34fbefc138 | |||
| 48fccafe76 | |||
| 9394625d35 | |||
| 7492e37e02 | |||
| f0dca3917c | |||
| 57ccbc150a | |||
| 8fa4335669 | |||
| 49298a1821 | |||
| 6fb4d245cb | |||
| 2dc93271fd | |||
| 5be5798681 | |||
| 1a24bc4572 | |||
| 068575f8e8 | |||
| e121cef17e | |||
| bdaea1106c | |||
| bc17213597 | |||
| 64b2b4bd85 | |||
| 8737508839 | |||
| 02f0500eac | |||
| 2d53224feb | |||
| 38964ad9a8 | |||
| d3f18f3b82 | |||
| 1a4265372e | |||
| eb20410849 | |||
| 2a492475e3 | |||
| 6a5272da7a | |||
| 4d5583df2d | |||
| de6f263817 | |||
| e4ce14da3f | |||
| b71c979a91 | |||
| 33f43fb83d | |||
| 1606a784a4 | |||
| 9f2cf613e1 | |||
| dbd9644047 | |||
| f8fef12b55 | |||
| 1dd81d4a56 | |||
| f93cf11d23 | |||
| 9d0ac4f8ce | |||
| 4ec5589f30 | |||
| c1d5ffcf3c | |||
| 7aded2b7fb | |||
| ed9e60a972 | |||
| 5d35331c83 | |||
| c7623429d9 | |||
| b596086245 | |||
| 24ca857b6f | |||
| ea0bcde413 | |||
| e93b08505a | |||
| 44efd44ede | |||
| 9d72574106 | |||
| d8ec41ebfc | |||
| f17c4f240b | |||
| 76bb1eb56a | |||
| 3b813e5eff | |||
| 436f5a109b | |||
| e17e54b315 | 
@@ -42,18 +42,34 @@ struct CALCULATE_LIBRARY_API price_t {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CALCULATE_LIBRARY_API CalcState {
 | 
					struct CALCULATE_LIBRARY_API CalcState {
 | 
				
			||||||
 | 
					    static QString const SUCCESS;
 | 
				
			||||||
 | 
					    static QString const ERROR_PARSING_ZONE_NR;
 | 
				
			||||||
 | 
					    static QString const ERROR_LOADING_TARIFF;
 | 
				
			||||||
 | 
					    static QString const ERROR_PARSING_TARIFF;
 | 
				
			||||||
 | 
					    static QString const NEGATIVE_PARKING_TIME;
 | 
				
			||||||
 | 
					    static QString const INVALID_START_DATE;
 | 
				
			||||||
 | 
					    static QString const WRONG_PARAM_VALUES;
 | 
				
			||||||
 | 
					    static QString const WRONG_ISO_TIME_FORMAT;
 | 
				
			||||||
 | 
					    static QString const ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
 | 
					    static QString const BELOW_MIN_PARKING_TIME;
 | 
				
			||||||
 | 
					    static QString const BELOW_MIN_PARKING_PRICE;
 | 
				
			||||||
 | 
					    static QString const ABOVE_MAX_PARKING_PRICE;
 | 
				
			||||||
 | 
					    static QString const OVERPAID;
 | 
				
			||||||
 | 
					    static QString const OUTSIDE_ALLOWED_PARKING_TIME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enum class State : uint8_t {
 | 
					    enum class State : uint8_t {
 | 
				
			||||||
        SUCCESS,
 | 
					        SUCCESS,
 | 
				
			||||||
        ERROR_PARSING_ZONE_NR,
 | 
					        ERROR_PARSING_ZONE_NR,
 | 
				
			||||||
        ERROR_LOADING_TARIFF,
 | 
					        ERROR_LOADING_TARIFF,
 | 
				
			||||||
        ERROR_PARSING_TARIFF,
 | 
					        ERROR_PARSING_TARIFF,
 | 
				
			||||||
        NEGATIVE_PARING_TIME,
 | 
					        NEGATIVE_PARKING_TIME,
 | 
				
			||||||
        INVALID_START_DATE,
 | 
					        INVALID_START_DATE,
 | 
				
			||||||
        WRONG_PARAM_VALUES,
 | 
					        WRONG_PARAM_VALUES,
 | 
				
			||||||
        WRONG_ISO_TIME_FORMAT,
 | 
					        WRONG_ISO_TIME_FORMAT,
 | 
				
			||||||
        ABOVE_MAX_PARKING_TIME,
 | 
					        ABOVE_MAX_PARKING_TIME,
 | 
				
			||||||
        BELOW_MIN_PARKING_TIME,
 | 
					        BELOW_MIN_PARKING_TIME,
 | 
				
			||||||
        BELOW_MIN_PARKING_PRICE,
 | 
					        BELOW_MIN_PARKING_PRICE,
 | 
				
			||||||
 | 
					        ABOVE_MAX_PARKING_PRICE,
 | 
				
			||||||
        OVERPAID,
 | 
					        OVERPAID,
 | 
				
			||||||
        OUTSIDE_ALLOWED_PARKING_TIME
 | 
					        OUTSIDE_ALLOWED_PARKING_TIME
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -88,96 +104,153 @@ struct CALCULATE_LIBRARY_API CalcState {
 | 
				
			|||||||
        QString s;
 | 
					        QString s;
 | 
				
			||||||
        switch (m_status) {
 | 
					        switch (m_status) {
 | 
				
			||||||
        case State::SUCCESS:
 | 
					        case State::SUCCESS:
 | 
				
			||||||
            s = "SUCCESS";
 | 
					            s = CalcState::SUCCESS;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_PARSING_ZONE_NR:
 | 
					        case State::ERROR_PARSING_ZONE_NR:
 | 
				
			||||||
            s = "ERROR_PARSING_ZONE_NR";
 | 
					            s = CalcState::ERROR_PARSING_ZONE_NR;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_LOADING_TARIFF:
 | 
					        case State::ERROR_LOADING_TARIFF:
 | 
				
			||||||
            s = "ERROR_LOADING_TARIFF";
 | 
					            s = CalcState::ERROR_LOADING_TARIFF;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_PARSING_TARIFF:
 | 
					        case State::ERROR_PARSING_TARIFF:
 | 
				
			||||||
            s = "ERROR_PARSING_TARIFF";
 | 
					            s = CalcState::ERROR_PARSING_TARIFF;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::NEGATIVE_PARING_TIME:
 | 
					        case State::NEGATIVE_PARKING_TIME:
 | 
				
			||||||
            s = "NEGATIVE_PARKING_TIME";
 | 
					            s = CalcState::NEGATIVE_PARKING_TIME;
 | 
				
			||||||
           break;
 | 
					           break;
 | 
				
			||||||
        case State::ABOVE_MAX_PARKING_TIME:
 | 
					        case State::ABOVE_MAX_PARKING_TIME:
 | 
				
			||||||
            s = "ABOVE_MAX_PARKING_TIME";
 | 
					            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::WRONG_PARAM_VALUES:
 | 
					        case State::WRONG_PARAM_VALUES:
 | 
				
			||||||
            s = "WRONG_PARAM_VALUES";
 | 
					            s = CalcState::WRONG_PARAM_VALUES;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::BELOW_MIN_PARKING_TIME:
 | 
					        case State::BELOW_MIN_PARKING_TIME:
 | 
				
			||||||
            s = "BELOW_MIN_PARKING_TIME";
 | 
					            s = CalcState::BELOW_MIN_PARKING_TIME;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::BELOW_MIN_PARKING_PRICE:
 | 
					        case State::BELOW_MIN_PARKING_PRICE:
 | 
				
			||||||
            s = "BELOW_MIN_PARKING_PRICE";
 | 
					            s = CalcState::BELOW_MIN_PARKING_PRICE;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::OVERPAID:
 | 
					        case State::OVERPAID:
 | 
				
			||||||
            s = "OVERPAID";
 | 
					            s = CalcState::OVERPAID;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::INVALID_START_DATE:
 | 
					        case State::INVALID_START_DATE:
 | 
				
			||||||
            s = "INVALID_START_DATE";
 | 
					            s = CalcState::INVALID_START_DATE;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::WRONG_ISO_TIME_FORMAT:
 | 
					        case State::WRONG_ISO_TIME_FORMAT:
 | 
				
			||||||
            s = "WRONG_ISO_TIME_FORMAT";
 | 
					            s = CalcState::WRONG_ISO_TIME_FORMAT;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::OUTSIDE_ALLOWED_PARKING_TIME:
 | 
					        case State::OUTSIDE_ALLOWED_PARKING_TIME:
 | 
				
			||||||
            s = "OUTSIDE_ALLOWED_PARKING_TIME";
 | 
					            s = CalcState::OUTSIDE_ALLOWED_PARKING_TIME;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case State::ABOVE_MAX_PARKING_PRICE:
 | 
				
			||||||
 | 
					            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (m_desc.size() > 0) {
 | 
				
			||||||
            return s + ":" + m_desc;
 | 
					            return s + ":" + m_desc;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        return s;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    explicit operator QString () const noexcept {
 | 
					    explicit operator QString () const noexcept {
 | 
				
			||||||
        QString s;
 | 
					        QString s;
 | 
				
			||||||
        switch (m_status) {
 | 
					        switch (m_status) {
 | 
				
			||||||
        case State::SUCCESS:
 | 
					        case State::SUCCESS:
 | 
				
			||||||
            s = "SUCCESS";
 | 
					            s = CalcState::SUCCESS;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_PARSING_ZONE_NR:
 | 
					        case State::ERROR_PARSING_ZONE_NR:
 | 
				
			||||||
            s = "ERROR_PARSING_ZONE_NR";
 | 
					            s = CalcState::ERROR_PARSING_ZONE_NR;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_LOADING_TARIFF:
 | 
					        case State::ERROR_LOADING_TARIFF:
 | 
				
			||||||
            s = "ERROR_LOADING_TARIFF";
 | 
					            s = CalcState::ERROR_LOADING_TARIFF;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::ERROR_PARSING_TARIFF:
 | 
					        case State::ERROR_PARSING_TARIFF:
 | 
				
			||||||
            s = "ERROR_PARSING_TARIFF";
 | 
					            s = CalcState::ERROR_PARSING_TARIFF;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::NEGATIVE_PARING_TIME:
 | 
					        case State::NEGATIVE_PARKING_TIME:
 | 
				
			||||||
            s = "NEGATIVE_PARKING_TIME";
 | 
					            s = CalcState::NEGATIVE_PARKING_TIME;
 | 
				
			||||||
           break;
 | 
					           break;
 | 
				
			||||||
        case State::ABOVE_MAX_PARKING_TIME:
 | 
					        case State::ABOVE_MAX_PARKING_TIME:
 | 
				
			||||||
            s = "ABOVE_MAX_PARKING_TIME";
 | 
					            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::WRONG_PARAM_VALUES:
 | 
					        case State::WRONG_PARAM_VALUES:
 | 
				
			||||||
            s = "WRONG_PARAM_VALUES";
 | 
					            s = CalcState::WRONG_PARAM_VALUES;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::BELOW_MIN_PARKING_TIME:
 | 
					        case State::BELOW_MIN_PARKING_TIME:
 | 
				
			||||||
            s = "BELOW_MIN_PARKING_TIME";
 | 
					            s = CalcState::BELOW_MIN_PARKING_TIME;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::BELOW_MIN_PARKING_PRICE:
 | 
					        case State::BELOW_MIN_PARKING_PRICE:
 | 
				
			||||||
            s = "BELOW_MIN_PARKING_PRICE";
 | 
					            s = CalcState::BELOW_MIN_PARKING_PRICE;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::OVERPAID:
 | 
					        case State::OVERPAID:
 | 
				
			||||||
            s = "OVERPAID";
 | 
					            s = CalcState::OVERPAID;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::INVALID_START_DATE:
 | 
					        case State::INVALID_START_DATE:
 | 
				
			||||||
            s = "INVALID_START_DATE";
 | 
					            s = CalcState::INVALID_START_DATE;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::WRONG_ISO_TIME_FORMAT:
 | 
					        case State::WRONG_ISO_TIME_FORMAT:
 | 
				
			||||||
            s = "WRONG_ISO_TIME_FORMAT";
 | 
					            s = CalcState::WRONG_ISO_TIME_FORMAT;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case State::OUTSIDE_ALLOWED_PARKING_TIME:
 | 
					        case State::OUTSIDE_ALLOWED_PARKING_TIME:
 | 
				
			||||||
            s = "OUTSIDE_ALLOWED_PARKING_TIME";
 | 
					            s = CalcState::OUTSIDE_ALLOWED_PARKING_TIME;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case State::ABOVE_MAX_PARKING_PRICE:
 | 
				
			||||||
 | 
					            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return s + ":" + m_desc;
 | 
					        return s + ":" + m_desc;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CalcState &set(State s) { m_status = s; return *this; }
 | 
					    CalcState &set(State s) { m_status = s; return *this; }
 | 
				
			||||||
    CalcState &setStatus(State s) { return set(s); }
 | 
					    CalcState &setStatus(State s) { return set(s); }
 | 
				
			||||||
 | 
					    CalcState &setStatus(QString const &desc) {
 | 
				
			||||||
 | 
					        if (desc == SUCCESS) {
 | 
				
			||||||
 | 
					            m_status = State::SUCCESS;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == ERROR_PARSING_ZONE_NR) {
 | 
				
			||||||
 | 
					            m_status = State::ERROR_PARSING_ZONE_NR;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == ERROR_LOADING_TARIFF) {
 | 
				
			||||||
 | 
					            m_status = State::SUCCESS;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == ERROR_PARSING_TARIFF) {
 | 
				
			||||||
 | 
					            m_status = State::ERROR_LOADING_TARIFF;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == NEGATIVE_PARKING_TIME) {
 | 
				
			||||||
 | 
					            m_status = State::NEGATIVE_PARKING_TIME;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == INVALID_START_DATE) {
 | 
				
			||||||
 | 
					            m_status = State::INVALID_START_DATE;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == WRONG_PARAM_VALUES) {
 | 
				
			||||||
 | 
					            m_status = State::WRONG_PARAM_VALUES;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == WRONG_ISO_TIME_FORMAT) {
 | 
				
			||||||
 | 
					            m_status = State::WRONG_ISO_TIME_FORMAT;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == ABOVE_MAX_PARKING_TIME) {
 | 
				
			||||||
 | 
					            m_status = State::ABOVE_MAX_PARKING_TIME;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == BELOW_MIN_PARKING_TIME) {
 | 
				
			||||||
 | 
					            m_status = State::BELOW_MIN_PARKING_TIME;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == BELOW_MIN_PARKING_PRICE) {
 | 
				
			||||||
 | 
					            m_status = State::BELOW_MIN_PARKING_PRICE;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == OVERPAID) {
 | 
				
			||||||
 | 
					            m_status = State::OVERPAID;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
				
			||||||
 | 
					            m_status = State::OUTSIDE_ALLOWED_PARKING_TIME;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (desc == ABOVE_MAX_PARKING_PRICE) {
 | 
				
			||||||
 | 
					            m_status = State::ABOVE_MAX_PARKING_PRICE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    State getStatus() const { return m_status; }
 | 
					    State getStatus() const { return m_status; }
 | 
				
			||||||
    CalcState &setDesc(QString s) { m_desc = s; return *this; }
 | 
					    CalcState &setDesc(QString const &s) { m_desc = s; return *this; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void setAllowedTimeRange(QTime const &from, QTime const &until) {
 | 
					    void setAllowedTimeRange(QTime const &from, QTime const &until) {
 | 
				
			||||||
        m_allowedTimeRange.setTimeRange(from, until);
 | 
					        m_allowedTimeRange.setTimeRange(from, until);
 | 
				
			||||||
@@ -197,17 +270,18 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg);
 | 
					QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration const *cfg,
 | 
				
			||||||
                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
					                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
				
			||||||
                                                  int paymentOptionIndex=0);
 | 
					                                                  int paymentOptionIndex=0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration const *cfg,
 | 
				
			||||||
                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
					                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
				
			||||||
                                                  int paymentOptionIndex=0);
 | 
					                                                  int paymentOptionIndex=0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
				
			||||||
                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
					                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
				
			||||||
                                                   int paymentOptionIndex=0);
 | 
					                                                   int paymentOptionIndex = 0,
 | 
				
			||||||
 | 
					                                                   QDateTime const &start = QDateTime::currentDateTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
 | 
				
			||||||
                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
					                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,7 +91,7 @@ public:
 | 
				
			|||||||
    // helper function to find time steps for a tariff with PaymentMethod::Steps
 | 
					    // helper function to find time steps for a tariff with PaymentMethod::Steps
 | 
				
			||||||
    // (e.g. Schoenau/Koenigsee)
 | 
					    // (e.g. Schoenau/Koenigsee)
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    QList<int> GetTimeSteps(Configuration *cfg, int paymentOptionIndex=0) const;
 | 
					    QList<int> &GetTimeSteps(Configuration *cfg, int paymentOptionIndex=0) const;
 | 
				
			||||||
    QList<int> GetSteps(Configuration *cfg, int paymentOptionIndex=0) const { return GetTimeSteps(cfg, paymentOptionIndex); }
 | 
					    QList<int> GetSteps(Configuration *cfg, int paymentOptionIndex=0) const { return GetTimeSteps(cfg, paymentOptionIndex); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QList<int> GetPriceSteps(Configuration *cfg) const;
 | 
					    QList<int> GetPriceSteps(Configuration *cfg) const;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,9 @@ class Configuration
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    using SpecialDaysType = std::multimap<int, ATBSpecialDays>;
 | 
					    using SpecialDaysType = std::multimap<int, ATBSpecialDays>;
 | 
				
			||||||
    using SpecialDaysWorktimeType = std::multimap<int, ATBSpecialDaysWorktime>;
 | 
					    using SpecialDaysWorktimeType = std::multimap<int, ATBSpecialDaysWorktime>;
 | 
				
			||||||
 | 
					    using TimeRangeType = std::multimap<int, ATBTimeRange>;
 | 
				
			||||||
 | 
					    using TariffProductType = std::multimap<int, ATBTariffProduct>;
 | 
				
			||||||
 | 
					    using ATBPaymentOptionType = std::multimap<int, ATBPaymentOption>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ATBProject project;
 | 
					    ATBProject project;
 | 
				
			||||||
    ATBCurrency Currency;
 | 
					    ATBCurrency Currency;
 | 
				
			||||||
@@ -51,13 +54,13 @@ public:
 | 
				
			|||||||
	multimap<int, ATBWeekDays> WeekDays;
 | 
						multimap<int, ATBWeekDays> WeekDays;
 | 
				
			||||||
	multimap<int, ATBPeriodYear> YearPeriod;
 | 
						multimap<int, ATBPeriodYear> YearPeriod;
 | 
				
			||||||
	multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
 | 
						multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
 | 
				
			||||||
	multimap<int, ATBPaymentOption> PaymentOption;
 | 
					    ATBPaymentOptionType PaymentOption;
 | 
				
			||||||
    multimap<int, ATBDailyTicket> DailyTicket;
 | 
					    multimap<int, ATBDailyTicket> DailyTicket;
 | 
				
			||||||
    multimap<int, ATBTimeRange> TimeRange;
 | 
					    TimeRangeType TimeRange;
 | 
				
			||||||
    multimap<int, ATBTimeStepConfig> TimeStepConfig;
 | 
					    multimap<int, ATBTimeStepConfig> TimeStepConfig;
 | 
				
			||||||
    multimap<int, ATBTimeBase> TimeBase;
 | 
					    multimap<int, ATBTimeBase> TimeBase;
 | 
				
			||||||
    multimap<int, ATBCustomer> Customer;
 | 
					    multimap<int, ATBCustomer> Customer;
 | 
				
			||||||
    multimap<int, ATBTariffProduct> TariffProduct;
 | 
					    TariffProductType TariffProduct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// <summary>
 | 
						/// <summary>
 | 
				
			||||||
	/// Parse JSON string
 | 
						/// Parse JSON string
 | 
				
			||||||
@@ -85,6 +88,7 @@ public:
 | 
				
			|||||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForAllKeys() const;
 | 
					    std::optional<QVector<ATBTariffProduct>> getTariffProductForAllKeys() const;
 | 
				
			||||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(int id) const;
 | 
					    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(int id) const;
 | 
				
			||||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(PermitType permitType) const;
 | 
					    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(PermitType permitType) const;
 | 
				
			||||||
 | 
					    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductTypeName(QString const &permitTypeName) const;
 | 
				
			||||||
    std::optional<ATBCustomer> getCustomerForType(ATBCustomer::CustomerType customerType);
 | 
					    std::optional<ATBCustomer> getCustomerForType(ATBCustomer::CustomerType customerType);
 | 
				
			||||||
    std::optional<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek);
 | 
					    std::optional<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <cinttypes>
 | 
					#include <cinttypes>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QDateTime>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ATBPaymentOption
 | 
					class ATBPaymentOption
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@@ -22,6 +24,7 @@ public:
 | 
				
			|||||||
        pop_min_price = 0;
 | 
					        pop_min_price = 0;
 | 
				
			||||||
        pop_max_price = 0;
 | 
					        pop_max_price = 0;
 | 
				
			||||||
        pop_carry_over = -1;
 | 
					        pop_carry_over = -1;
 | 
				
			||||||
 | 
					        pop_carry_over_target = false;
 | 
				
			||||||
        pop_carry_over_time_range_id = -1;
 | 
					        pop_carry_over_time_range_id = -1;
 | 
				
			||||||
        pop_carry_over_start_time_range = -1;
 | 
					        pop_carry_over_start_time_range = -1;
 | 
				
			||||||
        pop_carry_over_end_time_range = -1;
 | 
					        pop_carry_over_end_time_range = -1;
 | 
				
			||||||
@@ -41,12 +44,21 @@ public:
 | 
				
			|||||||
    double pop_min_price;
 | 
					    double pop_min_price;
 | 
				
			||||||
    double pop_max_price;
 | 
					    double pop_max_price;
 | 
				
			||||||
    int pop_carry_over;
 | 
					    int pop_carry_over;
 | 
				
			||||||
 | 
					    bool pop_carry_over_target;
 | 
				
			||||||
    int pop_carry_over_time_range_id;
 | 
					    int pop_carry_over_time_range_id;
 | 
				
			||||||
    int pop_carry_over_start_time_range;
 | 
					    int pop_carry_over_start_time_range;
 | 
				
			||||||
    int pop_carry_over_end_time_range;
 | 
					    int pop_carry_over_end_time_range;
 | 
				
			||||||
    int pop_daily_card_price;
 | 
					    int pop_daily_card_price;
 | 
				
			||||||
    uint64_t pop_business_hours;
 | 
					    uint64_t pop_business_hours;
 | 
				
			||||||
    int pop_time_step_config;
 | 
					    int pop_time_step_config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ATBMaxDateTime {
 | 
				
			||||||
 | 
					        int direction;
 | 
				
			||||||
 | 
					        uint8_t week;
 | 
				
			||||||
 | 
					        uint8_t day;
 | 
				
			||||||
 | 
					        QTime time;
 | 
				
			||||||
 | 
					    } pop_min_date_time,
 | 
				
			||||||
 | 
					      pop_max_date_time;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // PAYMENT_OPT_H_INCLUDED
 | 
					#endif // PAYMENT_OPT_H_INCLUDED
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,13 @@
 | 
				
			|||||||
#define _OFFICIAL_HOLIDAY_                      (uint64_t)(1ULL << 15)
 | 
					#define _OFFICIAL_HOLIDAY_                      (uint64_t)(1ULL << 15)
 | 
				
			||||||
#define _ONLY_WEEKEND_                          ((_SAT_|_SUN_))
 | 
					#define _ONLY_WEEKEND_                          ((_SAT_|_SUN_))
 | 
				
			||||||
#define _ONLY_OPEN_FOR_BUSINESS_DAYS_           (uint64_t)(1ULL << 16)    /* verkaufsoffen */
 | 
					#define _ONLY_OPEN_FOR_BUSINESS_DAYS_           (uint64_t)(1ULL << 16)    /* verkaufsoffen */
 | 
				
			||||||
 | 
					#define _WITH_RESTRICTED_HOURS_                 (uint64_t)(1ULL << 17)
 | 
				
			||||||
 | 
					#define _ALL_DAYS_WITH_RESTRICTED_HOURS_        ((_WITH_RESTRICTED_HOURS_|_ALL_DAYS_))
 | 
				
			||||||
 | 
					#define _WEEKEND_WITH_RESTRICTED_HOURS_         ((_WITH_RESTRICTED_HOURS_|_FRI_|_SAT_|_SUN_))
 | 
				
			||||||
 | 
					#define _WORKING_DAYS_WITH_RESTRICTED_HOURS_    ((_WITH_RESTRICTED_HOURS_|_WORKING_DAYS_))
 | 
				
			||||||
 | 
					#define _FRI_WITH_RESTRICTED_HOURS_             ((_WITH_RESTRICTED_HOURS_|_FRI_))
 | 
				
			||||||
 | 
					#define _SAT_WITH_RESTRICTED_HOURS_             ((_WITH_RESTRICTED_HOURS_|_SAT_))
 | 
				
			||||||
 | 
					#define _SUN_WITH_RESTRICTED_HOURS_             ((_WITH_RESTRICTED_HOURS_|_SUN_))
 | 
				
			||||||
#define _NOT_DEFINED_                           (uint64_t)(~0ULL)
 | 
					#define _NOT_DEFINED_                           (uint64_t)(~0ULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum BusinessHours : std::uint64_t
 | 
					enum BusinessHours : std::uint64_t
 | 
				
			||||||
@@ -54,6 +61,12 @@ enum BusinessHours : std::uint64_t
 | 
				
			|||||||
    OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_,
 | 
					    OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_,
 | 
				
			||||||
    ONLY_WEEKEND = _ONLY_WEEKEND_,
 | 
					    ONLY_WEEKEND = _ONLY_WEEKEND_,
 | 
				
			||||||
    ONLY_OPEN_FOR_BUSINESS_DAYS = _ONLY_OPEN_FOR_BUSINESS_DAYS_,
 | 
					    ONLY_OPEN_FOR_BUSINESS_DAYS = _ONLY_OPEN_FOR_BUSINESS_DAYS_,
 | 
				
			||||||
 | 
					    ALL_DAYS_WITH_RESTRICTED_HOURS = _ALL_DAYS_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
 | 
					    WEEKEND_WITH_RESTRICTED_HOURS = _WEEKEND_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
 | 
					    WORKING_DAYS_WITH_RESTRICTED_HOURS = _WORKING_DAYS_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
 | 
					    FRI_WITH_RESTRICTED_HOURS = _FRI_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
 | 
					    SAT_WITH_RESTRICTED_HOURS = _SAT_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
 | 
					    SUN_WITH_RESTRICTED_HOURS = _SUN_WITH_RESTRICTED_HOURS_,
 | 
				
			||||||
    NOT_DEFINED = _NOT_DEFINED_
 | 
					    NOT_DEFINED = _NOT_DEFINED_
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,15 +4,16 @@
 | 
				
			|||||||
#include <QString>
 | 
					#include <QString>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class PERMIT_TYPE : quint8 {
 | 
					enum class PERMIT_TYPE : quint8 {
 | 
				
			||||||
    SHORT_TERM_PARKING,
 | 
					    SHORT_TERM_PARKING=0,
 | 
				
			||||||
    DAY_TICKET,
 | 
					    DAY_TICKET=1,
 | 
				
			||||||
    SZEGED_START,
 | 
					    SZEGED_START=2,
 | 
				
			||||||
    SZEGED_STOP,
 | 
					    SZEGED_STOP=3,
 | 
				
			||||||
    DAY_TICKET_ADULT,
 | 
					    DAY_TICKET_ADULT=4,
 | 
				
			||||||
    DAY_TICKET_TEEN,
 | 
					    DAY_TICKET_TEEN=5,
 | 
				
			||||||
    DAY_TICKET_CHILD,
 | 
					    DAY_TICKET_CHILD=6,
 | 
				
			||||||
    FOOD_STAMP,
 | 
					    INVALID=7,
 | 
				
			||||||
    INVALID
 | 
					    FOOD_STAMP=8,
 | 
				
			||||||
 | 
					    TWENTY_FOUR_HOURS_TICKET=9
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct PermitType {
 | 
					struct PermitType {
 | 
				
			||||||
@@ -45,6 +46,9 @@ struct PermitType {
 | 
				
			|||||||
        case 7:
 | 
					        case 7:
 | 
				
			||||||
            m_permitType = PERMIT_TYPE::FOOD_STAMP;
 | 
					            m_permitType = PERMIT_TYPE::FOOD_STAMP;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case 8:
 | 
				
			||||||
 | 
					            m_permitType = PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            m_permitType = PERMIT_TYPE::INVALID;
 | 
					            m_permitType = PERMIT_TYPE::INVALID;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -74,6 +78,8 @@ struct PermitType {
 | 
				
			|||||||
            return 6;
 | 
					            return 6;
 | 
				
			||||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
					        case PERMIT_TYPE::FOOD_STAMP:
 | 
				
			||||||
            return 7;
 | 
					            return 7;
 | 
				
			||||||
 | 
					        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
				
			||||||
 | 
					            return 8;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -81,7 +87,7 @@ struct PermitType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operator QString () {
 | 
					    QString toString() {
 | 
				
			||||||
        switch(m_permitType) {
 | 
					        switch(m_permitType) {
 | 
				
			||||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
					        case PERMIT_TYPE::DAY_TICKET:
 | 
				
			||||||
            return QString("DAY_TICKET");
 | 
					            return QString("DAY_TICKET");
 | 
				
			||||||
@@ -99,13 +105,15 @@ struct PermitType {
 | 
				
			|||||||
            return QString("SZEGED_STOP");
 | 
					            return QString("SZEGED_STOP");
 | 
				
			||||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
					        case PERMIT_TYPE::FOOD_STAMP:
 | 
				
			||||||
            return QString("FOOD_STAMP");
 | 
					            return QString("FOOD_STAMP");
 | 
				
			||||||
 | 
					        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
				
			||||||
 | 
					            return QString("TWENTY_FOUR_HOURS_TICKET");
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return QString("INVALID");
 | 
					        return QString("INVALID");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operator QString () const {
 | 
					    QString toString() const {
 | 
				
			||||||
        switch(m_permitType) {
 | 
					        switch(m_permitType) {
 | 
				
			||||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
					        case PERMIT_TYPE::DAY_TICKET:
 | 
				
			||||||
            return QString("DAY_TICKET");
 | 
					            return QString("DAY_TICKET");
 | 
				
			||||||
@@ -123,11 +131,21 @@ struct PermitType {
 | 
				
			|||||||
            return QString("SZEGED_STOP");
 | 
					            return QString("SZEGED_STOP");
 | 
				
			||||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
					        case PERMIT_TYPE::FOOD_STAMP:
 | 
				
			||||||
            return QString("FOOD_STAMP");
 | 
					            return QString("FOOD_STAMP");
 | 
				
			||||||
 | 
					        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
				
			||||||
 | 
					            return QString("TWENTY_FOUR_HOURS_TICKET");
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return QString("INVALID");
 | 
					        return QString("INVALID");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator QString () {
 | 
				
			||||||
 | 
					        return toString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator QString () const {
 | 
				
			||||||
 | 
					        return toString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
					#endif // TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,12 +79,12 @@ namespace Utilities {
 | 
				
			|||||||
	double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
 | 
						double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QTime SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId);
 | 
					    QTime SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId);
 | 
				
			||||||
    QTime SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator it);
 | 
					    QTime SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator const &it);
 | 
				
			||||||
    QTime SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId);
 | 
					    QTime SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId);
 | 
				
			||||||
    QTime SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator it);
 | 
					    QTime SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator const &it);
 | 
				
			||||||
    QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
					    QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
				
			||||||
    QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
					    QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
				
			||||||
    int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
					    int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
				
			||||||
    // PaymentRate GetPaymentRate(Configuration const *cfg, );
 | 
					    // PaymentRate GetPaymentRate(Configuration const *cfg, );
 | 
				
			||||||
    bool isCarryOverSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
					    bool isCarryOverSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
				
			||||||
    bool isCarryOverNotSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
					    bool isCarryOverNotSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
				
			||||||
@@ -100,4 +100,5 @@ namespace Utilities {
 | 
				
			|||||||
    uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id);
 | 
					    uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id);
 | 
				
			||||||
    double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id);
 | 
					    double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id);
 | 
				
			||||||
    QStringList dumpBusinessHours(uint64_t businessHours);
 | 
					    QStringList dumpBusinessHours(uint64_t businessHours);
 | 
				
			||||||
 | 
					    uint32_t getDailyTicketCardPrice(Configuration const *cfg, PaymentMethod methodId);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,10 @@ INCLUDEPATH += $$_PRO_FILE_PWD_/include/rapidjson
 | 
				
			|||||||
#Version is set in yocto recipe with "EXTRA_QMAKEVARS_PRE"
 | 
					#Version is set in yocto recipe with "EXTRA_QMAKEVARS_PRE"
 | 
				
			||||||
#VERSION=1.0.0
 | 
					#VERSION=1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 04.06.2024: Fix for Szeged: read price for daily ticket directly from entry
 | 
				
			||||||
 | 
					#             PaymentOptions in tariff-file if it is not given as part of a
 | 
				
			||||||
 | 
					#             Json-Product-Array in tariff-file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG(debug, debug|release) {
 | 
					CONFIG(debug, debug|release) {
 | 
				
			||||||
    win32 {
 | 
					    win32 {
 | 
				
			||||||
        QMAKE_CXXFLAGS += -DCALCULATE_LIBRARY_EXPORTS
 | 
					        QMAKE_CXXFLAGS += -DCALCULATE_LIBRARY_EXPORTS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,11 +10,26 @@
 | 
				
			|||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
#include <QList>
 | 
					#include <QList>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString const CalcState::SUCCESS = "SUCCESS";
 | 
				
			||||||
 | 
					QString const CalcState::ERROR_PARSING_ZONE_NR = "ERROR_PARSING_ZONE_NR";
 | 
				
			||||||
 | 
					QString const CalcState::ERROR_LOADING_TARIFF = "ERROR_LOADING_TARIFF";
 | 
				
			||||||
 | 
					QString const CalcState::ERROR_PARSING_TARIFF = "ERROR_PARSING_TARIFF";
 | 
				
			||||||
 | 
					QString const CalcState::NEGATIVE_PARKING_TIME = "NEGATIVE_PARKING_TIME";
 | 
				
			||||||
 | 
					QString const CalcState::INVALID_START_DATE = "INVALID_START_DATE";
 | 
				
			||||||
 | 
					QString const CalcState::WRONG_PARAM_VALUES = "WRONG_PARAM_VALUES";
 | 
				
			||||||
 | 
					QString const CalcState::WRONG_ISO_TIME_FORMAT = "WRONG_ISO_TIME_FORMAT";
 | 
				
			||||||
 | 
					QString const CalcState::ABOVE_MAX_PARKING_TIME = "ABOVE_MAX_PARKING_TIME";
 | 
				
			||||||
 | 
					QString const CalcState::BELOW_MIN_PARKING_TIME = "BELOW_MIN_PARKING_TIME";
 | 
				
			||||||
 | 
					QString const CalcState::BELOW_MIN_PARKING_PRICE = "BELOW_MIN_PARKING_PRICE";
 | 
				
			||||||
 | 
					QString const CalcState::ABOVE_MAX_PARKING_PRICE = "ABOVE_MAX_PARKING_PRICE";
 | 
				
			||||||
 | 
					QString const CalcState::OVERPAID = "OVERPAID";
 | 
				
			||||||
 | 
					QString const CalcState::OUTSIDE_ALLOWED_PARKING_TIME = "OUTSIDE_ALLOWED_PARKING_TIME";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg) {
 | 
					QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg) {
 | 
				
			||||||
    return Calculator::GetInstance().GetTimeSteps(cfg);
 | 
					    return Calculator::GetInstance().GetTimeSteps(cfg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration const *cfg,
 | 
				
			||||||
                                                  PERMIT_TYPE permitType,
 | 
					                                                  PERMIT_TYPE permitType,
 | 
				
			||||||
                                                  int paymentOptionIndex) {
 | 
					                                                  int paymentOptionIndex) {
 | 
				
			||||||
    int minTime = 0;
 | 
					    int minTime = 0;
 | 
				
			||||||
@@ -33,14 +48,14 @@ int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg,
 | 
				
			|||||||
        // for each new sell-procedure, recomute the timesteps. implicitly, set
 | 
					        // for each new sell-procedure, recomute the timesteps. implicitly, set
 | 
				
			||||||
        // the minimal parking time.
 | 
					        // the minimal parking time.
 | 
				
			||||||
        Calculator::GetInstance().ResetTimeSteps(paymentOptionIndex);
 | 
					        Calculator::GetInstance().ResetTimeSteps(paymentOptionIndex);
 | 
				
			||||||
        Calculator::GetInstance().GetTimeSteps(cfg, paymentOptionIndex);
 | 
					        Calculator::GetInstance().GetTimeSteps((Configuration *)cfg, paymentOptionIndex);
 | 
				
			||||||
        minTime = qRound(cfg->getPaymentOptions(paymentOptionIndex).pop_min_time);
 | 
					        minTime = qRound(cfg->getPaymentOptions(paymentOptionIndex).pop_min_time);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return minTime;
 | 
					    return minTime;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration const *cfg,
 | 
				
			||||||
                                                  PERMIT_TYPE permitType,
 | 
					                                                  PERMIT_TYPE permitType,
 | 
				
			||||||
                                                  int paymentOptionIndex) {
 | 
					                                                  int paymentOptionIndex) {
 | 
				
			||||||
    int maxTime = 0;
 | 
					    int maxTime = 0;
 | 
				
			||||||
@@ -59,11 +74,13 @@ int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return maxTime;
 | 
					    return maxTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
					int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
				
			||||||
                                                   PERMIT_TYPE permitType,
 | 
					                                                   PERMIT_TYPE permitType,
 | 
				
			||||||
                                                   int paymentOptionIndex) {
 | 
					                                                   int paymentOptionIndex,
 | 
				
			||||||
 | 
					                                                   QDateTime const &start) {
 | 
				
			||||||
    int minPrice = -1;
 | 
					    int minPrice = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch(permitType) {
 | 
					    switch(permitType) {
 | 
				
			||||||
@@ -76,6 +93,9 @@ int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
				
			|||||||
    } break;
 | 
					    } break;
 | 
				
			||||||
    case PERMIT_TYPE::DAY_TICKET_CHILD: {
 | 
					    case PERMIT_TYPE::DAY_TICKET_CHILD: {
 | 
				
			||||||
    } break;
 | 
					    } break;
 | 
				
			||||||
 | 
					    case PERMIT_TYPE::DAY_TICKET: {
 | 
				
			||||||
 | 
					        minPrice = compute_product_price(cfg, permitType, start);
 | 
				
			||||||
 | 
					    } break;
 | 
				
			||||||
    default: ;
 | 
					    default: ;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,6 +164,10 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
 | 
				
			|||||||
                QTime const &startTime = p.getTimeStart();
 | 
					                QTime const &startTime = p.getTimeStart();
 | 
				
			||||||
                QTime const &endTime = p.getTimeEnd();
 | 
					                QTime const &endTime = p.getTimeEnd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // qCritical() << __LINE__ << startTime.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					                // qCritical() << __LINE__ << endTime.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					                // qCritical() << __LINE__ << start.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (start.time() >= startTime && start.time() < endTime) {
 | 
					                if (start.time() >= startTime && start.time() < endTime) {
 | 
				
			||||||
                    product_price = p.getProductPrice();
 | 
					                    product_price = p.getProductPrice();
 | 
				
			||||||
                    if (productStart && productEnd) {
 | 
					                    if (productStart && productEnd) {
 | 
				
			||||||
@@ -154,8 +178,41 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return product_price;
 | 
					            return product_price;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // SZEGED
 | 
				
			||||||
 | 
					            int const pop_daily_card_price = cfg->getPaymentOptions().pop_daily_card_price;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            qDebug() << QString("(%1:%2) no products defined in tariff-file").arg(__func__).arg(__LINE__);
 | 
				
			||||||
 | 
					            qDebug() << QString("(%1:%2) pop_daily_card_price=%3").arg(__func__).arg(__LINE__).arg(pop_daily_card_price);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
				
			||||||
 | 
					            // return Utilities::getDailyTicketCardPrice(cfg, paymentMethodId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return pop_daily_card_price;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } break;
 | 
					    } break;
 | 
				
			||||||
 | 
					    case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET: {
 | 
				
			||||||
 | 
					        std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
 | 
				
			||||||
 | 
					        if (products) {
 | 
				
			||||||
 | 
					            int product_price = 0;
 | 
				
			||||||
 | 
					            QVector<ATBTariffProduct> product = products.value();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (product.size() > 0) {
 | 
				
			||||||
 | 
					                if (productStart && productEnd) {
 | 
				
			||||||
 | 
					                    int pop_min_time = get_minimal_parkingtime(cfg); // in minutes
 | 
				
			||||||
 | 
					                    int pop_max_time = get_maximal_parkingtime(cfg); // in minutes
 | 
				
			||||||
 | 
					                    if (pop_max_time >= pop_min_time) {
 | 
				
			||||||
 | 
					                        *productStart = start;
 | 
				
			||||||
 | 
					                        *productEnd = start.addSecs(pop_max_time*60);
 | 
				
			||||||
 | 
					                        product_price = product[0].getProductPrice();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return product_price;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -315,8 +372,31 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu
 | 
				
			|||||||
        // progressive tariff: e.g. Neuhauser, Kirchdorf (743)
 | 
					        // progressive tariff: e.g. Neuhauser, Kirchdorf (743)
 | 
				
			||||||
        (paymentMethodId == PaymentMethod::Progressive))
 | 
					        (paymentMethodId == PaymentMethod::Progressive))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const QList<int> stepList = Calculator::GetInstance().GetTimeSteps(tariff);
 | 
					        QList<int> &stepList = Calculator::GetInstance().GetTimeSteps(tariff);
 | 
				
			||||||
 | 
					        int const size = stepList.size();
 | 
				
			||||||
 | 
					        if (size == 0) {
 | 
				
			||||||
 | 
					            qCritical() << "compute_next_timestep() *ERROR empty step-list*";
 | 
				
			||||||
 | 
					            return  currentTimeMinutes;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qCritical() << "   compute_next_timestep()      first time step:" << stepList[0];
 | 
				
			||||||
        qCritical() << "   compute_next_timestep()            timeSteps:" << stepList;
 | 
					        qCritical() << "   compute_next_timestep()            timeSteps:" << stepList;
 | 
				
			||||||
 | 
					        qCritical() << "   compute_next_timestep() currentTimeInMinutes:" << currentTimeMinutes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // consider time shift: the step-list might have been computed at a
 | 
				
			||||||
 | 
					        // slightly different time point
 | 
				
			||||||
 | 
					        int maxStep = -1;
 | 
				
			||||||
 | 
					        if (size >= 2) {
 | 
				
			||||||
 | 
					            maxStep = stepList[1] - stepList[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        int tolerance = (maxStep == -1) ? 5 : std::min(maxStep, 5);
 | 
				
			||||||
 | 
					        if (std::abs(stepList[0] - currentTimeMinutes) <= tolerance) {
 | 
				
			||||||
 | 
					            qCritical().noquote()
 | 
				
			||||||
 | 
					                << QString("   compute_next_timestep() correction stepList[0]=%1 -> %2:")
 | 
				
			||||||
 | 
					                                    .arg(stepList[0]).arg(currentTimeMinutes);
 | 
				
			||||||
 | 
					            stepList[0] = currentTimeMinutes;
 | 
				
			||||||
 | 
					            qCritical() << "   compute_next_timestep()        NEW timeSteps:" << stepList;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int currentStepIndex = stepList.indexOf(currentTimeMinutes);
 | 
					        int currentStepIndex = stepList.indexOf(currentTimeMinutes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -396,7 +476,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
				
			|||||||
    if (duration < 0) {
 | 
					    if (duration < 0) {
 | 
				
			||||||
        calcState.setDesc(QString("end=%1, start=%2")
 | 
					        calcState.setDesc(QString("end=%1, start=%2")
 | 
				
			||||||
                          .arg(end_parking_time, start_parking_time));
 | 
					                          .arg(end_parking_time, start_parking_time));
 | 
				
			||||||
        return calcState.set(CalcState::State::NEGATIVE_PARING_TIME);
 | 
					        return calcState.set(CalcState::State::NEGATIVE_PARKING_TIME);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (duration > maxMin) {
 | 
					    if (duration > maxMin) {
 | 
				
			||||||
        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(duration).arg(maxMin));
 | 
					        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(duration).arg(maxMin));
 | 
				
			||||||
@@ -453,6 +533,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // DEBUG
 | 
					    // DEBUG
 | 
				
			||||||
    qCritical() << "compute_price_for_parking_ticket() " << endl
 | 
					    qCritical() << "compute_price_for_parking_ticket() " << endl
 | 
				
			||||||
 | 
					                << "          paymentOptionIndex: " << paymentOptionIndex << endl
 | 
				
			||||||
                << "          start_parking_time: " << start_parking_time << endl
 | 
					                << "          start_parking_time: " << start_parking_time << endl
 | 
				
			||||||
                << "          netto_parking_time: " << netto_parking_time << endl
 | 
					                << "          netto_parking_time: " << netto_parking_time << endl
 | 
				
			||||||
                << "                      minMin: " << minMin << endl
 | 
					                << "                      minMin: " << minMin << endl
 | 
				
			||||||
@@ -463,7 +544,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
				
			|||||||
        calcState.setDesc(QString("end=%1, start=%2")
 | 
					        calcState.setDesc(QString("end=%1, start=%2")
 | 
				
			||||||
                          .arg(end_parking_time.toString(Qt::ISODate),
 | 
					                          .arg(end_parking_time.toString(Qt::ISODate),
 | 
				
			||||||
                               start_parking_time.toString(Qt::ISODate)));
 | 
					                               start_parking_time.toString(Qt::ISODate)));
 | 
				
			||||||
        return calcState.set(CalcState::State::NEGATIVE_PARING_TIME);
 | 
					        return calcState.set(CalcState::State::NEGATIVE_PARKING_TIME);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (netto_parking_time > maxMin) {
 | 
					    if (netto_parking_time > maxMin) {
 | 
				
			||||||
        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(netto_parking_time).arg(maxMin));
 | 
					        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(netto_parking_time).arg(maxMin));
 | 
				
			||||||
@@ -479,14 +560,21 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    double cost = -1;
 | 
					    double cost = -1;
 | 
				
			||||||
    if (start_parking_time.isValid()) {
 | 
					    if (start_parking_time.isValid()) {
 | 
				
			||||||
        if (tariff->getPaymentOptions().pop_payment_method_id == PaymentMethod::Steps) {
 | 
					        if (tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id == PaymentMethod::Steps) {
 | 
				
			||||||
            // hier muesste man unterscheiden: uebertrag oder nicht?
 | 
					            // hier muesste man unterscheiden: uebertrag oder nicht?
 | 
				
			||||||
            calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time,
 | 
					            calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time,
 | 
				
			||||||
                                                                   netto_parking_time, paymentOptionIndex);
 | 
					                                                                   netto_parking_time, paymentOptionIndex);
 | 
				
			||||||
            if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
					            if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
				
			||||||
 | 
					                // qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
				
			||||||
 | 
					                //             << calcState.toString();
 | 
				
			||||||
                return calcState;
 | 
					                return calcState;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time, paymentOptionIndex);
 | 
					            cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time, paymentOptionIndex);
 | 
				
			||||||
 | 
					            end_parking_time = start_parking_time.addSecs(netto_parking_time*60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
				
			||||||
 | 
					            //             << "end_parking_time" << end_parking_time.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            cost = Calculator::GetInstance().GetCostFromDuration(
 | 
					            cost = Calculator::GetInstance().GetCostFromDuration(
 | 
				
			||||||
                        tariff,
 | 
					                        tariff,
 | 
				
			||||||
@@ -503,7 +591,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // DEBUG
 | 
					        // DEBUG
 | 
				
			||||||
        qCritical() << "               -> calculated cost (price->netto) =  " << cost;
 | 
					        qCritical() << "            end_parking_time: " << end_parking_time;
 | 
				
			||||||
 | 
					        qCritical() << "  -> calculated cost (netto): " << cost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        price->brutto = price->vat = price->vat_percentage = 0;
 | 
					        price->brutto = price->vat = price->vat_percentage = 0;
 | 
				
			||||||
        price->units = cost;
 | 
					        price->units = cost;
 | 
				
			||||||
@@ -564,17 +653,77 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
 | 
				
			|||||||
                    tariff->getPaymentOptions().pop_payment_method_id,
 | 
					                    tariff->getPaymentOptions().pop_payment_method_id,
 | 
				
			||||||
                    cs.toLocal8Bit().constData(),
 | 
					                    cs.toLocal8Bit().constData(),
 | 
				
			||||||
                    price, false, true).c_str();
 | 
					                    price, false, true).c_str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (endTime == CalcState::SUCCESS) {
 | 
				
			||||||
 | 
					            calcState.setDesc(QString("SUCCESS"));
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::ERROR_PARSING_ZONE_NR) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::ERROR_LOADING_TARIFF) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::ERROR_PARSING_TARIFF) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::NEGATIVE_PARKING_TIME) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::INVALID_START_DATE) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::WRONG_PARAM_VALUES) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::WRONG_ISO_TIME_FORMAT) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::ABOVE_MAX_PARKING_TIME) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::BELOW_MIN_PARKING_TIME) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::BELOW_MIN_PARKING_PRICE) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::ABOVE_MAX_PARKING_PRICE) {
 | 
				
			||||||
 | 
					            calcState.setDesc(CalcState::ABOVE_MAX_PARKING_PRICE);
 | 
				
			||||||
 | 
					            calcState.setStatus(CalcState::ABOVE_MAX_PARKING_PRICE);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::OVERPAID) {
 | 
				
			||||||
 | 
					            calcState.setDesc(CalcState::OVERPAID);
 | 
				
			||||||
 | 
					            calcState.setStatus(CalcState::OVERPAID);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					        if (endTime == CalcState::OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
				
			||||||
 | 
					            calcState.setStatus(endTime);
 | 
				
			||||||
 | 
					            return calcState;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            ticketEndTime = QDateTime::fromString(endTime,Qt::ISODate);
 | 
					            ticketEndTime = QDateTime::fromString(endTime,Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // DEBUG
 | 
					            // DEBUG
 | 
				
			||||||
        qCritical() << "compute_duration_for_parking_ticket(): ";
 | 
					            //qCritical() << "compute_duration_for_parking_ticket(): ";
 | 
				
			||||||
        qCritical() << "                 endTime: " << endTime;
 | 
					            //qCritical() << "                 endTime: " << endTime;
 | 
				
			||||||
        qCritical() << "           ticketEndTime: " << ticketEndTime;
 | 
					            //qCritical() << "           ticketEndTime: " << ticketEndTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!ticketEndTime.isValid()) {
 | 
					            if (!ticketEndTime.isValid()) {
 | 
				
			||||||
                calcState.setDesc(QString("ticketEndTime=%1").arg(endTime));
 | 
					                calcState.setDesc(QString("ticketEndTime=%1").arg(endTime));
 | 
				
			||||||
                return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
 | 
					                return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        return calcState.set(CalcState::State::INVALID_START_DATE);
 | 
					        return calcState.set(CalcState::State::INVALID_START_DATE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,7 +144,228 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                qCritical() << __func__ << ":" << __LINE__ << "NOT YET IMPLEMENTED";
 | 
					                // TODO: man braucht den richtigen Index
 | 
				
			||||||
 | 
					                int paymentOptionIndex = 0;
 | 
				
			||||||
 | 
					                int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
 | 
				
			||||||
 | 
					                int const pop_max_price = cfg->getPaymentOptions(paymentOptionIndex).pop_max_price;
 | 
				
			||||||
 | 
					                int const pop_min_price = cfg->getPaymentOptions(paymentOptionIndex).pop_min_price;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (cost > pop_max_price) {
 | 
				
			||||||
 | 
					                    qCritical() << DBG_HEADER << "MAX-PARKING-PRICE" << pop_max_price << ", COST" << cost;
 | 
				
			||||||
 | 
					                    return CalcState::OVERPAID.toStdString();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (cost < pop_min_price) {
 | 
				
			||||||
 | 
					                    qCritical() << DBG_HEADER << "MIN-PARKING-PRICE" << pop_min_price << ", COST" << cost;
 | 
				
			||||||
 | 
					                    return CalcState::BELOW_MIN_PARKING_PRICE.toStdString();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // int const pop_pre_paid = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (prepaid) {
 | 
				
			||||||
 | 
					                    // no limits on pre-pay-option, i.e. pre-pay-ranges are exactly
 | 
				
			||||||
 | 
					                    // the complements of operational-ranges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // find out if we are in a pre-pay-range.
 | 
				
			||||||
 | 
					                    // in this case, adapt inputDate accordingly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#define DEBUG_GET_DURATION_FROM_COST 1
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                    qCritical() << DBG_HEADER << "PRE-PAID-OPTION: ADAPT-INPUT-DATE" << inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    QTime currentTime = inputDate.time();
 | 
				
			||||||
 | 
					                    int pwd_period_day_in_week_id = inputDate.date().dayOfWeek();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    bool useWeekDaysWorkTimeOfOtherDay = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_day_in_week_id); iter != rEnd; ++iter) {
 | 
				
			||||||
 | 
					                        QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate);
 | 
				
			||||||
 | 
					                        QTime pwd_time_to = QTime::fromString(QString::fromStdString(iter->second.pwd_time_to), Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (inputDate.time() < pwd_time_from) {
 | 
				
			||||||
 | 
					                            inputDate.setTime(pwd_time_from);
 | 
				
			||||||
 | 
					                            useWeekDaysWorkTimeOfOtherDay = false;
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (currentTime <= pwd_time_to) {
 | 
				
			||||||
 | 
					                            useWeekDaysWorkTimeOfOtherDay = false;
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (useWeekDaysWorkTimeOfOtherDay) {// for the current day, we are above
 | 
				
			||||||
 | 
					                                                        // the latest worktime-range -> find the next valid range
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        QTime pwd_time_from_next_valid_range(0, 0, 0);
 | 
				
			||||||
 | 
					                        int pwd_period_next_day_in_week_id = pwd_period_day_in_week_id;
 | 
				
			||||||
 | 
					                        for (int days = 1; days < 8; ++days) {
 | 
				
			||||||
 | 
					                            pwd_period_next_day_in_week_id += 1;
 | 
				
			||||||
 | 
					                            if (pwd_period_next_day_in_week_id > (int)Qt::Sunday) {
 | 
				
			||||||
 | 
					                                pwd_period_next_day_in_week_id = Qt::Monday;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (cfg->WeekDaysWorktime.count(pwd_period_next_day_in_week_id) > 0) {
 | 
				
			||||||
 | 
					                                for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_next_day_in_week_id); iter != rEnd; ++iter) {
 | 
				
			||||||
 | 
					                                    QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate);
 | 
				
			||||||
 | 
					                                    if (pwd_time_from_next_valid_range < pwd_time_from) {
 | 
				
			||||||
 | 
					                                        pwd_time_from_next_valid_range = pwd_time_from;
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                inputDate = inputDate.addDays(days);
 | 
				
			||||||
 | 
					                                inputDate.setTime(pwd_time_from_next_valid_range);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << "(ADAPTED) INPUT-DATE" << inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // inputDate is now located in a valid operational-working-range
 | 
				
			||||||
 | 
					                // find this working-time-range
 | 
				
			||||||
 | 
					                int pwd_period_day_in_week_id = inputDate.date().dayOfWeek();
 | 
				
			||||||
 | 
					                if (cfg->WeekDaysWorktime.count(pwd_period_day_in_week_id) == 0) {
 | 
				
			||||||
 | 
					                    qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					                                << "ERROR" << inputDate.toString(Qt::ISODate)
 | 
				
			||||||
 | 
					                                << "NOT IN VALID WORKING TIME-RANGE";
 | 
				
			||||||
 | 
					                    return "";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                QTime current_working_time_from;
 | 
				
			||||||
 | 
					                QTime current_working_time_to;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(pwd_period_day_in_week_id); iter != rEnd; ++iter) {
 | 
				
			||||||
 | 
					                    QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate);
 | 
				
			||||||
 | 
					                    QTime pwd_time_to = QTime::fromString(QString::fromStdString(iter->second.pwd_time_to), Qt::ISODate);
 | 
				
			||||||
 | 
					                    if (pwd_time_from <= inputDate.time() && inputDate.time() <= pwd_time_to) {
 | 
				
			||||||
 | 
					                        current_working_time_from = pwd_time_from;
 | 
				
			||||||
 | 
					                        current_working_time_to = pwd_time_to;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (current_working_time_from.isNull() || current_working_time_to.isNull()) {
 | 
				
			||||||
 | 
					                    // can never happen
 | 
				
			||||||
 | 
					                    qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					                                << "ERROR" << inputDate.toString(Qt::ISODate)
 | 
				
			||||||
 | 
					                                << "NOT IN VALID WORKING TIME-RANGE";
 | 
				
			||||||
 | 
					                    return "";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << "CURRENT WORKING-TIME-FROM" << current_working_time_from.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << "  CURRENT WORKING-TIME-TO" << current_working_time_to.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) {
 | 
				
			||||||
 | 
					                    int const pra_price = itr->second.pra_price;
 | 
				
			||||||
 | 
					                    if ((double)pra_price == cost) {
 | 
				
			||||||
 | 
					                        int const durationId = itr->second.pra_payment_unit_id;
 | 
				
			||||||
 | 
					                        auto search = cfg->Duration.find(durationId);
 | 
				
			||||||
 | 
					                        if (search != cfg->Duration.end()) {
 | 
				
			||||||
 | 
					                            // found now the duration in minutes
 | 
				
			||||||
 | 
					                            // check if we are still inside the working-time-range
 | 
				
			||||||
 | 
					                            ATBDuration duration = search->second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            int durationInSecs = duration.pun_duration * 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            QDateTime current_working_date_time_to = inputDate;
 | 
				
			||||||
 | 
					                            current_working_date_time_to.setTime(current_working_time_to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "DURATION IN MINUTES" << duration.pun_duration;
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "DURATION IN SECONDS" << duration.pun_duration * 60;
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "CURRENT-WORKING-DATE-TIME-TO"
 | 
				
			||||||
 | 
					                                                      << current_working_date_time_to.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "NEW INPUT DATE" << inputDate.addSecs(durationInSecs).toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (inputDate.addSecs(durationInSecs) > current_working_date_time_to) {
 | 
				
			||||||
 | 
					                                QTime next_working_time_from;
 | 
				
			||||||
 | 
					                                if (cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over != 0) {
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                                    qCritical() << DBG_HEADER << "CARRY-OVER SET";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                                    // check for next working-time-range on same day
 | 
				
			||||||
 | 
					                                    int day_in_week_id = inputDate.date().dayOfWeek();
 | 
				
			||||||
 | 
					                                    for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(day_in_week_id); iter != rEnd; ++iter) {
 | 
				
			||||||
 | 
					                                        QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate);
 | 
				
			||||||
 | 
					                                        if (pwd_time_from > current_working_time_to) {
 | 
				
			||||||
 | 
					                                            next_working_time_from = pwd_time_from;
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                                            qCritical() << DBG_HEADER << "NEXT-WORKING-TIME-FROM"
 | 
				
			||||||
 | 
					                                                        << next_working_time_from.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                                            break;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    // check for next working-time-range on following day(s)
 | 
				
			||||||
 | 
					                                    if (next_working_time_from.isNull()) {
 | 
				
			||||||
 | 
					                                        next_working_time_from = QTime(0, 0, 0);
 | 
				
			||||||
 | 
					                                        for (int days = 1; days < 8; ++days) {
 | 
				
			||||||
 | 
					                                            day_in_week_id += 1;
 | 
				
			||||||
 | 
					                                            if (day_in_week_id > (int)Qt::Sunday) {
 | 
				
			||||||
 | 
					                                                day_in_week_id = Qt::Monday;
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
 | 
					                                            if (cfg->WeekDaysWorktime.count(day_in_week_id) > 0) {
 | 
				
			||||||
 | 
					                                                for (auto[iter, rEnd] = cfg->WeekDaysWorktime.equal_range(day_in_week_id); iter != rEnd; ++iter) {
 | 
				
			||||||
 | 
					                                                    QTime pwd_time_from = QTime::fromString(QString::fromStdString(iter->second.pwd_time_from), Qt::ISODate);
 | 
				
			||||||
 | 
					                                                    if (next_working_time_from < pwd_time_from) {
 | 
				
			||||||
 | 
					                                                        next_working_time_from = pwd_time_from;
 | 
				
			||||||
 | 
					                                                        break;
 | 
				
			||||||
 | 
					                                                    }
 | 
				
			||||||
 | 
					                                                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                                QDateTime upper = inputDate.addDays(days);
 | 
				
			||||||
 | 
					                                                upper.setTime(next_working_time_from);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                                QDateTime lower = inputDate;
 | 
				
			||||||
 | 
					                                                lower.setTime(current_working_time_to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                                inputDate = inputDate.addSecs(lower.secsTo(upper) + durationInSecs);
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                                                qCritical() << DBG_HEADER << "TICKET-END" << inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                                                break;
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
 | 
					                                        } // for (int days = 1; days < 8; ++days) {
 | 
				
			||||||
 | 
					                                    } else { // next working-time is on same day
 | 
				
			||||||
 | 
					                                        QDateTime upper = inputDate;
 | 
				
			||||||
 | 
					                                        upper.setTime(next_working_time_from);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        QDateTime lower = inputDate;
 | 
				
			||||||
 | 
					                                        lower.setTime(current_working_time_to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        inputDate = inputDate.addSecs(lower.secsTo(upper) + durationInSecs);
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                                        qCritical() << DBG_HEADER << "TICKET-END" << inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                inputDate = inputDate.addSecs(duration.pun_duration * 60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                                qCritical() << DBG_HEADER << "INPUT-DATE" << inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            QString const &s = inputDate.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_GET_DURATION_FROM_COST==1
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "TICKET-END" << s;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            return s.toStdString();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return "";
 | 
					                return "";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -628,12 +849,19 @@ CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
				
			|||||||
    PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
					    PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
				
			||||||
    if (paymentMethodId == PaymentMethod::Steps) {
 | 
					    if (paymentMethodId == PaymentMethod::Steps) {
 | 
				
			||||||
        uint64_t const businessHours = cfg->getPaymentOptions(paymentOptionIndex).pop_business_hours;
 | 
					        uint64_t const businessHours = cfg->getPaymentOptions(paymentOptionIndex).pop_business_hours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (cfg->isDayIncluded(businessHours, start)) {
 | 
					        if (cfg->isDayIncluded(businessHours, start)) {
 | 
				
			||||||
            if (businessHours == BusinessHours::NO_RESTRICTION_24_7) {
 | 
					            if (businessHours == BusinessHours::NO_RESTRICTION_24_7) {
 | 
				
			||||||
                return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
 | 
					                return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
 | 
				
			||||||
                         QTime(0, 0, 0), QTime(23, 59, 59));
 | 
					                         QTime(0, 0, 0), QTime(23, 59, 59));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            int const weekdayId = start.date().dayOfWeek();
 | 
					            int const weekdayId = start.date().dayOfWeek();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					            //             << "weekdayId" << weekdayId
 | 
				
			||||||
 | 
					            //             << "count" << cfg->WeekDaysWorktime.count(weekdayId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (cfg->WeekDaysWorktime.count(weekdayId) > 0) {
 | 
					            if (cfg->WeekDaysWorktime.count(weekdayId) > 0) {
 | 
				
			||||||
                using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
					                using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
				
			||||||
                std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
					                std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
				
			||||||
@@ -649,8 +877,10 @@ CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
				
			|||||||
                    QTime const &startTime = start.time();
 | 
					                    QTime const &startTime = start.time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (startTime >= from && startTime <= until) {
 | 
					                    if (startTime >= from && startTime <= until) {
 | 
				
			||||||
                        QTime const endTime = start.addSecs(netto_parking_time*60).time();
 | 
					                        QDateTime const end = start.addSecs(netto_parking_time*60);
 | 
				
			||||||
                        if (endTime <= until) {
 | 
					                        QTime const endTime = end.time();
 | 
				
			||||||
 | 
					                        if (endTime <= until && start.date().dayOfWeek() == end.date().dayOfWeek()) {
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER;
 | 
				
			||||||
                            return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED", from, until);
 | 
					                            return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED", from, until);
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
 | 
					                            errorStr = QString("%1 startTime not in range (%2 not in [%3, %4))")
 | 
				
			||||||
@@ -668,28 +898,59 @@ CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
 | 
					                    int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					                    //             << "paymentOptionIndex" << paymentOptionIndex
 | 
				
			||||||
 | 
					                    //             << "pop_carry_over" << pop_carry_over;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (pop_carry_over == 1) {
 | 
					                    if (pop_carry_over == 1) {
 | 
				
			||||||
                        qCritical() << DBG_HEADER
 | 
					                        // qCritical() << DBG_HEADER
 | 
				
			||||||
                                    << "NO. CHECK IF PARKING IS ALLOWED WITH CARRY-OVER ...";
 | 
					                        //             << "NO. CHECK IF PARKING IS ALLOWED WITH CARRY-OVER ...";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        int const pop_carry_over_start_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_start_time_range;
 | 
					                        int const pop_carry_over_start_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_start_time_range;
 | 
				
			||||||
                        int const pop_carry_over_end_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_end_time_range;
 | 
					                        int const pop_carry_over_end_time_range = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_end_time_range;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					                        //             << "pop_carry_over_start_time_range" << pop_carry_over_start_time_range
 | 
				
			||||||
 | 
					                        //             << "pop_carry_over_end_time_range" << pop_carry_over_end_time_range;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if ((int)cfg->TimeRange.count(pop_carry_over_start_time_range) <= 0 &&
 | 
				
			||||||
 | 
					                            (int)cfg->TimeRange.count(pop_carry_over_end_time_range) <= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            qCritical() << DBG_HEADER << "PARKING_ALLOWED. startTime" << startTime.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					                            return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED", startTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        } else
 | 
				
			||||||
 | 
					                        // search entry in time-range-field of tariff-file
 | 
				
			||||||
                        if (cfg->TimeRange.count(pop_carry_over_start_time_range) == 1 &&
 | 
					                        if (cfg->TimeRange.count(pop_carry_over_start_time_range) == 1 &&
 | 
				
			||||||
                            cfg->TimeRange.count(pop_carry_over_end_time_range) == 1) {
 | 
					                            cfg->TimeRange.count(pop_carry_over_end_time_range) == 1) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            ATBTimeRange s = cfg->TimeRange.find(pop_carry_over_start_time_range)->second;
 | 
					                            ATBTimeRange s = cfg->TimeRange.find(pop_carry_over_start_time_range)->second;
 | 
				
			||||||
                            ATBTimeRange e = cfg->TimeRange.find(pop_carry_over_end_time_range)->second;
 | 
					                            ATBTimeRange e = cfg->TimeRange.find(pop_carry_over_end_time_range)->second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            // qCritical() << DBG_HEADER
 | 
				
			||||||
 | 
					                            //             << "startTime" << startTime.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            if (startTime >= s.getTimeFrom() && startTime <= s.getTimeUntil()) {
 | 
					                            if (startTime >= s.getTimeFrom() && startTime <= s.getTimeUntil()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                QDateTime sd = start;
 | 
					                                QDateTime sd = start;
 | 
				
			||||||
                                sd.setTime(s.getTimeUntil());
 | 
					                                sd.setTime(s.getTimeUntil());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                // qCritical() << DBG_HEADER << "jumpFrom" << sd.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                QDateTime ed = start.addDays(1);
 | 
					                                QDateTime ed = start.addDays(1);
 | 
				
			||||||
                                ed.setTime(e.getTimeFrom());
 | 
					                                ed.setTime(e.getTimeFrom());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                // qCritical() << DBG_HEADER << "to" << ed.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                int const jumpSecs = sd.secsTo(ed);
 | 
					                                int const jumpSecs = sd.secsTo(ed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                // qCritical() << DBG_HEADER << "jumpSecs" << jumpSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                QDateTime const end = start.addSecs(netto_parking_time*60 + jumpSecs);
 | 
					                                QDateTime const end = start.addSecs(netto_parking_time*60 + jumpSecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                // qCritical() << DBG_HEADER << "new end" << end.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                if (end.time() <= e.getTimeUntil()) {
 | 
					                                if (end.time() <= e.getTimeUntil()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    qCritical() << DBG_HEADER
 | 
					                                    qCritical() << DBG_HEADER
 | 
				
			||||||
@@ -699,13 +960,13 @@ CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
				
			|||||||
                                    return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
 | 
					                                    return CalcState(CalcState::State::SUCCESS, "PARKING_ALLOWED",
 | 
				
			||||||
                                                     startTime, end.time());
 | 
					                                                     startTime, end.time());
 | 
				
			||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    errorStr = QString("endTime %1 exceeds [%2, %3))")
 | 
					                                    errorStr = QString("endTime %1 outside [%2, %3))")
 | 
				
			||||||
                                                  .arg(end.toString(Qt::ISODate))
 | 
					                                                  .arg(end.toString(Qt::ISODate))
 | 
				
			||||||
                                                  .arg(sd.toString(Qt::ISODate))
 | 
					                                                  .arg(sd.toString(Qt::ISODate))
 | 
				
			||||||
                                                  .arg(ed.toString(Qt::ISODate));
 | 
					                                                  .arg(ed.toString(Qt::ISODate));
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
                                errorStr = QString("startTime %1 exceeds [%2, %3))")
 | 
					                                errorStr = QString("startTime %1 outside [%2, %3))")
 | 
				
			||||||
                                              .arg(startTime.toString(Qt::ISODate))
 | 
					                                              .arg(startTime.toString(Qt::ISODate))
 | 
				
			||||||
                                              .arg(s.getTimeFrom().toString(Qt::ISODate))
 | 
					                                              .arg(s.getTimeFrom().toString(Qt::ISODate))
 | 
				
			||||||
                                              .arg(s.getTimeUntil().toString(Qt::ISODate));
 | 
					                                              .arg(s.getTimeUntil().toString(Qt::ISODate));
 | 
				
			||||||
@@ -728,6 +989,8 @@ CalcState Calculator::isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qCritical() << DBG_HEADER << "errorStr" << errorStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return CalcState(CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME, errorStr,
 | 
					    return CalcState(CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME, errorStr,
 | 
				
			||||||
                     QTime(), QTime());
 | 
					                     QTime(), QTime());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1827,13 +2090,16 @@ QList<int> Calculator::GetPriceSteps(Configuration * /*cfg*/) const {
 | 
				
			|||||||
    return QList<int>();
 | 
					    return QList<int>();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QList<int> Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) const {
 | 
					QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex) const {
 | 
				
			||||||
    qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "paymentOptionIndex:" << paymentOptionIndex;
 | 
					    qCritical() << "(" << __func__ << ":" << __LINE__ << ")              paymentOptionIndex:" << paymentOptionIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m_timeSteps.size() > paymentOptionIndex) {
 | 
					    if (m_timeSteps.size() > paymentOptionIndex) {
 | 
				
			||||||
        //qCritical() << __PRETTY_FUNCTION__ << "timeSteps:" << m_timeSteps;
 | 
					        if (!m_timeSteps[paymentOptionIndex].isEmpty()) {
 | 
				
			||||||
            return m_timeSteps[paymentOptionIndex];
 | 
					            return m_timeSteps[paymentOptionIndex];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        m_timeSteps.push_back(QList<int>());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QDateTime start = QDateTime::currentDateTime();
 | 
					    QDateTime start = QDateTime::currentDateTime();
 | 
				
			||||||
    start.setTime(QTime(start.time().hour(), start.time().minute(), 0));
 | 
					    start.setTime(QTime(start.time().hour(), start.time().minute(), 0));
 | 
				
			||||||
@@ -1888,7 +2154,7 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
				
			|||||||
                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ") configured minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
					                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ") configured minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    // set dynamic minimal parking time
 | 
					                                    // set dynamic minimal parking time
 | 
				
			||||||
                                    cfg->getPaymentOptions().pop_min_time = timeStep;
 | 
					                                    cfg->getPaymentOptions(paymentOptionIndex).pop_min_time = timeStep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")   computed minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
					                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")   computed minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1935,7 +2201,7 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "NEW timeSteps:" << m_timeSteps;
 | 
					    qCritical() << "(" << __func__ << ":" << __LINE__ << ")                   NEW timeSteps:" << m_timeSteps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return m_timeSteps[paymentOptionIndex];
 | 
					    return m_timeSteps[paymentOptionIndex];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2003,6 +2269,9 @@ Calculator::GetDailyTicketPrice(Configuration* cfg,
 | 
				
			|||||||
        if (dailyTickets) {
 | 
					        if (dailyTickets) {
 | 
				
			||||||
            QVector<ATBDailyTicket> const tickets = dailyTickets.value();
 | 
					            QVector<ATBDailyTicket> const tickets = dailyTickets.value();
 | 
				
			||||||
            switch (permitType) {
 | 
					            switch (permitType) {
 | 
				
			||||||
 | 
					                case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET: {
 | 
				
			||||||
 | 
					                    // TODO
 | 
				
			||||||
 | 
					                } break;
 | 
				
			||||||
                case PERMIT_TYPE::FOOD_STAMP: {
 | 
					                case PERMIT_TYPE::FOOD_STAMP: {
 | 
				
			||||||
                    // TODO
 | 
					                    // TODO
 | 
				
			||||||
                } break;
 | 
					                } break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <QString>
 | 
					#include <QString>
 | 
				
			||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					#include <QRegularExpression>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <inheritdoc/>
 | 
					/// <inheritdoc/>
 | 
				
			||||||
MemberType Configuration::IdentifyJsonMember(const char* member_name)
 | 
					MemberType Configuration::IdentifyJsonMember(const char* member_name)
 | 
				
			||||||
@@ -436,6 +437,60 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
				
			|||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        } else if (strcmp(inner_obj_name, "pop_time_step_config") == 0) {
 | 
					                        } else if (strcmp(inner_obj_name, "pop_time_step_config") == 0) {
 | 
				
			||||||
                            this->currentPaymentOptions.last().pop_time_step_config = k->value.GetInt();
 | 
					                            this->currentPaymentOptions.last().pop_time_step_config = k->value.GetInt();
 | 
				
			||||||
 | 
					                        } else if ((strcmp(inner_obj_name, "pop_min_date_time") == 0)
 | 
				
			||||||
 | 
					                                || (strcmp(inner_obj_name, "pop_max_date_time") == 0)) {
 | 
				
			||||||
 | 
					                            if (k->value.IsString()) { // -w0dFriT16:20:00 or +w0dMonT00:00:00
 | 
				
			||||||
 | 
					                                static const QRegularExpression re(R"(([+-])w([0-9]+)d([A-Za-z]{3})T([0-9]{2}:[0-9]{2}:[0-9]{2}))");
 | 
				
			||||||
 | 
					                                QString const &s = QString::fromStdString(k->value.GetString());
 | 
				
			||||||
 | 
					                                QRegularExpressionMatch match = re.match(s);
 | 
				
			||||||
 | 
					                                if (match.hasMatch()) {
 | 
				
			||||||
 | 
					                                    ATBPaymentOption::ATBMaxDateTime dt;
 | 
				
			||||||
 | 
					                                    int lastCaptured = match.lastCapturedIndex();
 | 
				
			||||||
 | 
					                                    if (lastCaptured == 4) {
 | 
				
			||||||
 | 
					                                        dt.direction = (match.captured(1) == "-") ? -1 : +1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        bool ok;
 | 
				
			||||||
 | 
					                                        uint8_t week = match.captured(2).toUInt(&ok);
 | 
				
			||||||
 | 
					                                        if (ok) {
 | 
				
			||||||
 | 
					                                            dt.week = week;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        QString const &day = match.captured(3);
 | 
				
			||||||
 | 
					                                        if (day.compare("Mon", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Monday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Tue", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Tuesday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Wed", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Wednesday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Thu", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Thursday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Fri", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Friday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Sat", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Saturday;
 | 
				
			||||||
 | 
					                                        } else if (day.compare("Sun", Qt::CaseInsensitive) == 0) {
 | 
				
			||||||
 | 
					                                            dt.day = (int)Qt::Sunday;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        QTime t = QTime::fromString(match.captured(4), Qt::ISODate);
 | 
				
			||||||
 | 
					                                        if (t.isValid()) {
 | 
				
			||||||
 | 
					                                            dt.time = t;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    if (strcmp(inner_obj_name, "pop_min_date_time") == 0) {
 | 
				
			||||||
 | 
					                                        this->currentPaymentOptions.last().pop_min_date_time = dt;
 | 
				
			||||||
 | 
					                                    } else
 | 
				
			||||||
 | 
					                                    if (strcmp(inner_obj_name, "pop_max_date_time") == 0) {
 | 
				
			||||||
 | 
					                                        this->currentPaymentOptions.last().pop_max_date_time = dt;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } else if (strcmp(inner_obj_name, "pop_carry_over_target") == 0) {
 | 
				
			||||||
 | 
					                            if (k->value.IsBool()) {
 | 
				
			||||||
 | 
					                                bool const v = k->value.GetBool();
 | 
				
			||||||
 | 
					                                this->currentPaymentOptions.last().pop_carry_over_target = v;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
					case MemberType::DurationType:
 | 
										case MemberType::DurationType:
 | 
				
			||||||
@@ -583,7 +638,7 @@ int Configuration::getPaymentOptionIndex(QDateTime const &dt) const {
 | 
				
			|||||||
        if (sd.ped_id != 0) {
 | 
					        if (sd.ped_id != 0) {
 | 
				
			||||||
            for (int opt=0; opt < numOptions; ++opt) {
 | 
					            for (int opt=0; opt < numOptions; ++opt) {
 | 
				
			||||||
                uint64_t const pop_id = getPaymentOptions(opt).pop_id;
 | 
					                uint64_t const pop_id = getPaymentOptions(opt).pop_id;
 | 
				
			||||||
                if (pop_id == sd.ped_payment_option_id) {
 | 
					                if (pop_id == (uint64_t)sd.ped_payment_option_id) {
 | 
				
			||||||
                    return opt;
 | 
					                    return opt;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -627,7 +682,8 @@ int Configuration::getPaymentOptionIndex(QDateTime const &dt) const {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return -1;
 | 
					    qCritical() << DBG_HEADER << "ERROR: DEFAULT VALUE OF '0' RETURNED AS STATIC VALUE";
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ATBSpecialDays Configuration::specialDay(QDateTime const &dt) const {
 | 
					ATBSpecialDays Configuration::specialDay(QDateTime const &dt) const {
 | 
				
			||||||
@@ -718,12 +774,38 @@ Configuration::getTariffProductForAllKeys() const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::optional<QVector<ATBTariffProduct>>
 | 
					std::optional<QVector<ATBTariffProduct>>
 | 
				
			||||||
Configuration::getTariffProductForProductId(PermitType permitType) const {
 | 
					Configuration::getTariffProductForProductTypeName(QString const &permitTypeName) const {
 | 
				
			||||||
    QVector<ATBTariffProduct> products;
 | 
					    QVector<ATBTariffProduct> products;
 | 
				
			||||||
    std::optional<QVector<ATBTariffProduct>> value;
 | 
					    std::optional<QVector<ATBTariffProduct>> value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    products.clear();
 | 
					    products.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(const auto &product: this->TariffProduct) {
 | 
				
			||||||
 | 
					        ATBTariffProduct const &v = product.second;
 | 
				
			||||||
 | 
					        if (v.m_tariff_product_name == permitTypeName) {
 | 
				
			||||||
 | 
					            products.append(v);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (products.size() > 0) {
 | 
				
			||||||
 | 
					        value = value.value_or(products);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::optional<QVector<ATBTariffProduct>>
 | 
				
			||||||
 | 
					Configuration::getTariffProductForProductId(PermitType permitType) const {
 | 
				
			||||||
 | 
					    QString permitTypeName(permitType);
 | 
				
			||||||
 | 
					    return getTariffProductForProductTypeName(permitTypeName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					    QVector<ATBTariffProduct> products;
 | 
				
			||||||
 | 
					    std::optional<QVector<ATBTariffProduct>> value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    products.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto[it, rangeEnd] = this->TariffProduct.equal_range(permitType); it != rangeEnd; ++it) {
 | 
					    for (auto[it, rangeEnd] = this->TariffProduct.equal_range(permitType); it != rangeEnd; ++it) {
 | 
				
			||||||
        products.append(it->second);
 | 
					        products.append(it->second);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -733,6 +815,7 @@ Configuration::getTariffProductForProductId(PermitType permitType) const {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::optional<QVector<ATBTariffProduct>>
 | 
					std::optional<QVector<ATBTariffProduct>>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -334,11 +334,11 @@ QTime Utilities::SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDa
 | 
				
			|||||||
    return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QTime Utilities::SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator it) {
 | 
					QTime Utilities::SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator const &it) {
 | 
				
			||||||
    return QTime::fromString(it->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(it->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QTime Utilities::SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator it) {
 | 
					QTime Utilities::SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator const &it) {
 | 
				
			||||||
    return QTime::fromString(it->second.pedwt_time_to.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(it->second.pedwt_time_to.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -346,15 +346,15 @@ QTime Utilities::SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialD
 | 
				
			|||||||
    return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_to.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_to.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QTime Utilities::WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr) {
 | 
					QTime Utilities::WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr) {
 | 
				
			||||||
    return QTime::fromString(itr->second.pwd_time_from.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(itr->second.pwd_time_from.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QTime Utilities::WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr) {
 | 
					QTime Utilities::WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr) {
 | 
				
			||||||
    return QTime::fromString(itr->second.pwd_time_to.c_str(), Qt::ISODate);
 | 
					    return QTime::fromString(itr->second.pwd_time_to.c_str(), Qt::ISODate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Utilities::WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr) {
 | 
					int Utilities::WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr) {
 | 
				
			||||||
    return itr->second.pwd_period_day_in_week_id;
 | 
					    return itr->second.pwd_period_day_in_week_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -406,9 +406,16 @@ uint32_t Utilities::getMaximalParkingPrice(Configuration const *cfg, PaymentMeth
 | 
				
			|||||||
    return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_max_price, 0);
 | 
					    return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_max_price, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t Utilities::getDailyTicketCardPrice(Configuration const *cfg, PaymentMethod methodId) {
 | 
				
			||||||
 | 
					    return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_daily_card_price, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t Utilities::getTimeRangeStep(Configuration const *cfg, int step, PaymentMethod methodId) {
 | 
					uint32_t Utilities::getTimeRangeStep(Configuration const *cfg, int step, PaymentMethod methodId) {
 | 
				
			||||||
    if (methodId == PaymentMethod::Progressive) {
 | 
					    if (methodId == PaymentMethod::Progressive) {
 | 
				
			||||||
        return std::max((int)cfg->TimeRange.find(step)->second.time_range_to_in_minutes_from_start, 0);
 | 
					        Configuration::TimeRangeType::const_iterator it = cfg->TimeRange.find(step);
 | 
				
			||||||
 | 
					        if (it != cfg->TimeRange.cend()) {
 | 
				
			||||||
 | 
					            return std::max((int)(it->second.time_range_to_in_minutes_from_start), 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										882
									
								
								main/MessageHelper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										882
									
								
								main/MessageHelper.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,882 @@
 | 
				
			|||||||
 | 
					#include "MessageHelper.h"
 | 
				
			||||||
 | 
					#include "terminal_utils.h"
 | 
				
			||||||
 | 
					#include "aes128.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QDateTime>
 | 
				
			||||||
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_COINCOIDE_H               0x09
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_COINCOIDE_L               0x78
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MAX_ARRAY_SIZE	        1024
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE	    300
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MAX_RX_PACKET_SIZE	    10000   // 17000
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MIN_PACKET_SIZE	        16
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE        32
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE   16
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_POLYNOME	                0xedb88320	// 0x04C11DB7
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_POLYNOME_INITIAL	        0		    // 0xFFFFFFFF
 | 
				
			||||||
 | 
					#define IUC_ASYNCHPOS_PRINTTIMOUT               1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PACKET_ID_SIZE      8
 | 
				
			||||||
 | 
					#define MAX_POSID_LENGTH    255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STX     ((char)0x01)
 | 
				
			||||||
 | 
					#define ETX1    ((char)0x02)
 | 
				
			||||||
 | 
					#define ETX2    ((char)0x03)
 | 
				
			||||||
 | 
					#define EOT     ((char)0x04)
 | 
				
			||||||
 | 
					#define ENQ     ((char)0x05)
 | 
				
			||||||
 | 
					#define ACK1    ((char)0x06)
 | 
				
			||||||
 | 
					#define ACK2    ((char)0x07)
 | 
				
			||||||
 | 
					#define DLE     ((char)0x10)
 | 
				
			||||||
 | 
					#define NAK     ((char)0x15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DBG_EMERGENCY   (0) // System is unusable
 | 
				
			||||||
 | 
					#define DBG_ALERT       (1) // Action must be taken immediately
 | 
				
			||||||
 | 
					#define DBG_CRITICAL    (2) // Critical conditions
 | 
				
			||||||
 | 
					#define DBG_ERROR       (3) // Error conditions
 | 
				
			||||||
 | 
					#define DBG_WARNING     (4) // Warning conditions
 | 
				
			||||||
 | 
					#define DBG_NOTICE      (5) // Normal but significant conditions
 | 
				
			||||||
 | 
					                            // Conditions that are not error conditions, but that may require special handling
 | 
				
			||||||
 | 
					#define DBG_INFORMATION (6) // Informational messages
 | 
				
			||||||
 | 
					                            // Confirmation that the program is working as expected
 | 
				
			||||||
 | 
					#define DBG_DEBUG       (7) // Debug-level messages
 | 
				
			||||||
 | 
					                            // Messages that contain information normally of use only when debugging a program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int DBG_LEVEL = DBG_INFORMATION;
 | 
				
			||||||
 | 
					//static int DBG_LEVEL = DBG_DEBUG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct MessageHeader {
 | 
				
			||||||
 | 
					    uint8_t packetType;
 | 
				
			||||||
 | 
					    uint8_t packetID[PACKET_ID_SIZE];
 | 
				
			||||||
 | 
					    uint8_t POSIDLength;
 | 
				
			||||||
 | 
					    uint8_t POSID[MAX_POSID_LENGTH];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MessageHelper::AsynchBillData MessageHelper::m_asyncBillData;
 | 
				
			||||||
 | 
					MessageHelper::AuthorizationResult MessageHelper::m_authorizationResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MessageHelper::MessageHelper(QString const &posID, QString const &apak)
 | 
				
			||||||
 | 
					  : m_posID(posID.toUtf8().constData())
 | 
				
			||||||
 | 
					  , m_posIDLength(m_posID.size())
 | 
				
			||||||
 | 
					  , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00)
 | 
				
			||||||
 | 
					  , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) {
 | 
				
			||||||
 | 
					    m_messageHeaderPrefix[9] = (uint8_t)m_posID.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int p = 0; p < apak.size(); p+=2) {
 | 
				
			||||||
 | 
					        uint8_t n = strtoul(apak.mid(p, 2).toStdString().c_str(), nullptr, 16);
 | 
				
			||||||
 | 
					        m_apak.push_back(n);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << apak << m_apak.toHex(':');
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << m_posID.toHex(':');
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MessageHelper::MessageHelper(QByteArray const &posID, QString const &apak)
 | 
				
			||||||
 | 
					  : m_posID(posID)
 | 
				
			||||||
 | 
					  , m_posIDLength(m_posID.size())
 | 
				
			||||||
 | 
					  , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00)
 | 
				
			||||||
 | 
					  , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) {
 | 
				
			||||||
 | 
					    m_messageHeaderPrefix[9] = (uint8_t)m_posID.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int p = 0; p < apak.size(); p+=2) {
 | 
				
			||||||
 | 
					        uint8_t n = strtoul(apak.mid(p, 2).toStdString().c_str(), nullptr, 16);
 | 
				
			||||||
 | 
					        m_apak.push_back(n);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << apak << m_apak.toHex(':');
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << m_posID.toHex(':');
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MessageHelper::~MessageHelper() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::handleMessage(char const *pData) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					    //unsigned char marker = pData[0];
 | 
				
			||||||
 | 
					//	unsigned int tagNameLength = pData[1];
 | 
				
			||||||
 | 
					    unsigned char tagName[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE];
 | 
				
			||||||
 | 
					//	unsigned int curElementLength = 0;
 | 
				
			||||||
 | 
					    //unsigned char curElement[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE];
 | 
				
			||||||
 | 
					    //unsigned char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1];
 | 
				
			||||||
 | 
					    unsigned char rxBuf[20];
 | 
				
			||||||
 | 
					//	unsigned char flags[129];
 | 
				
			||||||
 | 
					//	unsigned char docNr[32];
 | 
				
			||||||
 | 
					    //unsigned char messageType = pData[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned int uitmp = 0;
 | 
				
			||||||
 | 
					    unsigned int uitmp2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iuc_asynchpos_sub_initArray(tagName, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE);
 | 
				
			||||||
 | 
					    //iuc_asynchpos_sub_initArray(curElement, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("LoginResult",pData) | biox_FindStrInBuffer("LOGINRESULT",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        asynchState = 0x02;	//eingeloggt
 | 
				
			||||||
 | 
					        /*rxBuf[0] = 0x45;
 | 
				
			||||||
 | 
					        rxBuf[1] = 0x00;
 | 
				
			||||||
 | 
					        rxBuf[2] = 0x00;
 | 
				
			||||||
 | 
					        vmc_SendWithBuffer(rxBuf,40,0x69,0);*/
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("AuthorizationStarted",pData) | biox_FindStrInBuffer("AUTHORIZATIONSTARTED",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        iuc_asynchpos_sub_initArray(rxBuf,5);
 | 
				
			||||||
 | 
					        rxBuf[0] = 0x53;
 | 
				
			||||||
 | 
					        rxBuf[1] = 0x00;
 | 
				
			||||||
 | 
					        rxBuf[2] = 0x00;
 | 
				
			||||||
 | 
					        vmc_SendWithBuffer(rxBuf,5,0x69,0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("AuthorizationResult",pData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        asynchState = 0x03; //successfully authorized
 | 
				
			||||||
 | 
					        iuc_asynchpos_sub_clear_message(0x00);
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("ID",pData);
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData);
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					        //uitmp = biox_FindStrInBuffer("Result",pData) | biox_FindStrInBuffer("RESULT",pData);
 | 
				
			||||||
 | 
					        //biox_CopyBlock(pData, uitmp + 2, asynchBill.result, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        brd_SendDiagStr("->IUC ASYNCHPOS message ID: ",0);
 | 
				
			||||||
 | 
					        brd_SendDiagBlock(asynchBill.id,1,36);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*if (iuc_asynch_PrintControl) {
 | 
				
			||||||
 | 
					            brd_SendDiagStr("->IUC ASYNCHPOS print data send AUTH: ",1);
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
 | 
				
			||||||
 | 
					            iuc_asynch_PrintControl = 0x00;
 | 
				
			||||||
 | 
					            //biox_delay_ms(750);
 | 
				
			||||||
 | 
					        }   else {
 | 
				
			||||||
 | 
					            brd_SendDiagStr("->IUC ASYNCHPOS sending authorization: ",1);
 | 
				
			||||||
 | 
					            iuc_asynch_PrintControl = 0x01;
 | 
				
			||||||
 | 
					        }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("ERROR",pData);
 | 
				
			||||||
 | 
					        if (!uitmp/*biox_FindStrInBuffer("OK",pData) | biox_FindStrInBuffer("Approved",pData) | biox_FindStrInBuffer("APPROVED",asynchBill.result)*/) {
 | 
				
			||||||
 | 
					            iuc_asynch_PrintControl |= 0xF0;
 | 
				
			||||||
 | 
					            /*uitmp = biox_FindStrInBufferInt("Amount",pData) | biox_FindStrInBufferInt("AMOUNT",pData);
 | 
				
			||||||
 | 
					            //if (pData[uitmp + 1] <= 10) {
 | 
				
			||||||
 | 
					                biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            //} else {
 | 
				
			||||||
 | 
					                //biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, 10);
 | 
				
			||||||
 | 
					            //}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //uitmp = biox_FindStrInBuffer("Token",pData);
 | 
				
			||||||
 | 
					            //biox_CopyBlock(pData, uitmp + 2, asynchBill.token, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            /*uitmp = biox_FindStrInBufferInt("Authcode",pData) | biox_FindStrInBufferInt("AUTHCODE",pData);
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, asynchBill.authCode, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            uitmp = biox_FindStrInBufferInt("RRN",pData);
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, asynchBill.rrn, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            uitmp = biox_FindStrInBufferInt("STAN",pData);
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, asynchBill.stan, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            uitmp = biox_FindStrInBufferInt("CardType",pData) | biox_FindStrInBufferInt("CARDTYPE",pData);
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, asynchBill.cardtype, 0, pData[uitmp + 1]);*/
 | 
				
			||||||
 | 
					            asynchState = 0x04;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            brd_SendDiagStr("->IUC ASYNCHPOS authorization confirmed.",1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*iuc_asynchpos_sub_initArray(rxBuf,20);
 | 
				
			||||||
 | 
					            rxBuf[0] = 0x45;
 | 
				
			||||||
 | 
					            rxBuf[1] = 0x00;
 | 
				
			||||||
 | 
					            rxBuf[2] = 0x00;
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(rxBuf,20,0x69,0);*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //iuc_asynchpos_resetBuffers(0x01);
 | 
				
			||||||
 | 
					            //iuc_asynchpos_command_close_Document();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            iuc_asynch_PrintControl |= 0xF0;
 | 
				
			||||||
 | 
					            //uitmp = biox_FindStrInBufferInt("ErrCode",pData) | biox_FindStrInBufferInt("ERRCODE",pData);
 | 
				
			||||||
 | 
					            //biox_CopyBlock(pData, uitmp + 2, asynchBill.errCode, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            brd_SendDiagStr("->IUC ASYNCHPOS authorization failed.",1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*iuc_asynchpos_sub_initArray(rxBuf,20);
 | 
				
			||||||
 | 
					            rxBuf[0] = 0x45;
 | 
				
			||||||
 | 
					            rxBuf[1] = 0xFF;
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, rxBuf, 2, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(rxBuf,20,0x69,0);*/
 | 
				
			||||||
 | 
					            iuc_asynch_keepAlive = 0x00;
 | 
				
			||||||
 | 
					            //VendRequest=0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("PrintReceipt",pData) | biox_FindStrInBufferInt("PRINTRECEIPT",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        asynchState = 0x03; //Customer receipt recieved
 | 
				
			||||||
 | 
					        //iuc_asynchpos_sub_initArray(flags,129);
 | 
				
			||||||
 | 
					        //uitmp = biox_FindStrInBufferInt("Flag",pData) | biox_FindStrInBufferInt("FLAG",pData) | biox_FindStrInBufferInt("Flags",pData) | biox_FindStrInBufferInt("FLAGS",pData);
 | 
				
			||||||
 | 
					        /*if (uitmp) {
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, flags, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					            uitmp = biox_FindStrInBufferInt("CD",flags) | biox_FindStrInBufferInt("LR",flags);
 | 
				
			||||||
 | 
					        }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*iuc_asynchpos_sub_clear_message(0x00);
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("ID",pData);
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData);
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);*/
 | 
				
			||||||
 | 
					        iuc_asynchpos_sub_initArray(asynchBill.printId,129);
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("ID",pData);
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, asynchBill.printId, 0, pData[uitmp + 1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //if(asynchState == 0x02/* && uitmp biox_FindStrInBufferInt("CD",flags) || biox_FindStrInBufferInt("LR",flags)*/) {
 | 
				
			||||||
 | 
					        if((!iuc_asynch_PRNrecieved) && (biox_FindStrInBufferInt("CD",pData) || biox_FindStrInBufferInt("LR",pData)) )	{
 | 
				
			||||||
 | 
					            iuc_asynch_PRNrecieved = 0x01;
 | 
				
			||||||
 | 
					            iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1);
 | 
				
			||||||
 | 
					            uitmp = /*biox_FindStrInBuffer("ReceiptText",pData) | */biox_FindStrInBufferInt("RECEIPTTEXT",pData);
 | 
				
			||||||
 | 
					            uitmp2 = (pData[uitmp] * 256) + pData[uitmp + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //if (uitmp2 <= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
 | 
				
			||||||
 | 
					            if (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
 | 
				
			||||||
 | 
					                uitmp2 = IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
 | 
				
			||||||
 | 
					                brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large! Cutting off.",1);
 | 
				
			||||||
 | 
					                /*receiptData[0] = 0x50;
 | 
				
			||||||
 | 
					                biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*);
 | 
				
			||||||
 | 
					                //uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
 | 
				
			||||||
 | 
					                //uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0);
 | 
				
			||||||
 | 
					                brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
 | 
				
			||||||
 | 
					                iuc_asynch_PrintControl |= 0x0F;*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /*if (iuc_asynch_PrintControl) {
 | 
				
			||||||
 | 
					                    brd_SendDiagStr("->IUC ASYNCHPOS print data send: ",1);
 | 
				
			||||||
 | 
					                    vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
 | 
				
			||||||
 | 
					                    iuc_asynch_PrintControl = 0x00;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    brd_SendDiagStr("->IUC ASYNCHPOS print data stored: ",1);
 | 
				
			||||||
 | 
					                    iuc_asynch_PrintControl = 0x01;
 | 
				
			||||||
 | 
					                }*/
 | 
				
			||||||
 | 
					                //biox_delay_ms(750);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //iuc_asynchpos_resetBuffers(0x01);
 | 
				
			||||||
 | 
					                //iuc_asynchpos_command_close_Document();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //iuc_asynchpos_resetBuffers(0x02);
 | 
				
			||||||
 | 
					                //iuc_asynchpos_command_print_Result(0x01);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            receiptData[0] = 0x50;
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*/);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0);
 | 
				
			||||||
 | 
					            brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
 | 
				
			||||||
 | 
					            iuc_asynch_PrintControl |= 0x0F;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* else {
 | 
				
			||||||
 | 
					                //receiptData[0] = 0x50;
 | 
				
			||||||
 | 
					                //iuc_asynchpos_sub_initZero(receiptData,1);
 | 
				
			||||||
 | 
					                brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large!",1);
 | 
				
			||||||
 | 
					                iuc_asynch_PrintControl |= 0x0E;
 | 
				
			||||||
 | 
					            } */
 | 
				
			||||||
 | 
					            /* else {
 | 
				
			||||||
 | 
					                //iuc_asynchpos_resetBuffers(0x02);
 | 
				
			||||||
 | 
					                iuc_asynchpos_command_print_Result(0x00);
 | 
				
			||||||
 | 
					            }*/
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //++iuc_print_counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //if(asynchState == 0x04 && iuc_asynch_PrintControl == 0) {
 | 
				
			||||||
 | 
					            //iuc_asynchpos_resetBuffers(0x01);
 | 
				
			||||||
 | 
					            //iuc_asynchpos_resetBuffers(0x00);
 | 
				
			||||||
 | 
					            //iuc_asynchpos_command_print_Result(0x01);
 | 
				
			||||||
 | 
					        /*} /else {
 | 
				
			||||||
 | 
					            //iuc_asynchpos_resetBuffers(0x02);
 | 
				
			||||||
 | 
					            iuc_asynchpos_command_print_Result(0x01);
 | 
				
			||||||
 | 
					        }*/
 | 
				
			||||||
 | 
					            //iuc_asynchpos_command_print_Result(0x01);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*while (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) {
 | 
				
			||||||
 | 
					            biox_CopyBlock(pData, uitmp + 2, receiptData, 0, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);
 | 
				
			||||||
 | 
					            uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
 | 
				
			||||||
 | 
					            uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE;
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Rest des Packets
 | 
				
			||||||
 | 
					        biox_CopyBlock(pData, uitmp + 2, receiptData, 0, uitmp2);
 | 
				
			||||||
 | 
					        vmc_SendWithBuffer(receiptData,uitmp2,0x69,0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //iuc_asynchpos_resetBuffers(0x02);
 | 
				
			||||||
 | 
					        iuc_asynchpos_command_print_Result(0x01);*/
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("VoidResult",pData) | biox_FindStrInBufferInt("VOIDRESULT",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        asynchState = 0x01; //There was a cancel. Relogin and try again.
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("ERROR",pData);
 | 
				
			||||||
 | 
					        if (uitmp) {
 | 
				
			||||||
 | 
					            rxBuf[0] = 0x45;
 | 
				
			||||||
 | 
					            rxBuf[1] = 0x56;
 | 
				
			||||||
 | 
					            rxBuf[2] = 0x45;
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(rxBuf,3,0x69,0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uitmp = biox_FindStrInBufferInt("REFUND",pData);
 | 
				
			||||||
 | 
					        if (uitmp) {
 | 
				
			||||||
 | 
					            rxBuf[0] = 0x45;
 | 
				
			||||||
 | 
					            rxBuf[1] = 0x56;
 | 
				
			||||||
 | 
					            rxBuf[2] = 0x52;
 | 
				
			||||||
 | 
					            vmc_SendWithBuffer(rxBuf,3,0x69,0);
 | 
				
			||||||
 | 
					            //TODO refund bill here. Should not trigger, but it might.
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uitmp = biox_FindStrInBufferInt("DocClosed",pData);
 | 
				
			||||||
 | 
					    if (uitmp) {
 | 
				
			||||||
 | 
					        asynchState = 0x01; //Transaction successful
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //if (VendRequest)
 | 
				
			||||||
 | 
					            GWstate.VendRequest=0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::handleCommand(AsyncPosCommand command, char status) {
 | 
				
			||||||
 | 
					    //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					    UCHAR	tempBuf[3];
 | 
				
			||||||
 | 
					    UCHAR	rxBuf[8];
 | 
				
			||||||
 | 
					//	UINT	uitemp = 0;
 | 
				
			||||||
 | 
					UINT uitmp= 700;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tempBuf[0] = 0x00;
 | 
				
			||||||
 | 
					    tempBuf[1] = 0x00;
 | 
				
			||||||
 | 
					    tempBuf[2] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    timeHoldISMAS = GWglobTime.SecOfDay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iuc_asynchpos_sub_initArray(rxBuf,8);
 | 
				
			||||||
 | 
					    //iuc_asynchpos_resetBuffers(0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (command) {
 | 
				
			||||||
 | 
					        case 0x72:	//registration
 | 
				
			||||||
 | 
					                    //iuc_asynchpos_init();
 | 
				
			||||||
 | 
					                    asynchState = 0x01;
 | 
				
			||||||
 | 
					                    iuc_asynchpos_command_Login();
 | 
				
			||||||
 | 
					                    GWstate.VendRequest=1;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x61:	//authorisation
 | 
				
			||||||
 | 
					                    iuc_asynch_keepAlive = 0x01;
 | 
				
			||||||
 | 
					                    iuc_asynch_PrintControl = 0;
 | 
				
			||||||
 | 
					                    iuc_asynchpos_sub_clear_message(0x01);
 | 
				
			||||||
 | 
					                    //VendRequest=1;
 | 
				
			||||||
 | 
					                    iuc_asynchpos_resetBuffers(0x00);
 | 
				
			||||||
 | 
					                    ///#ifdef IUC_ASYCHNPOS_TESTMODE
 | 
				
			||||||
 | 
					                    //iuc_asynchpos_command_authorize(uitmp);
 | 
				
			||||||
 | 
					                    //#else
 | 
				
			||||||
 | 
					                    iuc_asynchpos_command_authorize(Vend.Amount);
 | 
				
			||||||
 | 
					                    //#endif
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x63:	//cancel
 | 
				
			||||||
 | 
					        case 0x73:	//storno
 | 
				
			||||||
 | 
					                    /*if (asynchState <= 0x02 != 0) {	//Authorization result recieved?
 | 
				
			||||||
 | 
					                        iuc_asynchpos_command_cancel_authorize();
 | 
				
			||||||
 | 
					                    } else {*/
 | 
				
			||||||
 | 
					                        iuc_asynchpos_command_close_Document(0x01);
 | 
				
			||||||
 | 
					                    //}
 | 
				
			||||||
 | 
					                    iuc_asynch_keepAlive = 0x00;
 | 
				
			||||||
 | 
					                    //VendRequest=0;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x6B:	//kassenschnitt
 | 
				
			||||||
 | 
					                    iuc_asynchpos_command_Logout();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x62:	//get last bill
 | 
				
			||||||
 | 
					                    //iuc_zvt_getLastBill(tempBuf);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x01:	iuc_asynchpos_command_close_Document(0x00);
 | 
				
			||||||
 | 
					                    iuc_asynch_keepAlive = 0x00;
 | 
				
			||||||
 | 
					                    //VendRequest=0;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        case 0x70:	iuc_asynchpos_command_ping_terminal();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createRawPacket(PacketType packetType,
 | 
				
			||||||
 | 
					                                    QByteArray const &encryptedPacketID,
 | 
				
			||||||
 | 
					                                    QByteArray const &message) {
 | 
				
			||||||
 | 
					    if (createMessageHeaderPrefix(packetType, encryptedPacketID)) {
 | 
				
			||||||
 | 
					        QByteArray ba(m_messageHeaderPrefix);
 | 
				
			||||||
 | 
					        ba = ba.append(m_posID);
 | 
				
			||||||
 | 
					        ba = ba.append(message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint16_t const size = ba.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ba.push_front((char)size);
 | 
				
			||||||
 | 
					        ba.push_front((char)(size >> 8));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_rawPacket = ba;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MessageHelper::setMessageHeaderPacketType(PacketType packetType) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (packetType) {
 | 
				
			||||||
 | 
					    case PacketType::POS_ECR:
 | 
				
			||||||
 | 
					    case PacketType::MESSAGE_RECEIVED_POSITIVE_ACK:
 | 
				
			||||||
 | 
					    case PacketType::MESSAGE_RECEIVED_NEGATIVE_ACK:
 | 
				
			||||||
 | 
					        m_messageHeaderPrefix[0] = (uint8_t)packetType;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MessageHelper::createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID) {
 | 
				
			||||||
 | 
					    if (encryptedPacketID.size() == PACKET_ID_SIZE) {
 | 
				
			||||||
 | 
					        if (setMessageHeaderPacketType(packetType)) {
 | 
				
			||||||
 | 
					            for (int i = 1; i <= 8; ++i) {
 | 
				
			||||||
 | 
					                m_messageHeaderPrefix[i] = (uint8_t)encryptedPacketID[i-1];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray const &MessageHelper::generateUniqueTransactionID(QString const &machineNr,
 | 
				
			||||||
 | 
					                                                             QString const &customerNr) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: wieder entfernen
 | 
				
			||||||
 | 
					    QDateTime dt(QDateTime::fromString("2024-06-18T12:00:00", Qt::ISODate));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint64_t const transID = MessageHelper::secsSinceJan2017(dt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_uniqueTransactionID.clear();
 | 
				
			||||||
 | 
					    m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(std::to_string(transID).c_str(), 9).rightJustified(10, '0'));
 | 
				
			||||||
 | 
					    m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(machineNr.toStdString().c_str()).rightJustified(5, '0'));
 | 
				
			||||||
 | 
					    m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(customerNr.toStdString().c_str()).rightJustified(4, '0'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return m_uniqueTransactionID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// actual payment. amount to pay is known.
 | 
				
			||||||
 | 
					void MessageHelper::createAuthorizeMessage() {
 | 
				
			||||||
 | 
					    m_authorizeMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x89); // 9 in 0x89 is the size
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Authorize"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString const &price= m_price.setNum(1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x06);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Amount"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)price.size());
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray(price.toStdString().c_str()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Cash"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x01);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x30);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x08);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Currency"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x03);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("978"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x05);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("DocNr"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x13);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(generateUniqueTransactionID("1000", "100"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Time"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QDateTime current = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
					    // TODO: wieder entfernen
 | 
				
			||||||
 | 
					    current.setTime(QTime(12, 0, 0));
 | 
				
			||||||
 | 
					    current.setDate(QDate(2024, 6, 18));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray time(current.toString(Qt::ISODate).toStdString().c_str());
 | 
				
			||||||
 | 
					    time[10] = ' ';
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray(time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("Lang"));
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x02);
 | 
				
			||||||
 | 
					    m_authorizeMessage = m_authorizeMessage.append(QByteArray("lt"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_authorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createCancelAuthorizeMessage() {
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.push_back((char)0x96); // 0x80 + 0x16
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage = m_cancelAuthorizeMessage.append(QByteArray("AuthorizationCancelled"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.push_back((char)0x02);
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage = m_authorizeMessage.append(QByteArray("ID"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.push_back((char)QByteArray(m_asyncBillData.id).size());
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage = m_cancelAuthorizeMessage.append(QByteArray(m_asyncBillData.id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_cancelAuthorizeMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createPingMessage() {
 | 
				
			||||||
 | 
					    m_pingMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_pingMessage.push_back((char)0x84); // 4 in 0x84 is the size
 | 
				
			||||||
 | 
					    m_pingMessage = m_pingMessage.append(QByteArray("Ping"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_pingMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_pingMessage = m_authorizeMessage.append(QByteArray("Time"));
 | 
				
			||||||
 | 
					    m_pingMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_pingMessage.push_back((char)0x13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QDateTime current = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
					    // TODO: wieder entfernen
 | 
				
			||||||
 | 
					    current.setTime(QTime(12, 0, 0));
 | 
				
			||||||
 | 
					    current.setDate(QDate(2024, 6, 18));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray time(current.toString(Qt::ISODate).toStdString().c_str());
 | 
				
			||||||
 | 
					    time[10] = ' ';
 | 
				
			||||||
 | 
					    m_pingMessage = m_pingMessage.append(QByteArray(time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_pingMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createCloseDocumentMessage(bool storno) {
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.push_back((char)0x89); // 9 in 0x89 is the size
 | 
				
			||||||
 | 
					    m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("DocClosed"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.push_back((char)0x05);
 | 
				
			||||||
 | 
					    m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("DocNr"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint16_t const docNrSize = m_uniqueTransactionID.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.push_back((char)(docNrSize >> 8));
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.push_back((char)(docNrSize));
 | 
				
			||||||
 | 
					    m_closeDocumentMessage = m_closeDocumentMessage.append(m_uniqueTransactionID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!storno) {
 | 
				
			||||||
 | 
					        m_closeDocumentMessage.push_back((char)0x06);
 | 
				
			||||||
 | 
					        m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("AuthID"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        QByteArray ba(m_authorizationResult.m_id.toStdString().c_str());
 | 
				
			||||||
 | 
					        uint16_t const authIdSize = ba.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_closeDocumentMessage.push_back((char)(authIdSize >> 8));
 | 
				
			||||||
 | 
					        m_closeDocumentMessage.push_back((char)(authIdSize));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_closeDocumentMessage = m_closeDocumentMessage.append(ba);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_closeDocumentMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createPrintResultMessage() {
 | 
				
			||||||
 | 
					    m_printResultMessage.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t MessageHelper::secsSinceJan2017(QDateTime const &dt) {
 | 
				
			||||||
 | 
					    return QDateTime(QDateTime::fromString("2017-01-01T00:00:00", Qt::ISODate)).secsTo(dt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createLoginMessage() {
 | 
				
			||||||
 | 
					    m_loginMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x85); // 5 in 0x85 is the size
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(QByteArray("Login"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(QByteArray("Time"));
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QDateTime current = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
					    // TODO: wieder entfernen
 | 
				
			||||||
 | 
					    current.setTime(QTime(12, 0, 0));
 | 
				
			||||||
 | 
					    current.setDate(QDate(2024, 6, 18));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray time(current.toString(Qt::ISODate).toStdString().c_str());
 | 
				
			||||||
 | 
					    time[10] = ' ';
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x05);
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(QByteArray("Flags"));
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x06);
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(QByteArray("AP3|LR"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_INFORMATION) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << "loginMessage" << m_loginMessage.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MessageHelper::createLogoutMessage() {
 | 
				
			||||||
 | 
					    m_logoutMessage.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_logoutMessage.push_back((char)0x86); // 6 in 0x86 is the size
 | 
				
			||||||
 | 
					    m_logoutMessage = m_loginMessage.append(QByteArray("Logout"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x04);
 | 
				
			||||||
 | 
					    m_loginMessage = m_loginMessage.append(QByteArray("Time"));
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QDateTime current = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
					    // TODO: wieder entfernen
 | 
				
			||||||
 | 
					    current.setTime(QTime(12, 0, 0));
 | 
				
			||||||
 | 
					    current.setDate(QDate(2024, 6, 18));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray time(current.toString(Qt::ISODate).toStdString().c_str());
 | 
				
			||||||
 | 
					    time[10] = ' ';
 | 
				
			||||||
 | 
					    m_logoutMessage = m_logoutMessage.append(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_loginMessage.push_back((char)0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_INFORMATION) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << "loginMessage" << m_logoutMessage.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArrayList const &MessageHelper::createMessageChunksToSend(AsyncPosCommand cmd, char etx) {
 | 
				
			||||||
 | 
					    QByteArray encryptedPacketID(QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_messageChunkList.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (cmd) {
 | 
				
			||||||
 | 
					    case (int)MessageHelper::AsyncPosCommand::LOGIN:
 | 
				
			||||||
 | 
					        createLoginMessage();
 | 
				
			||||||
 | 
					        createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_loginMessage);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case (int)MessageHelper::AsyncPosCommand::LOGOUT:
 | 
				
			||||||
 | 
					        createLogoutMessage();
 | 
				
			||||||
 | 
					        createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_logoutMessage);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case (int)MessageHelper::AsyncPosCommand::AUTHORIZE:
 | 
				
			||||||
 | 
					        createAuthorizeMessage();
 | 
				
			||||||
 | 
					        createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_authorizeMessage);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case (int)MessageHelper::AsyncPosCommand::CLOSE_DOCUMENT:
 | 
				
			||||||
 | 
					        createCloseDocumentMessage(); // actung: hier default parameter
 | 
				
			||||||
 | 
					        createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_closeDocumentMessage);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << m_rawPacket.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray const &ba = m_rawPacket.mid(11);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << ba.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // calculate crc32 on message starting from (including) POSID length
 | 
				
			||||||
 | 
					    uint32_t crc = TU::crc32(ba);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << "crc32" << hex << crc;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned char cipherText[256];
 | 
				
			||||||
 | 
					    memset(cipherText, 0, sizeof(cipherText));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // XOR crc32-value (4 bytes) with APAK starting from left
 | 
				
			||||||
 | 
					    // (rest of APAK untouched)
 | 
				
			||||||
 | 
					    QByteArray clearText(m_apak);
 | 
				
			||||||
 | 
					    clearText[0] = clearText[0] ^ ((uint8_t)(crc >> 24));
 | 
				
			||||||
 | 
					    clearText[1] = clearText[1] ^ ((uint8_t)(crc >> 16));
 | 
				
			||||||
 | 
					    clearText[2] = clearText[2] ^ ((uint8_t)(crc >>  8));
 | 
				
			||||||
 | 
					    clearText[3] = clearText[3] ^ ((uint8_t)(crc >>  0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << "clearText" << clearText.toHex();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // encrypt XOR result with APAK using AES129, ECB mode
 | 
				
			||||||
 | 
					    aes_encrypt((uint8_t *)clearText.data(),
 | 
				
			||||||
 | 
					                (uint8_t *)cipherText,
 | 
				
			||||||
 | 
					                (uint8_t *)m_apak.toStdString().c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 8 left bytes of encryption result is signature (Packet ID)
 | 
				
			||||||
 | 
					    encryptedPacketID = QByteArray((const char *)cipherText, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (DBG_LEVEL >= DBG_INFORMATION) {
 | 
				
			||||||
 | 
					        qCritical() << DBG_HEADER << "cipherText (new PacketID)" << encryptedPacketID.toHex(':');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // insert PacketID in packet
 | 
				
			||||||
 | 
					    if (insertEncryptedPacketID(encryptedPacketID)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // build chunks to be sent over serial line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const chunks = m_rawPacket.size() / IUC_ASYNCHPOS_MIN_PACKET_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					            qCritical() << DBG_HEADER << "nr of chunks" << chunks;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int i = 0;
 | 
				
			||||||
 | 
					        for (; i < chunks; ++i) {
 | 
				
			||||||
 | 
					            QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*i,
 | 
				
			||||||
 | 
					                                                      IUC_ASYNCHPOS_MIN_PACKET_SIZE);
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << i << "unmasked" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageChunk = MessageHelper::mask(messageChunk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << i << "  masked" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char const lrc = TU::lrc(messageChunk);
 | 
				
			||||||
 | 
					            messageChunk.push_back(lrc);
 | 
				
			||||||
 | 
					            messageChunk.push_front(STX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_INFORMATION) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << "chunk to send" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            m_messageChunkList += messageChunk;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const rest = m_rawPacket.size() % IUC_ASYNCHPOS_MIN_PACKET_SIZE;
 | 
				
			||||||
 | 
					        if (rest) {
 | 
				
			||||||
 | 
					            QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*chunks, rest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << i << "unmasked" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageChunk = mask(messageChunk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << i << "  masked" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char const lrc = TU::lrc(messageChunk);
 | 
				
			||||||
 | 
					            messageChunk.push_back(lrc);
 | 
				
			||||||
 | 
					            messageChunk.push_front(STX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (DBG_LEVEL >= DBG_INFORMATION) {
 | 
				
			||||||
 | 
					                qCritical() << DBG_HEADER << "chunk to send" << messageChunk.toHex(':');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            m_messageChunkList += messageChunk;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return m_messageChunkList;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArrayList MessageHelper::createLoginMessageChunksToSend(char etx) {
 | 
				
			||||||
 | 
					    return createMessageChunksToSend(AsyncPosCommand::LOGIN, etx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArrayList MessageHelper::createLogoutMessageChunksToSend(char etx) {
 | 
				
			||||||
 | 
					    return createMessageChunksToSend(AsyncPosCommand::LOGOUT, etx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArrayList MessageHelper::createAuthorizeMessageChunksToSend(char etx) {
 | 
				
			||||||
 | 
					    return createMessageChunksToSend(AsyncPosCommand::AUTHORIZE, etx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArrayList MessageHelper::createCloseDocumentMessageChunksToSend(char etx) {
 | 
				
			||||||
 | 
					    return createMessageChunksToSend(AsyncPosCommand::CLOSE_DOCUMENT, etx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MessageHelper::insertEncryptedPacketID(QByteArray const &encryptedPacketID) {
 | 
				
			||||||
 | 
					    if (encryptedPacketID.size() == PACKET_ID_SIZE) {
 | 
				
			||||||
 | 
					        // m_rawPacket has already full length
 | 
				
			||||||
 | 
					        for (int i = 0; i < PACKET_ID_SIZE; ++i) {
 | 
				
			||||||
 | 
					            m_messageHeaderPrefix[i+1] = encryptedPacketID[i];
 | 
				
			||||||
 | 
					            m_rawPacket[i+3] = encryptedPacketID[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (DBG_LEVEL >= DBG_DEBUG) {
 | 
				
			||||||
 | 
					            qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':');
 | 
				
			||||||
 | 
					            qCritical() << DBG_HEADER << m_rawPacket.toHex(':');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray const &MessageHelper::mask(QByteArray &messageChunk) {
 | 
				
			||||||
 | 
					    QByteArray ba;
 | 
				
			||||||
 | 
					    for (int i = 0; i < messageChunk.size(); ++i) {
 | 
				
			||||||
 | 
					        char const c = messageChunk[i];
 | 
				
			||||||
 | 
					        switch(c) {
 | 
				
			||||||
 | 
					        case STX:   __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case ETX1:  __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case ETX2:  __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case EOT:   __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case ENQ:   __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case ACK1:  __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case ACK2:  __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case DLE:   __attribute__((fallthrough));
 | 
				
			||||||
 | 
					        case NAK:
 | 
				
			||||||
 | 
					            ba.push_back(char(DLE));
 | 
				
			||||||
 | 
					            ba.push_back(c + 0x30);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            ba.push_back(c);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    messageChunk = ba;
 | 
				
			||||||
 | 
					    return messageChunk;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QByteArray const &MessageHelper::unMask(QByteArray &messageChunk) {
 | 
				
			||||||
 | 
					    QByteArray ba;
 | 
				
			||||||
 | 
					    for (int i = 0; i < messageChunk.size(); ++i) {
 | 
				
			||||||
 | 
					        char c = messageChunk[i];
 | 
				
			||||||
 | 
					        if (c == (char)0x10) /* DEL */ {
 | 
				
			||||||
 | 
					            if ((i+1) < messageChunk.size()) {
 | 
				
			||||||
 | 
					                c = messageChunk[i+1] - (char)0x30;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ba.push_back(c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    messageChunk = ba;
 | 
				
			||||||
 | 
					    return messageChunk;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										112
									
								
								main/MessageHelper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								main/MessageHelper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					#ifndef MESSAGE_HELPER_H_INCLUDED
 | 
				
			||||||
 | 
					#define MESSAGE_HELPER_H_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cinttypes>
 | 
				
			||||||
 | 
					#include <QByteArray>
 | 
				
			||||||
 | 
					#include <QByteArrayList>
 | 
				
			||||||
 | 
					#include <QString>
 | 
				
			||||||
 | 
					#include <QDateTime>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MessageHelper {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    enum PacketType : std::uint8_t {
 | 
				
			||||||
 | 
					        POS_ECR = 0,
 | 
				
			||||||
 | 
					        // POS_EXT = 1,
 | 
				
			||||||
 | 
					        MESSAGE_RECEIVED_POSITIVE_ACK = 0x0A,
 | 
				
			||||||
 | 
					        MESSAGE_RECEIVED_NEGATIVE_ACK = 0x0F
 | 
				
			||||||
 | 
					        // POS_HOST_FORMAT_1_ENCRYPTED   = 0x11,
 | 
				
			||||||
 | 
					        // POS_HOST_FORMAT_1_UNENCRYPTED = 0x21
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum AsyncPosCommand : std::uint8_t {
 | 
				
			||||||
 | 
					        LOGIN  = 0,
 | 
				
			||||||
 | 
					        LOGOUT = 1,
 | 
				
			||||||
 | 
					        AUTHORIZE = 2,
 | 
				
			||||||
 | 
					        CLOSE_DOCUMENT = 3
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit MessageHelper(QString const &posID = "T-TPS-SELF2002in",
 | 
				
			||||||
 | 
					                           QString const &apak = "8AC304380E0E476BA2558B75DB9E2516");
 | 
				
			||||||
 | 
					    explicit MessageHelper(QByteArray const &posID, QString const &apak);
 | 
				
			||||||
 | 
					    ~MessageHelper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void createRawPacket(PacketType PacketType,
 | 
				
			||||||
 | 
					                         QByteArray const &encryptedPacketId,
 | 
				
			||||||
 | 
					                         QByteArray const &message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool insertEncryptedPacketID(QByteArray const &encryptedPacketID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArrayList createLoginMessageChunksToSend(char etx);
 | 
				
			||||||
 | 
					    QByteArrayList createLogoutMessageChunksToSend(char etx);
 | 
				
			||||||
 | 
					    QByteArrayList createAuthorizeMessageChunksToSend(char etx);
 | 
				
			||||||
 | 
					    QByteArrayList createCloseDocumentMessageChunksToSend(char etx);
 | 
				
			||||||
 | 
					    QByteArrayList const &createMessageChunksToSend(AsyncPosCommand cmd, char etx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray m_posID;
 | 
				
			||||||
 | 
					    QByteArray m_apak;
 | 
				
			||||||
 | 
					    uint8_t m_posIDLength;
 | 
				
			||||||
 | 
					    QByteArray m_messageHeaderPrefix;
 | 
				
			||||||
 | 
					    QByteArray m_rawPacket; // without leading STX and trailing [ETX(1/2), LRC]
 | 
				
			||||||
 | 
					    QByteArray m_loginMessage;
 | 
				
			||||||
 | 
					    QByteArray m_logoutMessage;
 | 
				
			||||||
 | 
					    QByteArray m_authorizeMessage;
 | 
				
			||||||
 | 
					    QByteArray m_cancelAuthorizeMessage;
 | 
				
			||||||
 | 
					    QByteArray m_pingMessage;
 | 
				
			||||||
 | 
					    QByteArray m_printResultMessage;
 | 
				
			||||||
 | 
					    QByteArray m_closeDocumentMessage;
 | 
				
			||||||
 | 
					    QByteArray m_uniqueTransactionID;
 | 
				
			||||||
 | 
					    QString m_price;
 | 
				
			||||||
 | 
					    QByteArrayList m_messageChunkList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool setMessageHeaderPacketType(PacketType packetType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID);
 | 
				
			||||||
 | 
					    void createLoginMessage();
 | 
				
			||||||
 | 
					    void createLogoutMessage();
 | 
				
			||||||
 | 
					    void createAuthorizeMessage();
 | 
				
			||||||
 | 
					    void createCancelAuthorizeMessage();
 | 
				
			||||||
 | 
					    void createPingMessage();
 | 
				
			||||||
 | 
					    void createCloseDocumentMessage(bool storno = false);
 | 
				
			||||||
 | 
					    void createPrintResultMessage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void handleCommand(AsyncPosCommand command, char status);
 | 
				
			||||||
 | 
					    //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void handleMessage(char const *pData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray const &generateUniqueTransactionID(QString const &machineNr, QString const &customerNumer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static QByteArray const &mask(QByteArray &messageChunk);
 | 
				
			||||||
 | 
					    static QByteArray const &unMask(QByteArray &messageChunk);
 | 
				
			||||||
 | 
					    static uint32_t secsSinceJan2017(QDateTime const &dt = QDateTime::currentDateTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AsynchBillData {
 | 
				
			||||||
 | 
					        char time[20];
 | 
				
			||||||
 | 
					        char id[37];
 | 
				
			||||||
 | 
					        char printId[129];
 | 
				
			||||||
 | 
					        char docNr[33];
 | 
				
			||||||
 | 
					        //unsigned char amount[10];
 | 
				
			||||||
 | 
					        //unsigned char token[25];
 | 
				
			||||||
 | 
					        //unsigned char result[8];
 | 
				
			||||||
 | 
					        //unsigned char authCode[7];
 | 
				
			||||||
 | 
					        //unsigned char rrn[13];
 | 
				
			||||||
 | 
					        //unsigned char stan[7];
 | 
				
			||||||
 | 
					        //unsigned char cardtype[33];
 | 
				
			||||||
 | 
					        char errCode[17];
 | 
				
			||||||
 | 
					        //unsigned char receiptData[IUC_ASYNCHPOS_RECEIPT_LENGTH];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AuthorizationResult {
 | 
				
			||||||
 | 
					        QString m_id;       // max. 36
 | 
				
			||||||
 | 
					        QString m_docNr;    // max. 32
 | 
				
			||||||
 | 
					        QString m_result;   // "OK" or "ERROR"
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static AsynchBillData m_asyncBillData;
 | 
				
			||||||
 | 
					    static AuthorizationResult m_authorizationResult;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // MESSAGE_HELPER_H_INCLUDED
 | 
				
			||||||
							
								
								
									
										625
									
								
								main/aes128.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										625
									
								
								main/aes128.cpp
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,625 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * aes128.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Created: 27.11.2017 13:33:29
 | 
				
			||||||
 | 
					 *  Author: Matthias
 | 
				
			||||||
 | 
					 */ 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <aes128.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* the expanded keySize */
 | 
				
			||||||
 | 
					#define EXPANDED_KEY_SIZE 176
 | 
				
			||||||
 | 
					//int expandedKeySize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* the expanded key */
 | 
				
			||||||
 | 
					//unsigned char expandedKey[EXPANDED_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* the cipher key */
 | 
				
			||||||
 | 
					//unsigned char key[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* the cipher key size */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum keySize{
 | 
				
			||||||
 | 
						SIZE_16 = 16,
 | 
				
			||||||
 | 
						SIZE_24 = 24,
 | 
				
			||||||
 | 
						SIZE_32 = 32
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//enum keySize size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char sbox[256] =   {
 | 
				
			||||||
 | 
						//0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
 | 
				
			||||||
 | 
						0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
 | 
				
			||||||
 | 
						0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
 | 
				
			||||||
 | 
						0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
 | 
				
			||||||
 | 
						0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
 | 
				
			||||||
 | 
						0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
 | 
				
			||||||
 | 
						0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
 | 
				
			||||||
 | 
						0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
 | 
				
			||||||
 | 
						0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
 | 
				
			||||||
 | 
						0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
 | 
				
			||||||
 | 
						0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
 | 
				
			||||||
 | 
						0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
 | 
				
			||||||
 | 
						0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
 | 
				
			||||||
 | 
						0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
 | 
				
			||||||
 | 
						0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
 | 
				
			||||||
 | 
						0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
 | 
				
			||||||
 | 
					0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char rsbox[256] =
 | 
				
			||||||
 | 
					{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
 | 
				
			||||||
 | 
						, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
 | 
				
			||||||
 | 
						, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
 | 
				
			||||||
 | 
						, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
 | 
				
			||||||
 | 
						, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
 | 
				
			||||||
 | 
						, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
 | 
				
			||||||
 | 
						, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
 | 
				
			||||||
 | 
						, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
 | 
				
			||||||
 | 
						, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
 | 
				
			||||||
 | 
						, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
 | 
				
			||||||
 | 
						, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
 | 
				
			||||||
 | 
						, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
 | 
				
			||||||
 | 
						, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
 | 
				
			||||||
 | 
						, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
 | 
				
			||||||
 | 
						, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
 | 
				
			||||||
 | 
					, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char Rcon[256] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
 | 
				
			||||||
 | 
						0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
 | 
				
			||||||
 | 
						0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
 | 
				
			||||||
 | 
						0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
 | 
				
			||||||
 | 
						0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab,
 | 
				
			||||||
 | 
						0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
 | 
				
			||||||
 | 
						0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25,
 | 
				
			||||||
 | 
						0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01,
 | 
				
			||||||
 | 
						0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
 | 
				
			||||||
 | 
						0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa,
 | 
				
			||||||
 | 
						0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
 | 
				
			||||||
 | 
						0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
 | 
				
			||||||
 | 
						0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
 | 
				
			||||||
 | 
						0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
 | 
				
			||||||
 | 
						0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
 | 
				
			||||||
 | 
						0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
 | 
				
			||||||
 | 
						0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f,
 | 
				
			||||||
 | 
						0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
 | 
				
			||||||
 | 
						0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33,
 | 
				
			||||||
 | 
					0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_init() {
 | 
				
			||||||
 | 
						//UINT uitemp = 0;
 | 
				
			||||||
 | 
						/* the expanded keySize */
 | 
				
			||||||
 | 
						//expandedKeySize = EXPANDED_KEY_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the cipher key */
 | 
				
			||||||
 | 
						//for (uitemp = 0; uitemp < 16; ++uitemp)
 | 
				
			||||||
 | 
							//key[uitemp] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the cipher key size */
 | 
				
			||||||
 | 
						//size = SIZE_16;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char getSBoxValue(unsigned char num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sbox[num];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char getSBoxInvert(unsigned char num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rsbox[num];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Key generation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Rijndael's key schedule rotate operation
 | 
				
			||||||
 | 
					 * rotate the word eight bits to the left
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * rotate(1d2c3a4f) = 2c3a4f1d
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * word is an char array of size 4 (32 bit)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void rotate(unsigned char *word)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned char c;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c = word[0];
 | 
				
			||||||
 | 
					    for (i = 0; i < 3; i++)
 | 
				
			||||||
 | 
					        word[i] = word[i+1];
 | 
				
			||||||
 | 
					    word[3] = c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char getRconValue(unsigned char num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return Rcon[num];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void core(unsigned char *word, int iteration)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* rotate the 32-bit word 8 bits to the left */
 | 
				
			||||||
 | 
						rotate(word);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* apply S-Box substitution on all 4 parts of the 32-bit word */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							word[i] = getSBoxValue(word[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* XOR the output of the rcon operation with i to the first part (leftmost) only */
 | 
				
			||||||
 | 
						word[0] = word[0]^getRconValue(((unsigned char) iteration));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Rijndael's key expansion
 | 
				
			||||||
 | 
					 * expands an 128,192,256 key into an 176,208,240 bytes key
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * expandedKey is a pointer to an char array of large enough size
 | 
				
			||||||
 | 
					 * key is a pointer to a non-expanded key
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void expandKey(unsigned char *expandedKey,
 | 
				
			||||||
 | 
					               unsigned char *key,
 | 
				
			||||||
 | 
					               enum keySize size,
 | 
				
			||||||
 | 
					               /*size_t*/ unsigned int expandedKeySize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* current expanded keySize, in bytes */
 | 
				
			||||||
 | 
					    int currentSize = 0;
 | 
				
			||||||
 | 
					    int rconIteration = 1;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    unsigned char t[4] = {0,0,0,0};   // temporary 4-byte variable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* set the 16,24,32 bytes of the expanded key to the input key */
 | 
				
			||||||
 | 
					    for (i = 0; i < size; i++)
 | 
				
			||||||
 | 
					        expandedKey[i] = key[i];
 | 
				
			||||||
 | 
					    currentSize += size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (currentSize < expandedKeySize)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* assign the previous 4 bytes to the temporary value t */
 | 
				
			||||||
 | 
					        for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            t[i] = expandedKey[(currentSize - 4) + i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* every 16,24,32 bytes we apply the core schedule to t
 | 
				
			||||||
 | 
					         * and increment rconIteration afterwards
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if(currentSize % size == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            core(t, rconIteration++);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* For 256-bit keys, we add an extra sbox to the calculation */
 | 
				
			||||||
 | 
					        if(size == SIZE_32 && ((currentSize % size) == 16)) {
 | 
				
			||||||
 | 
					            for(i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					                t[i] = getSBoxValue(t[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* We XOR t with the four-byte block 16,24,32 bytes before the new expanded key.
 | 
				
			||||||
 | 
					         * This becomes the next four bytes in the expanded key.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        for(i = 0; i < 4; i++) {
 | 
				
			||||||
 | 
					            expandedKey[currentSize] = expandedKey[currentSize - size] ^ t[i];
 | 
				
			||||||
 | 
					            currentSize++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Encrypt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void subBytes(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    /* substitute all the values from the state with the value in the SBox
 | 
				
			||||||
 | 
					     * using the state value as index for the SBox
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; i++)
 | 
				
			||||||
 | 
					        state[i] = getSBoxValue(state[i]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void shiftRow(unsigned char *state, unsigned char nbr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
						unsigned char tmp;
 | 
				
			||||||
 | 
						/* each iteration shifts the row to the left by 1 */
 | 
				
			||||||
 | 
						for (i = 0; i < nbr; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							tmp = state[0];
 | 
				
			||||||
 | 
							for (j = 0; j < 3; j++)
 | 
				
			||||||
 | 
							state[j] = state[j+1];
 | 
				
			||||||
 | 
							state[3] = tmp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void shiftRows(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						/* iterate over the 4 rows and call shiftRow() with that row */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						shiftRow(state+i*4, i);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void addRoundKey(unsigned char *state, unsigned char *roundKey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < 16; i++)
 | 
				
			||||||
 | 
						state[i] = state[i] ^ roundKey[i] ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned char galois_multiplication(unsigned char a, unsigned char b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char p = 0;
 | 
				
			||||||
 | 
						unsigned char counter;
 | 
				
			||||||
 | 
						unsigned char hi_bit_set;
 | 
				
			||||||
 | 
						for(counter = 0; counter < 8; counter++) {
 | 
				
			||||||
 | 
							if((b & 1) == 1)
 | 
				
			||||||
 | 
								p ^= a;
 | 
				
			||||||
 | 
							hi_bit_set = (a & 0x80);
 | 
				
			||||||
 | 
							a <<= 1;
 | 
				
			||||||
 | 
							if(hi_bit_set == 0x80)
 | 
				
			||||||
 | 
								a ^= 0x1b;
 | 
				
			||||||
 | 
							b >>= 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixColumn(unsigned char *column)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char cpy[4];
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for(i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							cpy[i] = column[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						column[0] = galois_multiplication(cpy[0],2) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						column[1] = galois_multiplication(cpy[1],2) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						column[2] = galois_multiplication(cpy[2],2) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						column[3] = galois_multiplication(cpy[3],2) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],1) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixColumns(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
						unsigned char column[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* iterate over the 4 columns */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* construct one column by iterating over the 4 rows */
 | 
				
			||||||
 | 
							for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								column[j] = state[(j*4)+i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* apply the mixColumn on one column */
 | 
				
			||||||
 | 
							mixColumn(column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* put the values back into the state */
 | 
				
			||||||
 | 
							for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								state[(j*4)+i] = column[j];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_round(unsigned char *state, unsigned char *roundKey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						subBytes(state);
 | 
				
			||||||
 | 
						shiftRows(state);
 | 
				
			||||||
 | 
						mixColumns(state);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void createRoundKey(unsigned char *expandedKey, unsigned char *roundKey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i,j;
 | 
				
			||||||
 | 
						/* iterate over the columns */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* iterate over the rows */
 | 
				
			||||||
 | 
							for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
							roundKey[(i+(j*4))] = expandedKey[(i*4)+j];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_main(unsigned char *state, unsigned char *expandedKey, int nbrRounds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char roundKey[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						createRoundKey(expandedKey, roundKey);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 1; i < nbrRounds; i++) {
 | 
				
			||||||
 | 
							createRoundKey(expandedKey + 16*i, roundKey);
 | 
				
			||||||
 | 
							aes_round(state, roundKey);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						createRoundKey(expandedKey + 16*nbrRounds, roundKey);
 | 
				
			||||||
 | 
						subBytes(state);
 | 
				
			||||||
 | 
						shiftRows(state);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char aes_encrypt(unsigned char *input,
 | 
				
			||||||
 | 
					                 unsigned char *output,
 | 
				
			||||||
 | 
					                 unsigned char *key
 | 
				
			||||||
 | 
					                 /*, enum keySize size*/)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum keySize size = SIZE_16;
 | 
				
			||||||
 | 
					    /* the expanded keySize */
 | 
				
			||||||
 | 
					    int expandedKeySize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the number of rounds */
 | 
				
			||||||
 | 
					    int nbrRounds = 10;	//NOTE: modded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the expanded key */
 | 
				
			||||||
 | 
					    //NOTE: modded: unsigned char *expandedKey = 0x00;
 | 
				
			||||||
 | 
						//unsigned char expandedKey[(16*(nbrRounds+1))];
 | 
				
			||||||
 | 
						unsigned char expandedKey[176];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the 128 bit block to encode */
 | 
				
			||||||
 | 
					    unsigned char block[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int i,j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* set the number of rounds */
 | 
				
			||||||
 | 
					    /*switch (size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case SIZE_16:
 | 
				
			||||||
 | 
					            nbrRounds = 10;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case SIZE_24:
 | 
				
			||||||
 | 
					            nbrRounds = 12;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case SIZE_32:
 | 
				
			||||||
 | 
					            nbrRounds = 14;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return 1; //UNKNOWN_KEYSIZE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }*/ //NOTE: modded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expandedKeySize = (16*(nbrRounds+1));
 | 
				
			||||||
 | 
					    /*if ((expandedKey = malloc(expandedKeySize * sizeof(char))) == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return MEMORY_ALLOCATION_PROBLEM;
 | 
				
			||||||
 | 
					    }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Set the block values, for the block:
 | 
				
			||||||
 | 
					     * a0,0 a0,1 a0,2 a0,3
 | 
				
			||||||
 | 
					     * a1,0 a1,1 a1,2 a1,3
 | 
				
			||||||
 | 
					     * a2,0 a2,1 a2,2 a2,3
 | 
				
			||||||
 | 
					     * a3,0 a3,1 a3,2 a3,3
 | 
				
			||||||
 | 
					     * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* iterate over the columns */
 | 
				
			||||||
 | 
					    for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* iterate over the rows */
 | 
				
			||||||
 | 
					        for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
					            block[(i+(j*4))] = input[(i*4)+j];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* expand the key into an 176, 208, 240 bytes key */
 | 
				
			||||||
 | 
					    expandKey(expandedKey, key, size, expandedKeySize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* encrypt the block using the expandedKey */
 | 
				
			||||||
 | 
					    aes_main(block, expandedKey, nbrRounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* unmap the block again into the output */
 | 
				
			||||||
 | 
					    for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* iterate over the rows */
 | 
				
			||||||
 | 
					        for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
					            output[(i*4)+j] = block[(i+(j*4))];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Decrypt
 | 
				
			||||||
 | 
					void invSubBytes(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    /* substitute all the values from the state with the value in the SBox
 | 
				
			||||||
 | 
					     * using the state value as index for the SBox
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; i++)
 | 
				
			||||||
 | 
					        state[i] = getSBoxInvert(state[i]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void invShiftRow(unsigned char *state, unsigned char nbr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
						unsigned char tmp;
 | 
				
			||||||
 | 
						/* each iteration shifts the row to the right by 1 */
 | 
				
			||||||
 | 
						for (i = 0; i < nbr; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							tmp = state[3];
 | 
				
			||||||
 | 
							for (j = 3; j > 0; j--)
 | 
				
			||||||
 | 
							state[j] = state[j-1];
 | 
				
			||||||
 | 
							state[0] = tmp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void invShiftRows(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    /* iterate over the 4 rows and call invShiftRow() with that row */
 | 
				
			||||||
 | 
					    for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					        invShiftRow(state+i*4, i);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void invMixColumn(unsigned char *column)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char cpy[4];
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for(i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							cpy[i] = column[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						column[0] = galois_multiplication(cpy[0],14) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],9) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],13) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],11);
 | 
				
			||||||
 | 
						column[1] = galois_multiplication(cpy[1],14) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],9) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],13) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],11);
 | 
				
			||||||
 | 
						column[2] = galois_multiplication(cpy[2],14) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],9) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],13) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[3],11);
 | 
				
			||||||
 | 
						column[3] = galois_multiplication(cpy[3],14) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[2],9) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[1],13) ^
 | 
				
			||||||
 | 
						galois_multiplication(cpy[0],11);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void invMixColumns(unsigned char *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
						unsigned char column[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* iterate over the 4 columns */
 | 
				
			||||||
 | 
						for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* construct one column by iterating over the 4 rows */
 | 
				
			||||||
 | 
							for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								column[j] = state[(j*4)+i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* apply the invMixColumn on one column */
 | 
				
			||||||
 | 
							invMixColumn(column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* put the values back into the state */
 | 
				
			||||||
 | 
							for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								state[(j*4)+i] = column[j];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_invRound(unsigned char *state, unsigned char *roundKey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						invShiftRows(state);
 | 
				
			||||||
 | 
						invSubBytes(state);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
						invMixColumns(state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_invMain(unsigned char *state, unsigned char *expandedKey, int nbrRounds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char roundKey[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						createRoundKey(expandedKey + 16*nbrRounds, roundKey);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = nbrRounds-1; i > 0; i--) {
 | 
				
			||||||
 | 
							createRoundKey(expandedKey + 16*i, roundKey);
 | 
				
			||||||
 | 
							aes_invRound(state, roundKey);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						createRoundKey(expandedKey, roundKey);
 | 
				
			||||||
 | 
						invShiftRows(state);
 | 
				
			||||||
 | 
						invSubBytes(state);
 | 
				
			||||||
 | 
						addRoundKey(state, roundKey);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char aes_decrypt(unsigned char *input,
 | 
				
			||||||
 | 
					                 unsigned char *output,
 | 
				
			||||||
 | 
					                 unsigned char *key
 | 
				
			||||||
 | 
					                 /*´, enum keySize size*/)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum keySize size = SIZE_16;
 | 
				
			||||||
 | 
					    /* the expanded keySize */
 | 
				
			||||||
 | 
					    int expandedKeySize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the number of rounds */
 | 
				
			||||||
 | 
					    int nbrRounds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the expanded key */
 | 
				
			||||||
 | 
					    unsigned char *expandedKey = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the 128 bit block to decode */
 | 
				
			||||||
 | 
					    unsigned char block[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int i,j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* set the number of rounds */
 | 
				
			||||||
 | 
					    switch (size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case SIZE_16:
 | 
				
			||||||
 | 
					            nbrRounds = 10;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case SIZE_24:
 | 
				
			||||||
 | 
					            nbrRounds = 12;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case SIZE_32:
 | 
				
			||||||
 | 
					            nbrRounds = 14;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return 1; //UNKNOWN_KEYSIZE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expandedKeySize = (16*(nbrRounds+1));
 | 
				
			||||||
 | 
					    /*if ((expandedKey = malloc(expandedKeySize * sizeof(char))) == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return MEMORY_ALLOCATION_PROBLEM;
 | 
				
			||||||
 | 
					    }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Set the block values, for the block:
 | 
				
			||||||
 | 
					     * a0,0 a0,1 a0,2 a0,3
 | 
				
			||||||
 | 
					     * a1,0 a1,1 a1,2 a1,3
 | 
				
			||||||
 | 
					     * a2,0 a2,1 a2,2 a2,3
 | 
				
			||||||
 | 
					     * a3,0 a3,1 a3,2 a3,3
 | 
				
			||||||
 | 
					     * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* iterate over the columns */
 | 
				
			||||||
 | 
					    for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* iterate over the rows */
 | 
				
			||||||
 | 
					        for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
					            block[(i+(j*4))] = input[(i*4)+j];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* expand the key into an 176, 208, 240 bytes key */
 | 
				
			||||||
 | 
					    expandKey(expandedKey, key, size, expandedKeySize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* decrypt the block using the expandedKey */
 | 
				
			||||||
 | 
					    aes_invMain(block, expandedKey, nbrRounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* unmap the block again into the output */
 | 
				
			||||||
 | 
					    for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* iterate over the rows */
 | 
				
			||||||
 | 
					        for (j = 0; j < 4; j++)
 | 
				
			||||||
 | 
					            output[(i*4)+j] = block[(i+(j*4))];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								main/aes128.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								main/aes128.h
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#ifndef AES128_H
 | 
				
			||||||
 | 
					#define AES128_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void aes_init();
 | 
				
			||||||
 | 
					char aes_encrypt(unsigned char *input,unsigned char *output,unsigned char *key);
 | 
				
			||||||
 | 
					char aes_decrypt(unsigned char *input,unsigned char *output,unsigned char *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										2131
									
								
								main/cc_iuc_asynchpos.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2131
									
								
								main/cc_iuc_asynchpos.cpp
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1630
									
								
								main/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										1630
									
								
								main/main.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -27,8 +27,7 @@ CONFIG(debug, debug|release) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SOURCES += main.cpp
 | 
					SOURCES += main.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# HEADERS +=
 | 
				
			||||||
# HEADERS += \
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# OTHER_FILES += \
 | 
					# OTHER_FILES += \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										96
									
								
								main/terminal_utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								main/terminal_utils.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					#include "terminal_utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <endian.h>
 | 
				
			||||||
 | 
					#include <QString>
 | 
				
			||||||
 | 
					#include <QByteArray>
 | 
				
			||||||
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace TU {
 | 
				
			||||||
 | 
					    char const *terminalStatus(uint8_t status) {
 | 
				
			||||||
 | 
					        switch (status) {
 | 
				
			||||||
 | 
					        case TERMINAL_CB2_KEYS_NOT_PRESENT:
 | 
				
			||||||
 | 
					            return "CB2 KEYS NOT PRESENT";
 | 
				
			||||||
 | 
					        case TERMINAL_NO_BANKING_PARAMETERS_PRESENT:
 | 
				
			||||||
 | 
					            return "NO BANKING PARAMETERS PRESENT";
 | 
				
			||||||
 | 
					        case TERMINAL_IS_BLOCKED:
 | 
				
			||||||
 | 
					            return "TERMINAL IS BLOCKED";
 | 
				
			||||||
 | 
					        case TERMINAL_NOT_OPERATIVE:
 | 
				
			||||||
 | 
					            return "TERMINAL NOT OPERATIVE";
 | 
				
			||||||
 | 
					        case TERMINAL_IS_READY_AND_ACTIVE:
 | 
				
			||||||
 | 
					            return "TERMINAL IS READY AND ACTIVE";
 | 
				
			||||||
 | 
					        case TERMINAL_IS_READY_AND_NOT_ACTIVE:
 | 
				
			||||||
 | 
					            return "TERMINAL IS READY AND *NOT* ACTIVE";
 | 
				
			||||||
 | 
					        case TERMINAL_LOG_FULL:
 | 
				
			||||||
 | 
					            return "TERMINAL LOG IS FULL";
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return "";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QByteArray int2Hex(int i) {
 | 
				
			||||||
 | 
					        return QByteArray::fromHex(
 | 
				
			||||||
 | 
					                QString().setNum(i, 16).toLocal8Bit().constData()).toHex();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint16_t getNextTransactionId() {
 | 
				
			||||||
 | 
					        static std::atomic<int> i{0};
 | 
				
			||||||
 | 
					        int j = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while ((j = (++i % 100)) == 0); // 1 <= j <= 99
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return htobe16(((j / 10) + 0x30) << 8) | ((j % 10) + 0x30);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t crc32(uint32_t crc, unsigned char* pData, size_t len) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qCritical() << "updateCRC" << QByteArray((char *)pData, len).toHex();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int i = 0;
 | 
				
			||||||
 | 
					        int j = 0;
 | 
				
			||||||
 | 
					        unsigned char ucCarry = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        crc = ~crc;
 | 
				
			||||||
 | 
					        while (len > 0) {
 | 
				
			||||||
 | 
					            uint32_t const c = pData[i];
 | 
				
			||||||
 | 
					            crc ^= c;
 | 
				
			||||||
 | 
					            ++i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (j = 0; j < 8; ++j) {
 | 
				
			||||||
 | 
					                ucCarry = crc & 1;
 | 
				
			||||||
 | 
					                crc >>= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (ucCarry) {
 | 
				
			||||||
 | 
					                    crc ^= 0xedb88320;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            --len;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ~crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t crc32(QByteArray const &ba) {
 | 
				
			||||||
 | 
					        uint32_t crc = 0;
 | 
				
			||||||
 | 
					        return crc32(crc, (uint8_t *)ba.data(), ba.size());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char lrc(QByteArray const &ba) {
 | 
				
			||||||
 | 
					        char crc = 0;
 | 
				
			||||||
 | 
					        for (int i = 0; i < ba.size(); ++i) {
 | 
				
			||||||
 | 
					            crc ^= ba[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return crc;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool isBigEndian() {
 | 
				
			||||||
 | 
					        union {
 | 
				
			||||||
 | 
					            uint32_t i;
 | 
				
			||||||
 | 
					            char c[4];
 | 
				
			||||||
 | 
					        } bint = {0x01020304};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return bint.c[0] == 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								main/terminal_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								main/terminal_utils.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					#ifndef TERMINAL_UTILS_H_INCLUDED
 | 
				
			||||||
 | 
					#define TERMINAL_UTILS_H_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cinttypes>
 | 
				
			||||||
 | 
					#include <QByteArray>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace TU {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum STATUS : uint8_t {
 | 
				
			||||||
 | 
					        TERMINAL_CB2_KEYS_NOT_PRESENT = 0x30,
 | 
				
			||||||
 | 
					        TERMINAL_NO_BANKING_PARAMETERS_PRESENT = 0x31,
 | 
				
			||||||
 | 
					        TERMINAL_IS_BLOCKED = 0x32,
 | 
				
			||||||
 | 
					        TERMINAL_NOT_OPERATIVE = 0x33,
 | 
				
			||||||
 | 
					        TERMINAL_IS_READY_AND_ACTIVE = 0x34,
 | 
				
			||||||
 | 
					        TERMINAL_IS_READY_AND_NOT_ACTIVE = 0x35,
 | 
				
			||||||
 | 
					        TERMINAL_LOG_FULL = 0x36
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char const *terminalStatus(uint8_t status);
 | 
				
			||||||
 | 
					    QByteArray int2Hex(int i);
 | 
				
			||||||
 | 
					    uint16_t getNextTransactionId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //uint32_t crc32(const char *s, size_t n);
 | 
				
			||||||
 | 
					    //uint32_t crc32(QByteArray const &ba);
 | 
				
			||||||
 | 
					    uint32_t crc32(QByteArray const &ba);
 | 
				
			||||||
 | 
					    uint32_t crc32(uint32_t crc, unsigned char* pData, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char lrc(QByteArray const &ba);
 | 
				
			||||||
 | 
					    bool isBigEndian();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif // TERMINAL_UTILS_H_INCLUDED
 | 
				
			||||||
		Reference in New Issue
	
	Block a user