Compare commits
	
		
			118 Commits
		
	
	
		
			fix-kirchd
			...
			kleipeda
		
	
	| 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 | |||
| d07fdd8540 | |||
| 1fab458de3 | |||
| 1ac2ca91c5 | |||
| 1852f552a3 | |||
| e2c02420f0 | |||
| 1240abbbec | |||
| e20eb93abf | |||
| b0e7bd91b4 | |||
| 0cd4424434 | |||
| 1991853b66 | |||
| b31fcc5f4f | |||
| dbe649d0e4 | |||
| dfd74a455a | |||
| 10828e0708 | |||
| 2dbcc7018c | |||
| 18ed85430d | |||
| b70094abb5 | |||
| aa15d1c126 | |||
| cd159f2bbd | |||
| 475487c2ce | |||
| 8ff5b8e2b5 | |||
| b0c4ad0e2e | |||
| 7e3347b043 | |||
| 4e7fa83507 | |||
| ac76f194e1 | |||
| fe485b7b39 | |||
| e210224340 | |||
| afa62183fd | |||
| f241a87dc1 | |||
| 9b1cc49d34 | |||
| 449e618417 | |||
| aba38d2614 | |||
| 57d6b85f52 | |||
| 4f9c0422fc | |||
| a5b95d71b8 | |||
| fcbc8dcdc3 | |||
| ed99bae725 | |||
| 627d14204d | |||
| 
						
						
							
						
						d8a4c4eaa7
	
				 | 
					
					
						|||
| 4f45db4fde | |||
| a744a1ebb3 | |||
| df16bd7f9c | |||
| b751ba339e | |||
| 
						
						
							
						
						588a88455b
	
				 | 
					
					
						|||
| 
						
						
							
						
						92bfdced6a
	
				 | 
					
					
						|||
| 8bbec596c9 | |||
| 87b14ee3f8 | |||
| 3ad2c77467 | |||
| 493d94aaa1 | |||
| 7831329b11 | |||
| abbbd06f93 | |||
| ac6e45a913 | 
@@ -42,18 +42,34 @@ struct CALCULATE_LIBRARY_API price_t {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
        SUCCESS,
 | 
			
		||||
        ERROR_PARSING_ZONE_NR,
 | 
			
		||||
        ERROR_LOADING_TARIFF,
 | 
			
		||||
        ERROR_PARSING_TARIFF,
 | 
			
		||||
        NEGATIVE_PARING_TIME,
 | 
			
		||||
        NEGATIVE_PARKING_TIME,
 | 
			
		||||
        INVALID_START_DATE,
 | 
			
		||||
        WRONG_PARAM_VALUES,
 | 
			
		||||
        WRONG_ISO_TIME_FORMAT,
 | 
			
		||||
        ABOVE_MAX_PARKING_TIME,
 | 
			
		||||
        BELOW_MIN_PARKING_TIME,
 | 
			
		||||
        BELOW_MIN_PARKING_PRICE,
 | 
			
		||||
        ABOVE_MAX_PARKING_PRICE,
 | 
			
		||||
        OVERPAID,
 | 
			
		||||
        OUTSIDE_ALLOWED_PARKING_TIME
 | 
			
		||||
    };
 | 
			
		||||
@@ -84,53 +100,157 @@ struct CALCULATE_LIBRARY_API CalcState {
 | 
			
		||||
        return (m_status == State::SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString toString() {
 | 
			
		||||
        QString s;
 | 
			
		||||
        switch (m_status) {
 | 
			
		||||
        case State::SUCCESS:
 | 
			
		||||
            s = CalcState::SUCCESS;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_ZONE_NR:
 | 
			
		||||
            s = CalcState::ERROR_PARSING_ZONE_NR;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_LOADING_TARIFF:
 | 
			
		||||
            s = CalcState::ERROR_LOADING_TARIFF;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_TARIFF:
 | 
			
		||||
            s = CalcState::ERROR_PARSING_TARIFF;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::NEGATIVE_PARKING_TIME:
 | 
			
		||||
            s = CalcState::NEGATIVE_PARKING_TIME;
 | 
			
		||||
           break;
 | 
			
		||||
        case State::ABOVE_MAX_PARKING_TIME:
 | 
			
		||||
            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_PARAM_VALUES:
 | 
			
		||||
            s = CalcState::WRONG_PARAM_VALUES;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_TIME:
 | 
			
		||||
            s = CalcState::BELOW_MIN_PARKING_TIME;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_PRICE:
 | 
			
		||||
            s = CalcState::BELOW_MIN_PARKING_PRICE;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::OVERPAID:
 | 
			
		||||
            s = CalcState::OVERPAID;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::INVALID_START_DATE:
 | 
			
		||||
            s = CalcState::INVALID_START_DATE;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_ISO_TIME_FORMAT:
 | 
			
		||||
            s = CalcState::WRONG_ISO_TIME_FORMAT;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit operator QString () const noexcept {
 | 
			
		||||
        QString s;
 | 
			
		||||
        switch (m_status) {
 | 
			
		||||
        case State::SUCCESS:
 | 
			
		||||
            s = "SUCCESS";
 | 
			
		||||
            s = CalcState::SUCCESS;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_ZONE_NR:
 | 
			
		||||
            s = "ERROR_PARSING_ZONE_NR";
 | 
			
		||||
            s = CalcState::ERROR_PARSING_ZONE_NR;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_LOADING_TARIFF:
 | 
			
		||||
            s = "ERROR_LOADING_TARIFF";
 | 
			
		||||
            s = CalcState::ERROR_LOADING_TARIFF;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_TARIFF:
 | 
			
		||||
            s = "ERROR_PARSING_TARIFF";
 | 
			
		||||
            s = CalcState::ERROR_PARSING_TARIFF;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::NEGATIVE_PARING_TIME:
 | 
			
		||||
            s = "NEGATIVE_PARKING_TIME";
 | 
			
		||||
        case State::NEGATIVE_PARKING_TIME:
 | 
			
		||||
            s = CalcState::NEGATIVE_PARKING_TIME;
 | 
			
		||||
           break;
 | 
			
		||||
        case State::ABOVE_MAX_PARKING_TIME:
 | 
			
		||||
            s = "ABOVE_MAX_PARKING_TIME";
 | 
			
		||||
            s = CalcState::ABOVE_MAX_PARKING_TIME;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_PARAM_VALUES:
 | 
			
		||||
            s = "WRONG_PARAM_VALUES";
 | 
			
		||||
            s = CalcState::WRONG_PARAM_VALUES;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_TIME:
 | 
			
		||||
            s = "BELOW_MIN_PARKING_TIME";
 | 
			
		||||
            s = CalcState::BELOW_MIN_PARKING_TIME;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_PRICE:
 | 
			
		||||
            s = "BELOW_MIN_PARKING_PRICE";
 | 
			
		||||
            s = CalcState::BELOW_MIN_PARKING_PRICE;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::OVERPAID:
 | 
			
		||||
            s = "OVERPAID";
 | 
			
		||||
            s = CalcState::OVERPAID;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::INVALID_START_DATE:
 | 
			
		||||
            s = "INVALID_START_DATE";
 | 
			
		||||
            s = CalcState::INVALID_START_DATE;
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_ISO_TIME_FORMAT:
 | 
			
		||||
            s = "WRONG_ISO_TIME_FORMAT";
 | 
			
		||||
            s = CalcState::WRONG_ISO_TIME_FORMAT;
 | 
			
		||||
            break;
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CalcState &set(State s) { m_status = s; return *this; }
 | 
			
		||||
    CalcState &setDesc(QString s) { m_desc = s; return *this; }
 | 
			
		||||
    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; }
 | 
			
		||||
    CalcState &setDesc(QString const &s) { m_desc = s; return *this; }
 | 
			
		||||
 | 
			
		||||
    void setAllowedTimeRange(QTime const &from, QTime const &until) {
 | 
			
		||||
        m_allowedTimeRange.setTimeRange(from, until);
 | 
			
		||||
@@ -149,11 +269,29 @@ int CALCULATE_LIBRARY_API get_zone_nr(int zone = -1);
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int currentTimeMinutes, int UpDown);
 | 
			
		||||
 | 
			
		||||
QList<int> CALCULATE_LIBRARY_API get_time_steps(Configuration *cfg);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration const *cfg,
 | 
			
		||||
                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
			
		||||
                                                  int paymentOptionIndex=0);
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration const *cfg,
 | 
			
		||||
                                                  PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
			
		||||
                                                  int paymentOptionIndex=0);
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
			
		||||
                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
			
		||||
                                                   int paymentOptionIndex = 0,
 | 
			
		||||
                                                   QDateTime const &start = QDateTime::currentDateTime());
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
 | 
			
		||||
                                                   PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
			
		||||
                                                   int paymentOptionIndex=0);
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
 | 
			
		||||
                                                PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING,
 | 
			
		||||
                                                QDateTime const &start = QDateTime::currentDateTime(),
 | 
			
		||||
                                                QDateTime *productStart = nullptr,
 | 
			
		||||
                                                QDateTime *productEnd = nullptr);
 | 
			
		||||
 | 
			
		||||
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(       // deprecated
 | 
			
		||||
                                            parking_tariff_t *tariff,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,19 @@
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class Calculator {
 | 
			
		||||
    mutable QList<int> m_timeSteps;
 | 
			
		||||
    mutable QVector<QList<int>> m_timeSteps;
 | 
			
		||||
    mutable QList<int> m_priceSteps;
 | 
			
		||||
 | 
			
		||||
    CalcState isParkingAllowedForWeekDay(Configuration const *cfg,
 | 
			
		||||
                                         QDateTime const &start,
 | 
			
		||||
                                         int netto_parking_time,
 | 
			
		||||
                                         int paymentOptionIndex);
 | 
			
		||||
 | 
			
		||||
    CalcState isParkingAllowedForSpecialDay(Configuration const *cfg,
 | 
			
		||||
                                            QDateTime const &start,
 | 
			
		||||
                                            int netto_parking_time,
 | 
			
		||||
                                            int paymentOptionIndex);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    explicit Calculator() = default;
 | 
			
		||||
 | 
			
		||||
@@ -29,13 +39,28 @@ public:
 | 
			
		||||
        return c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ResetTimeSteps() { m_timeSteps.clear(); }
 | 
			
		||||
    QList<int> timeSteps() const { return m_timeSteps; }
 | 
			
		||||
    void ResetTimeSteps(int paymentOptionIndex) {
 | 
			
		||||
        if (m_timeSteps.size() > 0) {
 | 
			
		||||
            m_timeSteps[paymentOptionIndex].clear();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    QList<int> timeSteps(int paymentOptionIndex=0) const {
 | 
			
		||||
        if (m_timeSteps.size() > 0) {
 | 
			
		||||
            return m_timeSteps[paymentOptionIndex];
 | 
			
		||||
        }
 | 
			
		||||
        return QList<int>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ResetPriceSteps() { m_priceSteps.clear(); }
 | 
			
		||||
    QList<int> priceSteps() const { return m_priceSteps; }
 | 
			
		||||
 | 
			
		||||
    CalcState isParkingAllowed(Configuration const *cfg, QDateTime const &start);
 | 
			
		||||
    CalcState isParkingAllowed(Configuration const *cfg,
 | 
			
		||||
                               QDateTime const &start);
 | 
			
		||||
 | 
			
		||||
    CalcState isParkingAllowed(Configuration const *cfg,
 | 
			
		||||
                               QDateTime const &start,
 | 
			
		||||
                               int netto_parking_time,
 | 
			
		||||
                               int paymentOptionIndex);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets duration in seconds from cost
 | 
			
		||||
@@ -66,8 +91,8 @@ public:
 | 
			
		||||
    // helper function to find time steps for a tariff with PaymentMethod::Steps
 | 
			
		||||
    // (e.g. Schoenau/Koenigsee)
 | 
			
		||||
    //
 | 
			
		||||
    QList<int> GetTimeSteps(Configuration *cfg) const;
 | 
			
		||||
    QList<int> GetSteps(Configuration *cfg) const { return GetTimeSteps(cfg); }
 | 
			
		||||
    QList<int> &GetTimeSteps(Configuration *cfg, int paymentOptionIndex=0) const;
 | 
			
		||||
    QList<int> GetSteps(Configuration *cfg, int paymentOptionIndex=0) const { return GetTimeSteps(cfg, paymentOptionIndex); }
 | 
			
		||||
 | 
			
		||||
    QList<int> GetPriceSteps(Configuration *cfg) const;
 | 
			
		||||
 | 
			
		||||
@@ -87,8 +112,8 @@ public:
 | 
			
		||||
// testing public:
 | 
			
		||||
    // Introduced for PaymentMethod::Steps (e.g. Schoenau)
 | 
			
		||||
    // For tariff of following structure: only steps, no special days, nonstop.
 | 
			
		||||
    uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, quint64 durationMinutes) const;
 | 
			
		||||
    uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, QDateTime const &end) const;
 | 
			
		||||
    uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, quint64 durationMinutes, int paymentOptionIndex=0) const;
 | 
			
		||||
    uint32_t GetCostFromDuration(Configuration *cfg, QDateTime const &start, QDateTime const &end, int paymentOptionIndex=0) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Ticket private_GetCostFromDuration(Configuration const* cfg,
 | 
			
		||||
@@ -104,7 +129,7 @@ private:
 | 
			
		||||
                              int durationMinutes);
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    uint32_t GetPriceForTimeStep(Configuration *cfg, int timeStep) const;
 | 
			
		||||
    uint32_t GetPriceForTimeStep(Configuration *cfg, int timeStep, int paymentOptionIndex=0) const;
 | 
			
		||||
    uint32_t GetPriceForStep(Configuration *cfg, int step) const {
 | 
			
		||||
        return GetPriceForTimeStep(cfg, step);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,12 @@ class Calculator;
 | 
			
		||||
class Configuration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    using SpecialDaysType = std::multimap<int, ATBSpecialDays>;
 | 
			
		||||
    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;
 | 
			
		||||
    ATBCurrency Currency;
 | 
			
		||||
	ATBDuration duration;
 | 
			
		||||
@@ -43,18 +49,18 @@ public:
 | 
			
		||||
	multimap<int, ATBDuration> Duration;
 | 
			
		||||
	multimap<int, ATBPaymentMethod> PaymentMethod;
 | 
			
		||||
	multimap<int, ATBPaymentRate> PaymentRate;
 | 
			
		||||
	multimap<int, ATBSpecialDaysWorktime> SpecialDaysWorktime;
 | 
			
		||||
	multimap<int, ATBSpecialDays> SpecialDays;
 | 
			
		||||
    SpecialDaysWorktimeType SpecialDaysWorktime;
 | 
			
		||||
    SpecialDaysType SpecialDays;
 | 
			
		||||
	multimap<int, ATBWeekDays> WeekDays;
 | 
			
		||||
	multimap<int, ATBPeriodYear> YearPeriod;
 | 
			
		||||
	multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
 | 
			
		||||
	multimap<int, ATBPaymentOption> PaymentOption;
 | 
			
		||||
    ATBPaymentOptionType PaymentOption;
 | 
			
		||||
    multimap<int, ATBDailyTicket> DailyTicket;
 | 
			
		||||
    multimap<int, ATBTimeRange> TimeRange;
 | 
			
		||||
    TimeRangeType TimeRange;
 | 
			
		||||
    multimap<int, ATBTimeStepConfig> TimeStepConfig;
 | 
			
		||||
    multimap<int, ATBTimeBase> TimeBase;
 | 
			
		||||
    multimap<int, ATBCustomer> Customer;
 | 
			
		||||
    multimap<int, ATBTariffProduct> TariffProduct;
 | 
			
		||||
    TariffProductType TariffProduct;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Parse JSON string
 | 
			
		||||
@@ -63,10 +69,18 @@ public:
 | 
			
		||||
	/// <returns>Returns operation status bool (OK | FAIL) </returns>
 | 
			
		||||
	bool ParseJson(Configuration* cfg, const char* json);
 | 
			
		||||
 | 
			
		||||
    ATBPaymentOption &getPaymentOptions();
 | 
			
		||||
    ATBPaymentOption const &getPaymentOptions() const;
 | 
			
		||||
    ATBPaymentOption &getPaymentOptions(int paymentOptionsIndex=0);
 | 
			
		||||
    ATBPaymentOption const &getPaymentOptions(int paymentOptionsIndex=0) const;
 | 
			
		||||
    QVector<ATBPaymentOption> &getAllPaymentOptions();
 | 
			
		||||
    QVector<ATBPaymentOption> const &getAllPaymentOptions() const;
 | 
			
		||||
    int getPaymentOptionIndex(QDateTime const &dt) const;
 | 
			
		||||
    int getPaymentOptionIndexIfSpecialDay(QDateTime const &dt) const;
 | 
			
		||||
    bool isSpecialDay(QDateTime const &dt) const;
 | 
			
		||||
    int specialDayId(QDateTime const &dt) const;
 | 
			
		||||
    ATBSpecialDays specialDay(QDateTime const &dt) const;
 | 
			
		||||
    bool isDayIncluded(uint64_t businessHours, QDateTime const &dt) const;
 | 
			
		||||
    bool isDayIncludedAsSpecialDay(uint64_t businessHours, QDateTime const &dt) const;
 | 
			
		||||
    bool isDayIncludedAsSpecialDay(uint64_t businessHours, int specialDayId) const;
 | 
			
		||||
    std::optional<QVector<ATBPaymentRate>> getPaymentRateForAllKeys() const;
 | 
			
		||||
    std::optional<QVector<ATBPaymentRate>> getPaymentRateForKey(int key) const;
 | 
			
		||||
    std::optional<QVector<ATBDailyTicket>> getDailyTicketsForAllKeys() const;
 | 
			
		||||
@@ -74,6 +88,7 @@ public:
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForAllKeys() const;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(int id) 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<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,11 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#ifndef PAYMENT_OPT_H_INCLUDED
 | 
			
		||||
#define PAYMENT_OPT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <cinttypes>
 | 
			
		||||
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
 | 
			
		||||
class ATBPaymentOption
 | 
			
		||||
{
 | 
			
		||||
@@ -18,7 +24,10 @@ public:
 | 
			
		||||
        pop_min_price = 0;
 | 
			
		||||
        pop_max_price = 0;
 | 
			
		||||
        pop_carry_over = -1;
 | 
			
		||||
        pop_carry_over_target = false;
 | 
			
		||||
        pop_carry_over_time_range_id = -1;
 | 
			
		||||
        pop_carry_over_start_time_range = -1;
 | 
			
		||||
        pop_carry_over_end_time_range = -1;
 | 
			
		||||
        pop_daily_card_price = -1;
 | 
			
		||||
        pop_business_hours = -1;
 | 
			
		||||
        pop_time_step_config = -1;
 | 
			
		||||
@@ -35,8 +44,21 @@ public:
 | 
			
		||||
    double pop_min_price;
 | 
			
		||||
    double pop_max_price;
 | 
			
		||||
    int pop_carry_over;
 | 
			
		||||
    bool pop_carry_over_target;
 | 
			
		||||
    int pop_carry_over_time_range_id;
 | 
			
		||||
    int pop_carry_over_start_time_range;
 | 
			
		||||
    int pop_carry_over_end_time_range;
 | 
			
		||||
    int pop_daily_card_price;
 | 
			
		||||
    int pop_business_hours;
 | 
			
		||||
    uint64_t pop_business_hours;
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,12 @@
 | 
			
		||||
class ATBSpecialDays
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit ATBSpecialDays() = default;
 | 
			
		||||
	int ped_id;
 | 
			
		||||
	std::string ped_label;
 | 
			
		||||
	std::string ped_date_start;
 | 
			
		||||
	std::string ped_date_end;
 | 
			
		||||
	int ped_period_special_day_id;
 | 
			
		||||
    int ped_period_special_day_id;
 | 
			
		||||
    int ped_payment_option_id;
 | 
			
		||||
	int ped_year;
 | 
			
		||||
};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -4,19 +4,89 @@
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Business hours (byte represents payment option id)
 | 
			
		||||
/// </summary>
 | 
			
		||||
enum BusinessHours
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#include <Qt>
 | 
			
		||||
 | 
			
		||||
#define _NO_RESTRICTION_24_7_                   (uint64_t)(0ULL)
 | 
			
		||||
#define _MON_                                   (uint64_t)(1ULL << 8)
 | 
			
		||||
#define _TUE_                                   (uint64_t)(1ULL << 9)
 | 
			
		||||
#define _WED_                                   (uint64_t)(1ULL << 10)
 | 
			
		||||
#define _THU_                                   (uint64_t)(1ULL << 11)
 | 
			
		||||
#define _FRI_                                   (uint64_t)(1ULL << 12)
 | 
			
		||||
#define _SAT_                                   (uint64_t)(1ULL << 13)
 | 
			
		||||
#define _SUN_                                   (uint64_t)(1ULL << 14)
 | 
			
		||||
#define _WEEK_DAYS_                             ((_MON_|_TUE_|_WED_|_THU_|_FRI_))
 | 
			
		||||
#define _WORKING_DAYS_                          ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_))
 | 
			
		||||
#define _ALL_DAYS_                              ((_MON_|_TUE_|_WED_|_THU_|_FRI_|_SAT_|_SUN_))
 | 
			
		||||
#define _OFFICIAL_HOLIDAY_                      (uint64_t)(1ULL << 15)
 | 
			
		||||
#define _ONLY_WEEKEND_                          ((_SAT_|_SUN_))
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
enum BusinessHours : std::uint64_t
 | 
			
		||||
{
 | 
			
		||||
    NoRestriction_24_7          = 0,
 | 
			
		||||
    OnlyWorkingDays             = 1,    // [Monday-Friday]
 | 
			
		||||
    OnlyWeekDays                = 2,    // [Monday-Saturday]
 | 
			
		||||
    OnlyWeekEnd                 = 4,    // [Saturday+Sunday]
 | 
			
		||||
    OnlyOfficialHolidays        = 8,
 | 
			
		||||
    OnlySundaysAndHolidays      = 12,   // [Sun+Holiday]
 | 
			
		||||
    OnlySpecialDays             = 16,
 | 
			
		||||
    OnlySchoolHolidays          = 32,
 | 
			
		||||
    SpecialAndSchoolHolidays    = 48,
 | 
			
		||||
    OnlyOpenForBusinessDays     = 64,   // verkaufsoffen
 | 
			
		||||
    AllDaysWithRestrictedHours  = 128,  // every day, restricted to some time range
 | 
			
		||||
    NoBusinessHoursDefined      = 255
 | 
			
		||||
    NoBusinessHoursDefined      = 255,
 | 
			
		||||
 | 
			
		||||
    // new 12.04.2024
 | 
			
		||||
    NO_RESTRICTION_24_7 = _NO_RESTRICTION_24_7_,
 | 
			
		||||
    MON = _MON_,
 | 
			
		||||
    TUE = _TUE_,
 | 
			
		||||
    WED = _WED_,
 | 
			
		||||
    THU = _THU_,
 | 
			
		||||
    FRI = _FRI_,
 | 
			
		||||
    SAT = _SAT_,
 | 
			
		||||
    SUN = _SUN_,
 | 
			
		||||
    WEEK_DAYS = _WEEK_DAYS_,
 | 
			
		||||
    WORKING_DAYS = _WORKING_DAYS_,
 | 
			
		||||
    ALL_DAYS = _ALL_DAYS_,
 | 
			
		||||
    OFFICIAL_HOLIDAY = _OFFICIAL_HOLIDAY_,
 | 
			
		||||
    ONLY_WEEKEND = _ONLY_WEEKEND_,
 | 
			
		||||
    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_
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static bool business(uint64_t businessHours, QDateTime &const dt) {
 | 
			
		||||
    switch (dayOfWeek) {
 | 
			
		||||
    case Qt::Monday:
 | 
			
		||||
        (businessHours & _MON_) == _MON_;
 | 
			
		||||
    case Qt::Tuesday:
 | 
			
		||||
    case Qt::Wednesday:
 | 
			
		||||
    case Qt::Thursday:
 | 
			
		||||
    case Qt::Saturday:
 | 
			
		||||
    case Qt::Sunday:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct BusinessHours_struct {
 | 
			
		||||
    BusinessHours bh;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_BUSINESS_HOURS_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								library/include/mobilisis/tariff_global_defines.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								library/include/mobilisis/tariff_global_defines.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
#ifndef TARIFF_GLOBAL_DEFINES_H_INCLUDED
 | 
			
		||||
#define TARIFF_GLOBAL_DEFINES_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_GLOBAL_DEFINES_H_INCLUDED
 | 
			
		||||
@@ -4,14 +4,16 @@
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
enum class PERMIT_TYPE : quint8 {
 | 
			
		||||
    SHORT_TERM_PARKING,
 | 
			
		||||
    DAY_TICKET,
 | 
			
		||||
    SZEGED_START,
 | 
			
		||||
    SZEGED_STOP,
 | 
			
		||||
    DAY_TICKET_ADULT,
 | 
			
		||||
    DAY_TICKET_TEEN,
 | 
			
		||||
    DAY_TICKET_CHILD,
 | 
			
		||||
    INVALID
 | 
			
		||||
    SHORT_TERM_PARKING=0,
 | 
			
		||||
    DAY_TICKET=1,
 | 
			
		||||
    SZEGED_START=2,
 | 
			
		||||
    SZEGED_STOP=3,
 | 
			
		||||
    DAY_TICKET_ADULT=4,
 | 
			
		||||
    DAY_TICKET_TEEN=5,
 | 
			
		||||
    DAY_TICKET_CHILD=6,
 | 
			
		||||
    INVALID=7,
 | 
			
		||||
    FOOD_STAMP=8,
 | 
			
		||||
    TWENTY_FOUR_HOURS_TICKET=9
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PermitType {
 | 
			
		||||
@@ -41,6 +43,12 @@ struct PermitType {
 | 
			
		||||
        case 6:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::DAY_TICKET_CHILD;
 | 
			
		||||
            break;
 | 
			
		||||
        case 7:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::FOOD_STAMP;
 | 
			
		||||
            break;
 | 
			
		||||
        case 8:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::INVALID;
 | 
			
		||||
        }
 | 
			
		||||
@@ -52,7 +60,7 @@ struct PermitType {
 | 
			
		||||
 | 
			
		||||
    operator PERMIT_TYPE() const { return m_permitType; }
 | 
			
		||||
 | 
			
		||||
    operator int() const {
 | 
			
		||||
    operator int () const {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::SHORT_TERM_PARKING:
 | 
			
		||||
            return 0;
 | 
			
		||||
@@ -68,6 +76,10 @@ struct PermitType {
 | 
			
		||||
            return 5;
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
            return 6;
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return 7;
 | 
			
		||||
        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
			
		||||
            return 8;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -75,7 +87,7 @@ struct PermitType {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator QString() const {
 | 
			
		||||
    QString toString() {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
			
		||||
            return QString("DAY_TICKET");
 | 
			
		||||
@@ -91,11 +103,49 @@ struct PermitType {
 | 
			
		||||
            return QString("SZEGED_START");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_STOP:
 | 
			
		||||
            return QString("SZEGED_STOP");
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return QString("FOOD_STAMP");
 | 
			
		||||
        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
			
		||||
            return QString("TWENTY_FOUR_HOURS_TICKET");
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return QString("INVALID");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString toString() const {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
			
		||||
            return QString("DAY_TICKET");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_ADULT:
 | 
			
		||||
            return QString("DAY_TICKET_ADULT");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_CHILD:
 | 
			
		||||
            return QString("DAY_TICKET_CHILD");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
            return QString("DAY_TICKET_TEEN");
 | 
			
		||||
        case PERMIT_TYPE::SHORT_TERM_PARKING:
 | 
			
		||||
            return QString("SHORT_TERM_PARKING");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_START:
 | 
			
		||||
            return QString("SZEGED_START");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_STOP:
 | 
			
		||||
            return QString("SZEGED_STOP");
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return QString("FOOD_STAMP");
 | 
			
		||||
        case PERMIT_TYPE::TWENTY_FOUR_HOURS_TICKET:
 | 
			
		||||
            return QString("TWENTY_FOUR_HOURS_TICKET");
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return QString("INVALID");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator QString () {
 | 
			
		||||
        return toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator QString () const {
 | 
			
		||||
        return toString();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,8 @@ struct ATBTariffProduct {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t getProductPrice() const { return m_tariff_product_price; }
 | 
			
		||||
 | 
			
		||||
    friend QDebug operator<<(QDebug debug, ATBTariffProduct const &product) {
 | 
			
		||||
        QDebugStateSaver saver(debug);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,9 @@
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
namespace Utilities {
 | 
			
		||||
 | 
			
		||||
    bool isDayIncluded(uint64_t businessHours, QDateTime const &dt);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get day of week from current date (Zeller's Algorithm), starting day is Sunday
 | 
			
		||||
	/// </summary>
 | 
			
		||||
@@ -76,10 +79,12 @@ namespace Utilities {
 | 
			
		||||
	double CalculatePricePerUnit(double pra_price, double durationUnit = -1);
 | 
			
		||||
 | 
			
		||||
    QTime SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDayId);
 | 
			
		||||
    QTime SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator const &it);
 | 
			
		||||
    QTime SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId);
 | 
			
		||||
    QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
			
		||||
    QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
			
		||||
    int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator itr);
 | 
			
		||||
    QTime SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator const &it);
 | 
			
		||||
    QTime WeekDaysWorkTimeFrom(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
			
		||||
    QTime WeekDaysWorkTimeUntil(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
			
		||||
    int WeekDayId(std::multimap<int, ATBWeekDaysWorktime>::const_iterator const &itr);
 | 
			
		||||
    // PaymentRate GetPaymentRate(Configuration const *cfg, );
 | 
			
		||||
    bool isCarryOverSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
			
		||||
    bool isCarryOverNotSet(Configuration const *cfg, PaymentMethod paymentMethodId);
 | 
			
		||||
@@ -94,4 +99,6 @@ namespace Utilities {
 | 
			
		||||
    BusinessHours getBusinessHours(Configuration const *cfg, PaymentMethod methodId);
 | 
			
		||||
    uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id);
 | 
			
		||||
    double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id);
 | 
			
		||||
    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=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) {
 | 
			
		||||
    win32 {
 | 
			
		||||
        QMAKE_CXXFLAGS += -DCALCULATE_LIBRARY_EXPORTS
 | 
			
		||||
@@ -79,7 +83,8 @@ HEADERS += \
 | 
			
		||||
    include/mobilisis/tariff_timebase.h \
 | 
			
		||||
    include/mobilisis/tariff_timestep_config.h \
 | 
			
		||||
    include/mobilisis/tariff_product.h \
 | 
			
		||||
    include/mobilisis/tariff_permit_type.h
 | 
			
		||||
    include/mobilisis/tariff_permit_type.h \
 | 
			
		||||
    include/mobilisis/tariff_global_defines.h
 | 
			
		||||
 | 
			
		||||
OTHER_FILES += src/main.cpp \
 | 
			
		||||
    ../tariffs/tariff_korneuburg.json \
 | 
			
		||||
 
 | 
			
		||||
@@ -10,16 +10,33 @@
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#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) {
 | 
			
		||||
    return Calculator::GetInstance().GetTimeSteps(cfg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration const *cfg,
 | 
			
		||||
                                                  PERMIT_TYPE permitType,
 | 
			
		||||
                                                  int paymentOptionIndex) {
 | 
			
		||||
    int minTime = 0;
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
        minTime = cfg->getPaymentOptions().pop_min_time;
 | 
			
		||||
        minTime = cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
    } break;
 | 
			
		||||
@@ -30,20 +47,22 @@ int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYP
 | 
			
		||||
    default:
 | 
			
		||||
        // for each new sell-procedure, recomute the timesteps. implicitly, set
 | 
			
		||||
        // the minimal parking time.
 | 
			
		||||
        Calculator::GetInstance().ResetTimeSteps();
 | 
			
		||||
        Calculator::GetInstance().GetTimeSteps(cfg);
 | 
			
		||||
        minTime = qRound(cfg->getPaymentOptions().pop_min_time);
 | 
			
		||||
        Calculator::GetInstance().ResetTimeSteps(paymentOptionIndex);
 | 
			
		||||
        Calculator::GetInstance().GetTimeSteps((Configuration *)cfg, paymentOptionIndex);
 | 
			
		||||
        minTime = qRound(cfg->getPaymentOptions(paymentOptionIndex).pop_min_time);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return minTime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration const *cfg,
 | 
			
		||||
                                                  PERMIT_TYPE permitType,
 | 
			
		||||
                                                  int paymentOptionIndex) {
 | 
			
		||||
    int maxTime = 0;
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
        maxTime = cfg->getPaymentOptions().pop_max_time;
 | 
			
		||||
        maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time;
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
    } break;
 | 
			
		||||
@@ -55,14 +74,18 @@ int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYP
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return maxTime;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg,
 | 
			
		||||
                                                   PERMIT_TYPE permitType,
 | 
			
		||||
                                                   int paymentOptionIndex,
 | 
			
		||||
                                                   QDateTime const &start) {
 | 
			
		||||
    int minPrice = -1;
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
        minPrice = cfg->getPaymentOptions().pop_min_price;
 | 
			
		||||
        minPrice = cfg->getPaymentOptions(paymentOptionIndex).pop_min_price;
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
    } break;
 | 
			
		||||
@@ -70,13 +93,20 @@ int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TY
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_CHILD: {
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET: {
 | 
			
		||||
        minPrice = compute_product_price(cfg, permitType, start);
 | 
			
		||||
    } break;
 | 
			
		||||
    default: ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return minPrice;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg,
 | 
			
		||||
                                                PERMIT_TYPE permitType,
 | 
			
		||||
                                                QDateTime const &start,
 | 
			
		||||
                                                QDateTime *productStart,
 | 
			
		||||
                                                QDateTime *productEnd) {
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
@@ -85,6 +115,8 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
        std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
 | 
			
		||||
        if (products) {
 | 
			
		||||
@@ -92,9 +124,95 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
 | 
			
		||||
            if (product.size() > 0) {
 | 
			
		||||
                ATBTariffProduct const &p = product[0];
 | 
			
		||||
                return p.m_tariff_product_price;
 | 
			
		||||
#if 0
 | 
			
		||||
                // in case we do not have prepaid-option
 | 
			
		||||
                QTime const ¤tTime = QDateTime::currentDateTime().time();
 | 
			
		||||
 | 
			
		||||
                if (p.m_tariff_product_start <= currentTime && currentTime <= p.m_tariff_product_end) {
 | 
			
		||||
                    return p.m_tariff_product_price;
 | 
			
		||||
                } else {
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "ERROR currentTime"
 | 
			
		||||
                                << currentTime.toString(Qt::ISODate)
 | 
			
		||||
                                << "INVALID ("
 | 
			
		||||
                                << p.m_tariff_product_start.toString(Qt::ISODate)
 | 
			
		||||
                                << p.m_tariff_product_end.toString(Qt::ISODate) << ")";
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::INVALID:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET: {
 | 
			
		||||
        std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
 | 
			
		||||
        if (products) {
 | 
			
		||||
            QVector<ATBTariffProduct> product = products.value();
 | 
			
		||||
            int product_price = 0;
 | 
			
		||||
 | 
			
		||||
            if (productStart && productEnd) {
 | 
			
		||||
                *productStart = start;
 | 
			
		||||
                *productEnd = start;
 | 
			
		||||
                if (product.size() > 0) {
 | 
			
		||||
                    productStart->setTime(product[0].getTimeStart());
 | 
			
		||||
                    productEnd->setTime(product[0].getTimeEnd());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (QVector<ATBTariffProduct>::size_type i=0; i<product.size(); ++i) {
 | 
			
		||||
                ATBTariffProduct const &p = product[i];
 | 
			
		||||
                QTime const &startTime = p.getTimeStart();
 | 
			
		||||
                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) {
 | 
			
		||||
                    product_price = p.getProductPrice();
 | 
			
		||||
                    if (productStart && productEnd) {
 | 
			
		||||
                        productStart->setTime(startTime);
 | 
			
		||||
                        productEnd->setTime(endTime);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
    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:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -102,22 +220,24 @@ int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg,
 | 
			
		||||
                                                   PERMIT_TYPE permitType,
 | 
			
		||||
                                                   int paymentOptionIndex) {
 | 
			
		||||
    int maxPrice = -1;
 | 
			
		||||
    static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
        if (paymentMethodId == PaymentMethod::Progressive) {
 | 
			
		||||
        if (paymentMethodId == PaymentMethod::Progressive || paymentMethodId == PaymentMethod::Steps) {
 | 
			
		||||
            maxPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId);
 | 
			
		||||
        } else { // PaymentMethod::Linear -> e.g. szeged
 | 
			
		||||
            int const key = cfg->getPaymentOptions().pop_id;
 | 
			
		||||
            int const maxTime = cfg->getPaymentOptions().pop_max_time; // maxTime is given in minutes
 | 
			
		||||
            int const key = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
 | 
			
		||||
            int const maxTime = cfg->getPaymentOptions(paymentOptionIndex).pop_max_time; // maxTime is given in minutes
 | 
			
		||||
            std::optional<QVector<ATBPaymentRate>> const &pv = cfg->getPaymentRateForKey(key);
 | 
			
		||||
            if (pv) {
 | 
			
		||||
                QVector<ATBPaymentRate> const &paymentRate = pv.value();
 | 
			
		||||
                if (paymentRate.size() > 0) {
 | 
			
		||||
                    int const price = paymentRate.at(0).pra_price; // price is given per hour
 | 
			
		||||
                    int const price = paymentRate.last().pra_price; // price is given per hour
 | 
			
		||||
                    maxPrice = qRound((maxTime * price) / 60.0f);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -252,8 +372,31 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu
 | 
			
		||||
        // progressive tariff: e.g. Neuhauser, Kirchdorf (743)
 | 
			
		||||
        (paymentMethodId == PaymentMethod::Progressive))
 | 
			
		||||
    {
 | 
			
		||||
        const QList<int> stepList = Calculator::GetInstance().GetTimeSteps(tariff);
 | 
			
		||||
        qCritical() << "   compute_next_timestep()     timeSteps:" << stepList;
 | 
			
		||||
        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() 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);
 | 
			
		||||
 | 
			
		||||
@@ -333,7 +476,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
    if (duration < 0) {
 | 
			
		||||
        calcState.setDesc(QString("end=%1, start=%2")
 | 
			
		||||
                          .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) {
 | 
			
		||||
        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(duration).arg(maxMin));
 | 
			
		||||
@@ -382,11 +525,15 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        bool prepaid)
 | 
			
		||||
{
 | 
			
		||||
    CalcState calcState;
 | 
			
		||||
    double minMin = tariff->getPaymentOptions().pop_min_time;
 | 
			
		||||
    double maxMin = tariff->getPaymentOptions().pop_max_time;
 | 
			
		||||
 | 
			
		||||
    int paymentOptionIndex = tariff->getPaymentOptionIndex(start_parking_time);
 | 
			
		||||
 | 
			
		||||
    double minMin = tariff->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
			
		||||
    double maxMin = tariff->getPaymentOptions(paymentOptionIndex).pop_max_time;
 | 
			
		||||
 | 
			
		||||
    // DEBUG
 | 
			
		||||
    qCritical() << "compute_price_for_parking_ticket() " << endl
 | 
			
		||||
                << "          paymentOptionIndex: " << paymentOptionIndex << endl
 | 
			
		||||
                << "          start_parking_time: " << start_parking_time << endl
 | 
			
		||||
                << "          netto_parking_time: " << netto_parking_time << endl
 | 
			
		||||
                << "                      minMin: " << minMin << endl
 | 
			
		||||
@@ -397,7 +544,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        calcState.setDesc(QString("end=%1, start=%2")
 | 
			
		||||
                          .arg(end_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) {
 | 
			
		||||
        calcState.setDesc(QString("duration=%1, maxMin=%2").arg(netto_parking_time).arg(maxMin));
 | 
			
		||||
@@ -411,25 +558,46 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        return calcState.set(CalcState::State::SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double cost = -1;
 | 
			
		||||
    if (start_parking_time.isValid()) {
 | 
			
		||||
        double cost = Calculator::GetInstance().GetCostFromDuration(
 | 
			
		||||
        if (tariff->getPaymentOptions(paymentOptionIndex).pop_payment_method_id == PaymentMethod::Steps) {
 | 
			
		||||
            // hier muesste man unterscheiden: uebertrag oder nicht?
 | 
			
		||||
            calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time,
 | 
			
		||||
                                                                   netto_parking_time, paymentOptionIndex);
 | 
			
		||||
            if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
			
		||||
                // qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                //             << calcState.toString();
 | 
			
		||||
                return calcState;
 | 
			
		||||
            }
 | 
			
		||||
            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 {
 | 
			
		||||
            cost = Calculator::GetInstance().GetCostFromDuration(
 | 
			
		||||
                        tariff,
 | 
			
		||||
                        tariff->getPaymentOptions().pop_payment_method_id,
 | 
			
		||||
                        start_parking_time,         // starting time
 | 
			
		||||
                        end_parking_time,           // return value: end time
 | 
			
		||||
                        netto_parking_time,         // minutes, netto
 | 
			
		||||
                        false, prepaid);
 | 
			
		||||
        double minCost = tariff->getPaymentOptions().pop_min_price;
 | 
			
		||||
        }
 | 
			
		||||
        double minCost = tariff->getPaymentOptions(paymentOptionIndex).pop_min_price;
 | 
			
		||||
        if (cost < minCost) {
 | 
			
		||||
            calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost));
 | 
			
		||||
            return calcState.set(CalcState::State::BELOW_MIN_PARKING_PRICE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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->units = cost;
 | 
			
		||||
        price->netto = cost;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        return calcState.set(CalcState::State::INVALID_START_DATE);
 | 
			
		||||
    }
 | 
			
		||||
@@ -485,16 +653,76 @@ CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(
 | 
			
		||||
                    tariff->getPaymentOptions().pop_payment_method_id,
 | 
			
		||||
                    cs.toLocal8Bit().constData(),
 | 
			
		||||
                    price, false, true).c_str();
 | 
			
		||||
        ticketEndTime = QDateTime::fromString(endTime,Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
        // DEBUG
 | 
			
		||||
        qCritical() << "compute_duration_for_parking_ticket(): ";
 | 
			
		||||
        qCritical() << "                 endTime: " << endTime;
 | 
			
		||||
        qCritical() << "           ticketEndTime: " << ticketEndTime;
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
        if (!ticketEndTime.isValid()) {
 | 
			
		||||
            calcState.setDesc(QString("ticketEndTime=%1").arg(endTime));
 | 
			
		||||
            return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
 | 
			
		||||
            // DEBUG
 | 
			
		||||
            //qCritical() << "compute_duration_for_parking_ticket(): ";
 | 
			
		||||
            //qCritical() << "                 endTime: " << endTime;
 | 
			
		||||
            //qCritical() << "           ticketEndTime: " << ticketEndTime;
 | 
			
		||||
 | 
			
		||||
            if (!ticketEndTime.isValid()) {
 | 
			
		||||
                calcState.setDesc(QString("ticketEndTime=%1").arg(endTime));
 | 
			
		||||
                return calcState.set(CalcState::State::WRONG_ISO_TIME_FORMAT);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        return calcState.set(CalcState::State::INVALID_START_DATE);
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,5 +1,6 @@
 | 
			
		||||
#include "utilities.h"
 | 
			
		||||
#include "tariff_log.h"
 | 
			
		||||
#include "tariff_business_hours.h"
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
@@ -260,7 +261,7 @@ bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeS
 | 
			
		||||
						//cout << "CheckSpecialDay() => Month is in range between start and end" << endl;
 | 
			
		||||
						if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday))
 | 
			
		||||
						{
 | 
			
		||||
							LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
 | 
			
		||||
                            //LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
 | 
			
		||||
							*specialDayId = spec_days_itr->second.ped_id;
 | 
			
		||||
							*specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
 | 
			
		||||
							return true;
 | 
			
		||||
@@ -275,7 +276,7 @@ bool Utilities::CheckSpecialDay(Configuration* cfg, const char* currentDateTimeS
 | 
			
		||||
					//cout << "CheckSpecialDay() => Month is in range between start and end" << endl;
 | 
			
		||||
					if ((current_tm.tm_mday >= start_tm.tm_mday) && (current_tm.tm_mday <= end_tm.tm_mday))
 | 
			
		||||
					{
 | 
			
		||||
						LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
 | 
			
		||||
                        //LOG_DEBUG("CheckSpecialDay() => SPECIAL DAY");
 | 
			
		||||
						*specialDayId = spec_days_itr->second.ped_id;
 | 
			
		||||
						*specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
 | 
			
		||||
						return true;
 | 
			
		||||
@@ -317,7 +318,7 @@ bool Utilities::CheckSpecialDay(Configuration const *cfg,
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    qDebug() << "CheckSpecialDay() => SPECIAL DAY";
 | 
			
		||||
                    //qDebug() << "CheckSpecialDay() => SPECIAL DAY";
 | 
			
		||||
                    *specialDayId = spec_days_itr->second.ped_id;
 | 
			
		||||
                    *specialDayPrice = cfg->SpecialDaysWorktime.find(*specialDayId)->second.pedwt_price;
 | 
			
		||||
                    return true;
 | 
			
		||||
@@ -333,19 +334,27 @@ QTime Utilities::SpecialDaysWorkTimeFrom(Configuration const *cfg, int specialDa
 | 
			
		||||
    return QTime::fromString(cfg->SpecialDaysWorktime.find(specialDayId)->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QTime Utilities::SpecialDaysWorkTimeFrom(Configuration::SpecialDaysWorktimeType::const_iterator const &it) {
 | 
			
		||||
    return QTime::fromString(it->second.pedwt_time_from.c_str(), Qt::ISODate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QTime Utilities::SpecialDaysWorkTimeUntil(Configuration::SpecialDaysWorktimeType::const_iterator const &it) {
 | 
			
		||||
    return QTime::fromString(it->second.pedwt_time_to.c_str(), Qt::ISODate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QTime Utilities::SpecialDaysWorkTimeUntil(Configuration const *cfg, int specialDayId) {
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -397,9 +406,16 @@ uint32_t Utilities::getMaximalParkingPrice(Configuration const *cfg, PaymentMeth
 | 
			
		||||
    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) {
 | 
			
		||||
    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;
 | 
			
		||||
@@ -420,10 +436,10 @@ uint32_t Utilities::getFirstDurationStep(Configuration const *cfg, PaymentMethod
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMethod methodId) {
 | 
			
		||||
    int businessHours = cfg->PaymentOption.find(methodId)->second.pop_business_hours;
 | 
			
		||||
    uint64_t businessHours = cfg->PaymentOption.find(methodId)->second.pop_business_hours;
 | 
			
		||||
 | 
			
		||||
    switch (businessHours) {
 | 
			
		||||
    case NoRestriction_24_7: return BusinessHours::NoRestriction_24_7;
 | 
			
		||||
    //case NoRestriction_24_7: return BusinessHours::NoRestriction_24_7;
 | 
			
		||||
    case OnlyWorkingDays: return BusinessHours::OnlyWorkingDays;
 | 
			
		||||
    case OnlyWeekDays: return BusinessHours::OnlyWeekDays;
 | 
			
		||||
    case OnlyWeekEnd: return BusinessHours::OnlyWeekEnd;
 | 
			
		||||
@@ -433,6 +449,21 @@ BusinessHours Utilities::getBusinessHours(Configuration const *cfg, PaymentMetho
 | 
			
		||||
    case SpecialAndSchoolHolidays: return BusinessHours::SpecialAndSchoolHolidays;
 | 
			
		||||
    case OnlyOpenForBusinessDays: return BusinessHours::OnlyOpenForBusinessDays;
 | 
			
		||||
    case AllDaysWithRestrictedHours: return BusinessHours::AllDaysWithRestrictedHours;
 | 
			
		||||
    case _NO_RESTRICTION_24_7_: return BusinessHours::NO_RESTRICTION_24_7;
 | 
			
		||||
    case _MON_: return BusinessHours::MON;
 | 
			
		||||
    case _TUE_: return BusinessHours::TUE;
 | 
			
		||||
    case _WED_: return BusinessHours::WED;
 | 
			
		||||
    case _THU_: return BusinessHours::THU;
 | 
			
		||||
    case _FRI_: return BusinessHours::FRI;
 | 
			
		||||
    case _SAT_: return BusinessHours::SAT;
 | 
			
		||||
    case _SUN_: return BusinessHours::SUN;
 | 
			
		||||
    case _WEEK_DAYS_: return BusinessHours::WEEK_DAYS;
 | 
			
		||||
    case _WORKING_DAYS_: return BusinessHours::WORKING_DAYS;
 | 
			
		||||
    case _ALL_DAYS_: return BusinessHours::ALL_DAYS;
 | 
			
		||||
    case _OFFICIAL_HOLIDAY_: return BusinessHours::OFFICIAL_HOLIDAY;
 | 
			
		||||
    case _ONLY_WEEKEND_: return BusinessHours::ONLY_WEEKEND;
 | 
			
		||||
    case _ONLY_OPEN_FOR_BUSINESS_DAYS_: return BusinessHours::ONLY_OPEN_FOR_BUSINESS_DAYS;
 | 
			
		||||
    case _NOT_DEFINED_: return BusinessHours::NOT_DEFINED;
 | 
			
		||||
    }
 | 
			
		||||
    return BusinessHours::NoBusinessHoursDefined;
 | 
			
		||||
}
 | 
			
		||||
@@ -447,3 +478,82 @@ double Utilities::computeWeekDaysDurationUnit(Configuration const *cfg, PaymentM
 | 
			
		||||
    int durationId = cfg->PaymentRate.find(pop_id)->second.pra_payment_unit_id;
 | 
			
		||||
    return (double)(cfg->Duration.find(durationId)->second.pun_duration);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Utilities::isDayIncluded(uint64_t businessHours, QDateTime const &dt) {
 | 
			
		||||
    int dayOfWeek = dt.date().dayOfWeek();
 | 
			
		||||
    switch (dayOfWeek) {
 | 
			
		||||
    case Qt::Monday:
 | 
			
		||||
        return ((businessHours & BusinessHours::MON) == BusinessHours::MON);
 | 
			
		||||
    case Qt::Tuesday:
 | 
			
		||||
        return ((businessHours & BusinessHours::TUE) == BusinessHours::TUE);
 | 
			
		||||
    case Qt::Wednesday:
 | 
			
		||||
        return ((businessHours & BusinessHours::WED) == BusinessHours::WED);
 | 
			
		||||
    case Qt::Thursday:
 | 
			
		||||
        return ((businessHours & BusinessHours::THU) == BusinessHours::THU);
 | 
			
		||||
    case Qt::Friday:
 | 
			
		||||
        return ((businessHours & BusinessHours::FRI) == BusinessHours::FRI);
 | 
			
		||||
    case Qt::Saturday:
 | 
			
		||||
        return ((businessHours & BusinessHours::SAT) == BusinessHours::SAT);
 | 
			
		||||
    case Qt::Sunday:
 | 
			
		||||
        return ((businessHours & BusinessHours::SUN) == BusinessHours::SUN);
 | 
			
		||||
    default:;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList Utilities::dumpBusinessHours(uint64_t businessHours) {
 | 
			
		||||
    QStringList s;
 | 
			
		||||
 | 
			
		||||
    if ((businessHours & BusinessHours::MON) == BusinessHours::MON) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "MON (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "MON";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::TUE) == BusinessHours::TUE) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "TUE (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "TUE";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::WED) == BusinessHours::WED) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "WED (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "WED";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::THU) == BusinessHours::THU) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "THU (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "THU";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::FRI) == BusinessHours::FRI) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "FRI (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "FRI";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::SAT) == BusinessHours::SAT) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "SAT (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "SAT";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ((businessHours & BusinessHours::SUN) == BusinessHours::SUN) {
 | 
			
		||||
        if ((businessHours & BusinessHours::OFFICIAL_HOLIDAY) == BusinessHours::OFFICIAL_HOLIDAY) {
 | 
			
		||||
            s << "SUN (Holiday)";
 | 
			
		||||
        } else {
 | 
			
		||||
            s << "SUN";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
											
										
									
								
							
							
								
								
									
										2198
									
								
								main/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										2198
									
								
								main/main.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -27,8 +27,7 @@ CONFIG(debug, debug|release) {
 | 
			
		||||
 | 
			
		||||
SOURCES += main.cpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# HEADERS += \
 | 
			
		||||
# HEADERS +=
 | 
			
		||||
 | 
			
		||||
# 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