Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/display/core/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ void Settings::setEmptyTankDistance(int empty_tank_distance) { emptyTankDistance
void Settings::setFullTankDistance(int full_tank_distance) { fullTankDistance.set(full_tank_distance); }

void Settings::setAltRelayFunction(int alt_relay_function) { altRelayFunction.set(alt_relay_function); }
void Settings::setShowWaterLevelDot(bool show) { showWaterLevelDot.set(show); }

void Settings::setAutoWakeupEnabled(bool enabled) { autowakeupEnabled.set(enabled); }

Expand Down
3 changes: 3 additions & 0 deletions src/display/core/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class Settings {
int getEmptyTankDistance() const { return emptyTankDistance.get(); }
int getFullTankDistance() const { return fullTankDistance.get(); }
int getAltRelayFunction() const { return altRelayFunction.get(); }
bool isShowWaterLevelDot() const { return showWaterLevelDot.get(); }
bool isAutoWakeupEnabled() const { return autowakeupEnabled.get(); }
std::vector<AutoWakeupSchedule> getAutoWakeupSchedules() const { return autowakeupSchedules.get(); }
String getButtonBehavior(int index) const {
Expand Down Expand Up @@ -225,6 +226,7 @@ class Settings {
void setEmptyTankDistance(int empty_tank_distance);
void setFullTankDistance(int full_tank_distance);
void setAltRelayFunction(int alt_relay_function);
void setShowWaterLevelDot(bool show);
void setAutoWakeupEnabled(bool enabled);
void setAutoWakeupSchedules(const std::vector<AutoWakeupSchedule> &schedules);
void setButtonBehavior(int index, String behavior);
Expand Down Expand Up @@ -305,6 +307,7 @@ class Settings {
Property<int> emptyTankDistance{registry, "sr_ed", 210};
Property<int> fullTankDistance{registry, "sr_fd", 30};

Property<bool> showWaterLevelDot{registry, "wld", true};
Property<int> altRelayFunction{registry, "alt_relay", ALT_RELAY_GRIND}; // Default to grind
Property<std::vector<String>> buttonBehavior{registry, "btnb", {"brew", "steam", "water"}};

Expand Down
2 changes: 2 additions & 0 deletions src/display/plugins/WebUIPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ void WebUIPlugin::handleSettings(AsyncWebServerRequest *request) const {
settings->setEmptyTankDistance(request->arg("emptyTankDistance").toInt());
if (request->hasArg("fullTankDistance"))
settings->setFullTankDistance(request->arg("fullTankDistance").toInt());
settings->setShowWaterLevelDot(request->hasArg("showWaterLevelDot"));
if (request->hasArg("altRelayFunction"))
settings->setAltRelayFunction(request->arg("altRelayFunction").toInt());
if (request->hasArg("buttonBehavior"))
Expand Down Expand Up @@ -856,6 +857,7 @@ void WebUIPlugin::handleSettings(AsyncWebServerRequest *request) const {
doc["emptyTankDistance"] = settings.getEmptyTankDistance();
doc["fullTankDistance"] = settings.getFullTankDistance();
doc["altRelayFunction"] = settings.getAltRelayFunction();
doc["showWaterLevelDot"] = settings.isShowWaterLevelDot();
// Add auto-wakeup settings to response
doc["autowakeupEnabled"] = settings.isAutoWakeupEnabled();
doc["buttonBehavior"] = implode(settings.getButtonBehaviorList(), ",");
Expand Down
62 changes: 62 additions & 0 deletions src/display/ui/default/DefaultUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ void DefaultUI::loop() {
updateTempStableFlag();

updateState();
updateWaterDot();
// Fill the EEZ data models before handleScreenChange() creates/ticks a screen (undefined fields abort the flow).
updateSystemStatus();
updateProfileInfo();
Expand Down Expand Up @@ -507,6 +508,8 @@ void DefaultUI::updateState() {
currentTemp = static_cast<int>(controller->getCurrentTemp());
targetTemp = static_cast<int>(controller->getTargetTemp());
pressureAvailable = controller->getSystemInfo().capabilities.pressure ? 1 : 0;
tofAvailable = controller->getSystemInfo().capabilities.tof;
waterLevel = tofAvailable ? controller->getWaterLevel() : 0;
wifiConnected = WiFi.status() == WL_CONNECTED;
grindAvailable = settings.isSmartGrindActive() || settings.getAltRelayFunction() == ALT_RELAY_GRIND;

Expand Down Expand Up @@ -690,6 +693,65 @@ void DefaultUI::updateBrewProcess() {

void DefaultUI::updateMenuScreen() {}

static uint32_t parseHexColor(const String &hex) { return strtol(hex.c_str() + 1, nullptr, 16); }

static lv_obj_t *createWaterDot(lv_obj_t *parent, int y) {
lv_obj_t *dot = lv_obj_create(parent);
lv_obj_set_size(dot, 14, 14);
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_border_width(dot, 0, 0);
lv_obj_set_style_pad_all(dot, 0, 0);
lv_obj_align(dot, LV_ALIGN_CENTER, 0, y);
return dot;
}

void DefaultUI::updateWaterDot() {
if (!tofAvailable || !controller->getSettings().isShowWaterLevelDot()) {
if (waterDot != nullptr) {
lv_obj_del(waterDot);
waterDot = nullptr;
}
if (waterDotMenu != nullptr) {
lv_obj_del(waterDotMenu);
waterDotMenu = nullptr;
}
return;
}
lv_obj_t *scr = lv_scr_act();
if (currentScreen == SCREEN_ID_MENU_SCREEN_NEW || currentScreen == SCREEN_ID_INFO_SCREEN ||
currentScreen == SCREEN_ID_PROFILE_SCREEN) {
waterDot = nullptr;
if (waterDotMenu == nullptr || !lv_obj_is_valid(waterDotMenu)) {
waterDotMenu = createWaterDot(scr, -230);
}
lv_color_t color =
lv_color_hex(controller->isLowWaterLevel() ? parseHexColor(controller->getSettings().getSunriseError())
: parseHexColor(controller->getSettings().getSunriseIdle()));
lv_obj_set_style_bg_color(waterDotMenu, color, 0);
lv_obj_set_style_bg_opa(waterDotMenu, LV_OPA_COVER, 0);
} else if (currentScreen == SCREEN_ID_BREW_SCREEN || currentScreen == SCREEN_ID_STEAM_SCREEN ||
currentScreen == SCREEN_ID_WATER_SCREEN) {
waterDotMenu = nullptr;
if (waterDot == nullptr || !lv_obj_is_valid(waterDot)) {
waterDot = createWaterDot(scr, -230);
}
lv_color_t color =
lv_color_hex(controller->isLowWaterLevel() ? parseHexColor(controller->getSettings().getSunriseError())
: parseHexColor(controller->getSettings().getSunriseIdle()));
lv_obj_set_style_bg_color(waterDot, color, 0);
lv_obj_set_style_bg_opa(waterDot, LV_OPA_COVER, 0);
} else {
if (waterDot != nullptr) {
lv_obj_del(waterDot);
waterDot = nullptr;
}
if (waterDotMenu != nullptr) {
lv_obj_del(waterDotMenu);
waterDotMenu = nullptr;
}
}
}

String DefaultUI::getErrorMessage() {
if (controller->isUpdating()) {
return "Updating...";
Expand Down
6 changes: 6 additions & 0 deletions src/display/ui/default/DefaultUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class DefaultUI {
void updateBoiler();
void updateBrewProcess();
void updateMenuScreen();
void updateWaterDot();
String getErrorMessage();

void adjustDials(lv_obj_t *dials);
Expand Down Expand Up @@ -133,6 +134,11 @@ class DefaultUI {
Value grindWeightTarget = FloatValue(18.0);
Value grindTimeTarget = StringValue("0:15");

int waterLevel = 0;
bool tofAvailable = false;
lv_obj_t *waterDot = nullptr;
lv_obj_t *waterDotMenu = nullptr;

int profileDirty = 0;
int currentProfileIdx = 0;
int profileLoaded = 0;
Expand Down
2 changes: 2 additions & 0 deletions web/src/pages/Settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ function buildSubmitFormData(formData, autowakeupSchedules, restart) {
'clock24hFormat',
'autowakeupEnabled',
'smartGrindToggle',
'showWaterLevelDot',
];

for (const [key, value] of Object.entries(formData)) {
Expand Down Expand Up @@ -262,6 +263,7 @@ export function Settings() {
'delayAdjust',
'clock24hFormat',
'autowakeupEnabled',
'showWaterLevelDot',
].includes(key)
) {
value = !formData[key];
Expand Down
10 changes: 9 additions & 1 deletion web/src/pages/Settings/tabs/MachineTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Section from '../../../components/Card.jsx';
import { Tooltip } from '../../../components/Tooltip.jsx';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCrosshairs } from '@fortawesome/free-solid-svg-icons/faCrosshairs';
import { InputGroupField, SettingsFormField } from '../../../components/SettingsFormField.jsx';
import { InputGroupField, SettingsFormField, ToggleField } from '../../../components/SettingsFormField.jsx';

const ledControl = computed(() => machine.value.capabilities.ledControl);
const pressureAvailable = computed(() => machine.value.capabilities.pressure);
Expand Down Expand Up @@ -314,6 +314,14 @@ export function MachineTab({ formData, onChange, setField }) {
onChange={onChange('sunriseExtBrightness')}
/>
</SettingsFormField>
<div className='mt-6'>
<ToggleField
label='Show Water Level Dot on Gaggimate Display'
htmlFor='showWaterLevelDot'
checked={!!formData.showWaterLevelDot}
onChange={onChange('showWaterLevelDot')}
/>
</div>
<div className='border-base-content/5 mt-6 grid grid-cols-1 gap-4 border-t pt-6 md:grid-cols-2'>
<TankDistanceField
id='emptyTankDistance'
Expand Down