// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-plugins-modbus. * * nymea-plugins-modbus is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nymea-plugins-modbus 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with nymea-plugins-modbus. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef SPEEDWIREINVERTER_H #define SPEEDWIREINVERTER_H #include #include #include #include "sma.h" #include "speedwire.h" #include "speedwireinterface.h" #include "speedwireinverterreply.h" #include "speedwireinverterrequest.h" class SpeedwireInverter : public QObject { Q_OBJECT public: enum State { StateIdle, StateDisconnected, StateInitializing, StateLogin, StateGetInformation, StateQueryData }; Q_ENUM(State) explicit SpeedwireInverter(SpeedwireInterface *speedwireInterface, NetworkDeviceMonitor *monitor, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); explicit SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr); NetworkDeviceMonitor *monitor() const; State state() const; bool reachable() const; Sma::DeviceClass deviceClass() const; QString modelName() const; double totalAcPower() const; double gridFrequency() const; double totalEnergyProduced() const; double todayEnergyProduced() const; double voltageAcPhase1() const; double voltageAcPhase2() const; double voltageAcPhase3() const; double currentAcPhase1() const; double currentAcPhase2() const; double currentAcPhase3() const; double powerAcPhase1() const; double powerAcPhase2() const; double powerAcPhase3() const; double powerDcMpp1() const; double powerDcMpp2() const; double voltageDcMpp1() const; double voltageDcMpp2() const; double currentDcMpp1() const; double currentDcMpp2() const; bool batteryAvailable() const; double batteryCycles() const; double batteryCharge() const; double batteryTemperature() const; double batteryCurrent() const; double batteryVoltage() const; // Query methods SpeedwireInverterReply *sendIdentifyRequest(); SpeedwireInverterReply *sendLoginRequest(const QString &password = "0000", bool loginAsUser = true); SpeedwireInverterReply *sendLogoutRequest(); SpeedwireInverterReply *sendSoftwareVersionRequest(); SpeedwireInverterReply *sendDeviceTypeRequest(); SpeedwireInverterReply *sendBatteryInfoRequest(); // Start connecting void startConnecting(const QString &password = "0000"); public slots: void refresh(); signals: void reachableChanged(bool reachable); void loginFinished(bool success); void stateChanged(State state); void valuesUpdated(); void batteryAvailableChanged(bool available); void batteryValuesUpdated(); private: SpeedwireInterface *m_speedwireInterface = nullptr; NetworkDeviceMonitor *m_monitor = nullptr; QHostAddress m_address; QString m_password; bool m_initialized = false; quint16 m_modelId = 0; quint32 m_serialNumber = 0; bool m_reachable = false; State m_state = StateDisconnected; quint8 m_packetId = 1; bool m_deviceInformationFetched = false; SpeedwireInverterReply *m_currentReply = nullptr; QQueue m_replyQueue; // Properties Sma::DeviceClass m_deviceClass = Sma::DeviceClassUnknown; QString m_modelName; QString m_softwareVersion; double m_totalAcPower = 0; double m_totalEnergyProduced = 0; double m_todayEnergyProduced = 0; double m_gridFrequency = 0; double m_voltageAcPhase1 = 0; double m_voltageAcPhase2 = 0; double m_voltageAcPhase3 = 0; double m_currentAcPhase1 = 0; double m_currentAcPhase2 = 0; double m_currentAcPhase3 = 0; double m_powerAcPhase1 = 0; double m_powerAcPhase2 = 0; double m_powerAcPhase3 = 0; double m_powerDcMpp1 = 0; double m_powerDcMpp2 = 0; double m_voltageDcMpp1 = 0; double m_voltageDcMpp2 = 0; double m_currentDcMpp1 = 0; double m_currentDcMpp2 = 0; bool m_batteryAvailable = false; double m_batteryCycles = 0; double m_batteryVoltage = 0; double m_batteryCurrent = 0; double m_batteryCharge = 0; double m_batteryTemperature = 0; void setState(State state); void sendNextReply(); SpeedwireInverterReply *createReply(const SpeedwireInverterRequest &request); // Request builder function void buildDefaultHeader(QDataStream &stream, quint16 payloadSize = 38, quint8 control = 0xa0); void buildPacket(QDataStream &stream, quint32 command, quint16 packetId); // Send generic request for internal use SpeedwireInverterReply *sendQueryRequest(Speedwire::Command command, quint32 firstWord, quint32 secondWord); // Response process methods void processSoftwareVersionResponse(const QByteArray &response); void processDeviceTypeResponse(const QByteArray &response); void processAcPowerResponse(const QByteArray &response); void processAcVoltageCurrentResponse(const QByteArray &response); void processAcTotalPowerResponse(const QByteArray &response); void processDcPowerResponse(const QByteArray &response); void processDcVoltageCurrentResponse(const QByteArray &response); void processEnergyProductionResponse(const QByteArray &response); void processGridFrequencyResponse(const QByteArray &response); void processBatteryInfoResponse(const QByteArray &response); void processBatteryChargeResponse(const QByteArray &response); void processInverterStatusResponse(const QByteArray &response); void readUntilEndOfMeasurement(QDataStream &stream); double readValue(quint32 value, double divisor = 1.0); double readValue(qint32 value, double divisor = 1.0); void setReachable(bool reachable); void setBatteryAvailable(bool available); private slots: void processData(const QHostAddress &senderAddress, quint16 senderPort, const QByteArray &data); void onReplyTimeout(); void onReplyFinished(); }; #endif // SPEEDWIREINVERTER_H