Skip to content

Commit

Permalink
feat(pv-overrides): show solar and pv icons on hmi controller
Browse files Browse the repository at this point in the history
  • Loading branch information
tspopp committed Jun 12, 2024
1 parent 6f4e17b commit 9d7d306
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 39 deletions.
10 changes: 8 additions & 2 deletions AquaMQTT/include/message/MainStatusMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class MainStatusMessage

bool statePV();

void enableStatePV(bool enabled);

bool stateSolar();

void enableStateSolar(bool enabled);

uint8_t settingPwmFirst();

uint8_t settingPwmSecond();
Expand Down Expand Up @@ -79,7 +85,7 @@ class MainStatusMessage

bool statesChanged() const;

bool statePVChanged() const;
bool statePVOrSolarChanged() const;

uint8_t errorCode() const;

Expand Down Expand Up @@ -120,7 +126,7 @@ class MainStatusMessage
bool mSettingBoilerCapacityChanged;
bool mSettingBoilerBrandChanged;
bool mSettingCapabilitiesChanged;
bool mPVStateChanged;
bool mPVOrSolarStateChanged;
bool mErrorCodeChanged;
};

Expand Down
2 changes: 2 additions & 0 deletions AquaMQTT/include/mqtt/MQTTDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const char MAIN_STATE_HEAT_ELEMENT[] PROGMEM = { "stateElement" };
const char MAIN_STATE_EXT_BOILER[] PROGMEM = { "stateExtBoiler" };
const char MAIN_STATE_DEFROST[] PROGMEM = { "stateDefrost" };
const char MAIN_STATE_PV[] PROGMEM = { "statePV" };
const char MAIN_STATE_SOLAR[] PROGMEM = { "stateSolar" };

const char MAIN_SETTING_PWM_01[] PROGMEM = { "settingPWM_1" };
const char MAIN_SETTING_PWM_02[] PROGMEM = { "settingPWM_2" };
Expand Down Expand Up @@ -135,6 +136,7 @@ const char STATS_MSG_SENT[] PROGMEM = { "msgSent" };
const char STATS_MSG_CRC_NOK[] PROGMEM = { "msgCRCNOK" };
const char STATS_DROPPED_BYTES[] PROGMEM = { "droppedBytes" };
const char STATS_ACTIVE_OVERRIDES[] PROGMEM = { "activeOverrides" };
const char STATS_ACTIVE_OVERRIDES_MAIN[] PROGMEM = { "activeOverridesMain" };
const char STATS_ENABLE_FLAG_PV_HEATPUMP[] PROGMEM = { "flagPVModeHeatPump" };
const char STATS_ENABLE_FLAG_PV_HEATELEMENT[] PROGMEM = { "flagPVModeHeatElement" };

Expand Down
73 changes: 73 additions & 0 deletions AquaMQTT/include/state/MainStateProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef AQUAMQTT_MAINSTATEPROXY_H
#define AQUAMQTT_MAINSTATEPROXY_H

#include "message/MainStatusMessage.h"
#include "mqtt/IMQTTCallback.h"
#include "state/DHWState.h"

namespace aquamqtt
{

struct AquaMqttMainOverrides
{
bool pvState;
bool solarState;
};

/**
* MainStateProxy accesses messages emitted by the main controller through DHW
* state and applies overrides for customizing the HMI
*/

class MainStateProxy : public mqtt::IMQTTCallback
{
public:
static MainStateProxy& getInstance();

virtual ~MainStateProxy() = default;

MainStateProxy(const MainStateProxy&) = delete;

private:
MainStateProxy();

public:
MainStateProxy& operator=(const MainStateProxy&) = delete;

void setListener(TaskHandle_t handle);

void applyMainOverrides(uint8_t* buffer);

bool copyFrame(uint8_t frameId, uint8_t* buffer);

void onOperationModeChanged(std::unique_ptr<message::HMIOperationMode> value) override;

void onOperationTypeChanged(std::unique_ptr<message::HMIOperationType> type) override;

void onInstallationModeChanged(std::unique_ptr<message::HMIInstallation> mode) override;

void onWaterTempTargetChanged(std::unique_ptr<float> value) override;

void onHeatingElementEnabledChanged(std::unique_ptr<bool> enabled) override;

void onEmergencyModeEnabledChanged(std::unique_ptr<bool> enabled) override;

void onPVModeHeatpumpEnabled(bool enabled) override;

void onPVModeHeatElementEnabled(bool enabled) override;

void onResetOverrides() override;

AquaMqttMainOverrides getOverrides();

private:
TaskHandle_t mNotify;
SemaphoreHandle_t mMutex;

bool mPVModeHeatPump;
bool mPVModeHeatElement;
};

} // namespace aquamqtt

#endif // AQUAMQTT_MAINSTATEPROXY_H
38 changes: 32 additions & 6 deletions AquaMQTT/src/message/MainStatusMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ bool MainStatusMessage::stateDefrost()
}

bool MainStatusMessage::statePV()
{
return mData[22] & 0x10;
}

bool MainStatusMessage::stateSolar()
{
return mData[22] & 0x20;
}
Expand Down Expand Up @@ -137,7 +142,7 @@ void MainStatusMessage::compareWith(uint8_t* data)
mSettingBoilerCapacityChanged = true;
mSettingBoilerBrandChanged = true;
mSettingCapabilitiesChanged = true;
mPVStateChanged = true;
mPVOrSolarStateChanged = true;
mErrorCodeChanged = true;
return;
}
Expand Down Expand Up @@ -191,7 +196,7 @@ void MainStatusMessage::compareWith(uint8_t* data)
mSettingAntiLegionellaTargetChanged = true;
break;
case 22:
mPVStateChanged = true;
mPVOrSolarStateChanged = true;
break;
case 23:
mErrorCodeChanged = true;
Expand Down Expand Up @@ -231,7 +236,7 @@ MainStatusMessage::MainStatusMessage(uint8_t* data)
, mSettingBoilerCapacityChanged(false)
, mSettingBoilerBrandChanged(false)
, mSettingCapabilitiesChanged(false)
, mPVStateChanged(false)
, mPVOrSolarStateChanged(false)
, mErrorCodeChanged(false)
{
}
Expand Down Expand Up @@ -295,15 +300,14 @@ bool MainStatusMessage::settingCapabilitiesChanged() const
{
return mSettingCapabilitiesChanged;
}
bool MainStatusMessage::statePVChanged() const
bool MainStatusMessage::statePVOrSolarChanged() const
{
return mPVStateChanged;
return mPVOrSolarStateChanged;
}
bool MainStatusMessage::errorCodeChanged() const
{
return mErrorCodeChanged;
}

uint8_t MainStatusMessage::errorCode() const
{
if (mData[23] == UINT8_MAX)
Expand All @@ -312,5 +316,27 @@ uint8_t MainStatusMessage::errorCode() const
}
return mData[23];
}
void MainStatusMessage::enableStatePV(bool enabled)
{
if (enabled)
{
mData[22] |= 0x10;
}
else
{
mData[22] &= ~0x10;
}
}
void MainStatusMessage::enableStateSolar(bool enabled)
{
if (enabled)
{
mData[22] |= 0x20;
}
else
{
mData[22] &= ~0x20;
}
}
} // namespace message
} // namespace aquamqtt
170 changes: 170 additions & 0 deletions AquaMQTT/src/state/MainStateProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include "state/MainStateProxy.h"

#include "config/Configuration.h"

namespace aquamqtt
{

MainStateProxy& MainStateProxy::getInstance()
{
static MainStateProxy instance;
return instance;
}

MainStateProxy::MainStateProxy()
: IMQTTCallback()
, mMutex(xSemaphoreCreateMutex())
, mNotify(nullptr)
, mPVModeHeatPump(false)
, mPVModeHeatElement(false)
{
}

void MainStateProxy::setListener(TaskHandle_t handle)
{
if (!xSemaphoreTake(mMutex, portMAX_DELAY))
{
return;
}

mNotify = handle;

xSemaphoreGive(mMutex);
}

void MainStateProxy::applyMainOverrides(uint8_t* buffer)
{
if (!xSemaphoreTake(mMutex, portMAX_DELAY))
{
return;
}

message::MainStatusMessage message(buffer);

// we only want to modify the message if a custom pv mode is active -> else leave state as it is
if (mPVModeHeatElement)
{
// let the hmi show the pv icon in case the heat element pv state is enabled
message.enableStatePV(true);
}

if (mPVModeHeatPump)
{
// let the hmi show the solar icon in case the heat element pv state is enabled
message.enableStateSolar(true);
}

xSemaphoreGive(mMutex);
}

bool MainStateProxy::copyFrame(uint8_t frameId, uint8_t* buffer)
{
if (frameId != aquamqtt::message::MAIN_MESSAGE_IDENTIFIER)
{
return aquamqtt::DHWState::getInstance().copyFrame(frameId, buffer);
}

bool hasMainMessage = aquamqtt::DHWState::getInstance().copyFrame(frameId, buffer);
if (hasMainMessage && aquamqtt::config::OPERATION_MODE == config::EOperationMode::MITM)
{
applyMainOverrides(buffer);
}
return hasMainMessage;
}

void MainStateProxy::onOperationModeChanged(std::unique_ptr<message::HMIOperationMode> value)
{
// noop
}

void MainStateProxy::onWaterTempTargetChanged(std::unique_ptr<float> value)
{
// noop
}

void MainStateProxy::onHeatingElementEnabledChanged(std::unique_ptr<bool> enabled)
{
// noop
}

void MainStateProxy::onEmergencyModeEnabledChanged(std::unique_ptr<bool> enabled)
{
// noop
}

void MainStateProxy::onPVModeHeatpumpEnabled(bool enabled)
{

if (!xSemaphoreTake(mMutex, portMAX_DELAY))
{
return;
}

mPVModeHeatPump = enabled;

// message 193 has changed
if (mNotify != nullptr)
{
xTaskNotifyIndexed(mNotify, 0, (1UL << 7UL), eSetBits);
}

xSemaphoreGive(mMutex);
}

void MainStateProxy::onPVModeHeatElementEnabled(bool enabled)
{
if (!xSemaphoreTake(mMutex, portMAX_DELAY))
{
return;
}

mPVModeHeatElement = enabled;

// message 193 has changed
if (mNotify != nullptr)
{
xTaskNotifyIndexed(mNotify, 0, (1UL << 7UL), eSetBits);
}

xSemaphoreGive(mMutex);
}

void MainStateProxy::onOperationTypeChanged(std::unique_ptr<message::HMIOperationType> type)
{
// noop
}

void MainStateProxy::onInstallationModeChanged(std::unique_ptr<message::HMIInstallation> mode)
{
// noop
}

void MainStateProxy::onResetOverrides()
{
// noop
}
AquaMqttMainOverrides MainStateProxy::getOverrides()
{
if (!xSemaphoreTake(mMutex, portMAX_DELAY))
{
return AquaMqttMainOverrides{};
}

AquaMqttMainOverrides retVal{};

if (mPVModeHeatPump)
{
retVal.solarState = true;
}

if (mPVModeHeatElement)
{
retVal.pvState = true;
}

xSemaphoreGive(mMutex);

return retVal;
}

} // namespace aquamqtt
Loading

0 comments on commit 9d7d306

Please sign in to comment.