/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2025, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. * This project including source code and documentation is protected by * copyright law, and remains the property of nymea GmbH. All rights, including * reproduction, publication, editing and translation, are reserved. The use of * this project is subject to the terms of a license agreement to be concluded * with nymea GmbH in accordance with the terms of use of nymea GmbH, available * under https://nymea.io/license * * GNU Lesser General Public License Usage * Alternatively, this project may be redistributed and/or modified under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; version 3. This project is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this project. If not, see . * * For any further details and any questions please contact us under * contact@nymea.io or see our FAQ/Licensing Information on * https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef KECONTACT_H #define KECONTACT_H #include #include #include #include #include #include #include #include "kecontactdatalayer.h" class KeContactRequest { public: KeContactRequest() = default; KeContactRequest(const QUuid &requestId, const QByteArray &command) : m_requestId(requestId), m_command(command) { } QUuid requestId() const { return m_requestId; } QByteArray command() const { return m_command; } uint delayUntilNextCommand() const { return m_delayUntilNextCommand; } void setDelayUntilNextCommand(uint delayUntilNextCommand) { m_delayUntilNextCommand = delayUntilNextCommand; } bool isValid() { return !m_requestId.isNull() && !m_command.isEmpty(); } private: QUuid m_requestId; QByteArray m_command; uint m_delayUntilNextCommand = 200; }; class KeContact : public QObject { Q_OBJECT public: enum DipSwitchOne { // Power settings // DIP 6 7 8 (Bit 2, 1, 0) // 0 0 0 : 10A // 1 0 0 : 13A // 0 1 0 : 16A // 1 1 0 : 20A // 0 0 1 : 25A // 1 0 1 : 32A DipSwitchOnePin8 = 0x01, DipSwitchOnePin7 = 0x02, DipSwitchOnePin6 = 0x04, DipSwitchOnePin5 = 0x08, DipSwitchOnePin4 = 0x10, DipSwitchOneSmartHomeInterface = 0x20, // 3 DipSwitchOneExternalInputX2 = 0x40, // 2 DipSwitchOneExternalInputX1 = 0x80 // 1 }; Q_ENUM(DipSwitchOne) Q_DECLARE_FLAGS(DipSwitchOneFlag, DipSwitchOne) enum State { StateStarting = 0, StateNotReady, StateReady, StateCharging, StateError, StateAuthorizationRejected }; Q_ENUM(State) enum PlugState { PlugStateUnplugged = 0, PlugStatePluggedOnChargingStation = 1, PlugStatePluggedOnChargingStationAndPlugLocked = 3, PlugStatePluggedOnChargingStationAndPluggedOnEV = 5, PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV = 7 }; Q_ENUM(PlugState) enum BroadcastType { BroadcastTypeState = 0, BroadcastTypePlug, BroadcastTypeInput, BroadcastTypeEnableSys, BroadcastTypeMaxCurr, BroadcastTypeEPres }; Q_ENUM(BroadcastType) struct ReportOne { QString product; // Model name (variant QString serialNumber; // Serial number QString firmware; // Firmware version bool comModule; // Communication module is installed (only P30) int seconds; // Current system clock since restart of the charging station.(only P30) quint8 dipSw1; // Dip Switch 1 flag quint8 dipSw2; // Dip Switch 2 flag }; struct ReportTwo { State state; //Current state of the charging station int error1; //Detail code for state 4; exceptions see FAQ on www.kecontact.com int error2; //Detail code for state 4 exception #6 see FAQ on www.kecontact.com PlugState plugState; //Current condition of the loading connection bool enableSys; //Enable state for charging (contains Enable input, RFID, UDP,..). bool enableUser; //Enable condition via UDP. double maxCurrent; //Current preset value via Control pilot in ampere. double maxCurrentPercentage; //Current preset value via Control pilot in 0,1% of the PWM value double currentHardwareLimitation; //Highest possible charging current of the charging connection. Contains device maximum, DIP-switch setting, cable coding and temperature reduction. double currentUser; //Current preset value of the user via UDP; Default = 63000mA. double currentFailsafe; //Current preset value for the Failsafe function. int timeoutFailsafe; //Communication timeout before triggering the Failsafe function. int currTimer; //Shows the current preset value of currtime. int timeoutCt; //Shows the remaining time until the current value is accepted. double setEnergy; //Shows the set energy limit bool output; //State of the output X2. bool input; //State of the potential free Enable input X1. When using the input, please pay attention to the information in the installation manual. QString serialNumber; //Serial number int seconds; //Current system clock since restart of the charging station. }; struct ReportThree { int voltagePhase1; //voltage in V int voltagePhase2; //voltage in V int voltagePhase3; //voltage in V double currentPhase1; //current in A double currentPhase2; //current in A double currentPhase3; //current in A double power; //Current power in W (Real Power). double powerFactor; //Power factor (cosphi) double energySession; //Power consumption of the current loading session in kWh; Reset with new loading session (state = 2). double energyTotal; //Total power consumption (persistent) without current loading session kWh; Is summed up after each completed charging session (state = 0). QString serialNumber; int seconds; //Current system clock since restart of the charging station. }; struct Report1XX { int sessionId; // running session counter; not resettable" double currHW; // maximum charging current of the cable and the charging station setting double startEnergy; // total energy value at the beginning of the session" double presentEnergy; // delivered energy until now (equal to E pres in report 3)" int startTime; // system time when the session was started (seconds from reboot; int endTime; // system time when the session has ended" int stopReason; // reason for stopping the session (1 = vehicle unplug; 10 = Rfid token)" QByteArray rfidTag; // RFID Token ID if session started with rfid QByteArray rfidClass; // RFID classifier shows the defined color code QString serialNumber; // serial number of the charging station" int seconds; // current time when the report was generated }; explicit KeContact(const QHostAddress &address, KeContactDataLayer *dataLayer, QObject *parent = nullptr); ~KeContact(); QHostAddress address() const; void setAddress(const QHostAddress &address); bool reachable() const; QUuid start(const QByteArray &rfidToken, const QByteArray &rfidClassifier); // Command “start” QUuid stop(const QByteArray &rfidToken); // Command “stop” QUuid enableOutput(bool state); // Command “ena” QUuid setMaxAmpere(int milliAmpere); // Command "currtime" QUuid setMaxAmpereGeneral(int milliAmpere); // Command "curr" QUuid unlockCharger(); // Command “unlock" QUuid displayMessage(const QByteArray &message); // Command “display” QUuid chargeWithEnergyLimit(double energy); // Command “setenergy” QUuid setFailsafe(int timeout, int current, bool save); // Command “failsafe” void getDeviceInformation(); // Command “i” void getReport1(); // Command “report” void getReport2(); void getReport3(); void getReport1XX(int reportNumber = 100); // Command “report 1xx” // Command “currtime” QUuid setOutputX2(bool state); // Command “output” private: KeContactDataLayer *m_dataLayer = nullptr; bool m_reachable = false; QHostAddress m_address; QTimer *m_requestTimeoutTimer = nullptr; QTimer *m_pauseTimer = nullptr; int m_serialNumber = 0; KeContactRequest m_currentRequest; QQueue m_requestQueue; void getReport(int reportNumber); void sendCommand(const QByteArray &command); void sendNextCommand(); void setReachable(bool reachable); signals: void reachableChanged(bool status); void commandExecuted(QUuid requestId, bool success); void deviceInformationReceived(const QString &firmware); void reportOneReceived(const KeContact::ReportOne &reportOne); void reportTwoReceived(const KeContact::ReportTwo &reportTwo); void reportThreeReceived(const KeContact::ReportThree &reportThree); void report1XXReceived(int reportNumber, const KeContact::Report1XX &report); void broadcastReceived(KeContact::BroadcastType type, const QVariant &content); private slots: void onReceivedDatagram(const QHostAddress &address, const QByteArray &datagram); }; Q_DECLARE_OPERATORS_FOR_FLAGS(KeContact::DipSwitchOneFlag); #endif // KECONTACT_H