#pragma once #include #include "VeDirectFrameHandler.h" template class MovingAverage { public: MovingAverage() : _sum(0) , _index(0) , _count(0) { } void addNumber(T num) { if (_count < WINDOW_SIZE) { _count++; } else { _sum -= _window[_index]; } _window[_index] = num; _sum += num; _index = (_index + 1) % WINDOW_SIZE; } double getAverage() const { if (_count == 0) { return 0.0; } return static_cast(_sum) / _count; } private: std::array _window; T _sum; size_t _index; size_t _count; }; class VeDirectMpptController : public VeDirectFrameHandler { public: VeDirectMpptController() = default; void init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging); bool isDataValid() const; // return true if data valid and not outdated struct veMpptStruct : veStruct { uint8_t MPPT; // state of MPP tracker int32_t PPV; // panel power in W int32_t P; // battery output power in W (calculated) double VPV; // panel voltage in V double IPV; // panel current in A (calculated) bool LOAD; // virtual load output state (on if battery voltage reaches upper limit, off if battery reaches lower limit) uint8_t CS; // current state of operation e. g. OFF or Bulk uint8_t ERR; // error code uint32_t OR; // off reason uint32_t HSDS; // day sequence number 1...365 double H19; // yield total kWh double H20; // yield today kWh int32_t H21; // maximum power today W double H22; // yield yesterday kWh int32_t H23; // maximum power yesterday W frozen::string const& getMpptAsString() const; // state of mppt as string frozen::string const& getCsAsString() const; // current state as string frozen::string const& getErrAsString() const; // error state as string frozen::string const& getOrAsString() const; // off reason as string }; using spData_t = std::shared_ptr; spData_t getData() const { return _spData; } private: void textRxEvent(char* name, char* value) final; void frameValidEvent() final; spData_t _spData = nullptr; veMpptStruct _tmpFrame{}; // private struct for received name and value pairs MovingAverage _efficiency; };