Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add power devices menu #75

Merged
merged 11 commits into from
May 24, 2024
302 changes: 302 additions & 0 deletions assets/material/power_devices_img.c

Large diffs are not rendered by default.

230 changes: 230 additions & 0 deletions assets/material_46/power_devices_img.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions assets/material_svg/power_devices_img.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion src/init_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ void InitPanel::connected(KWebSocketClient &ws) {

});
}
});
});

ws.send_jsonrpc("machine.device_power.devices", [this](json& j) {
main_panel.get_tune_panel().get_power_panel().create_devices(j);
});
}

void InitPanel::disconnected(KWebSocketClient &ws) {
Expand Down
141 changes: 141 additions & 0 deletions src/power_panel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "power_panel.h"
#include "utils.h"
#include "spdlog/spdlog.h"

#include <map>

LV_IMG_DECLARE(back);

PowerPanel::PowerPanel(KWebSocketClient &websocket_client, std::mutex &l)
: ws(websocket_client)
, lv_lock(l)
, cont(lv_obj_create(lv_scr_act()))
, back_btn(cont, &back, "Back", &PowerPanel::_handle_callback, this)
{
lv_obj_move_background(cont);
lv_obj_set_size(cont, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);

lv_obj_add_flag(back_btn.get_container(), LV_OBJ_FLAG_FLOATING);
lv_obj_align(back_btn.get_container(), LV_ALIGN_BOTTOM_RIGHT, 0, 0);
}

PowerPanel::~PowerPanel() {
if (cont != NULL) {
lv_obj_del(cont);
cont = NULL;
}

devices.clear();
}

void PowerPanel::create_device(json &j) {
std::string name = j["device"].template get<std::string>();

lv_obj_t *power_device_toggle;
auto entry = devices.find(name);
if (entry == devices.end()) {
lv_obj_t *power_device_toggle_cont = lv_obj_create(cont);
lv_obj_set_size(power_device_toggle_cont, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(power_device_toggle_cont, 0, 0);

lv_obj_t *l = lv_label_create(power_device_toggle_cont);
lv_label_set_text(l, name.c_str());
lv_obj_align(l, LV_ALIGN_LEFT_MID, 0, 0);

power_device_toggle = lv_switch_create(power_device_toggle_cont);
lv_obj_align(power_device_toggle, LV_ALIGN_RIGHT_MID, 0, 0);

lv_obj_add_event_cb(power_device_toggle, &PowerPanel::_handle_callback,
LV_EVENT_VALUE_CHANGED, this);

devices.insert({name, power_device_toggle});
} else {
power_device_toggle = entry->second;
}

std::string status = j["status"].template get<std::string>();
spdlog::debug("Fetched initial status for power device {}: {}", name, status);

if (status == "on") {
lv_obj_add_state(power_device_toggle, LV_STATE_CHECKED);
} else {
lv_obj_clear_state(power_device_toggle, LV_STATE_CHECKED);
}
}

void PowerPanel::create_devices(json &j) {
std::lock_guard<std::mutex> lock(lv_lock);

if (j.contains("result")) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably need to clear the devices map here for when the printer re-initializes, so if any devices removed physically will also get removed from in the UI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. Do you know how I can remove existing UI widgets in LVGL? Simply clearing the map still leaves the UI widget on screen and causes duplicate entries.

json result = j["result"];
if (result.contains("devices")) {
json devices = result["devices"];
for (auto &device : devices.items()) {
create_device(device.value());
}
}
}
}

void PowerPanel::handle_device_callback(json &j) {
std::lock_guard<std::mutex> lock(lv_lock);

if (j.contains("result")) {
json result = j["result"];
for (auto &device : result.items()) {
auto entry = devices.find(device.key());
if (entry != devices.end()) {
std::string new_status = device.value();

spdlog::debug("Fetched new status for power device {}: {}", entry->first, new_status);

if (new_status == "on") {
lv_obj_add_state(entry->second, LV_STATE_CHECKED);
} else {
lv_obj_clear_state(entry->second, LV_STATE_CHECKED);
}
}
}
}
}

void PowerPanel::foreground() {
lv_obj_move_foreground(cont);

json params;
for (auto &device : devices) {
params[device.first] = 0; // value is ignored by moonraker
}
ws.send_jsonrpc("machine.device_power.status", params, [this](json& j) {
this->handle_device_callback(j);
});
}

void PowerPanel::handle_callback(lv_event_t *e) {
if (lv_event_get_code(e) == LV_EVENT_CLICKED) {
lv_obj_t *btn = lv_event_get_current_target(e);
if (btn == back_btn.get_container()) {
lv_obj_move_background(cont);
}
} else if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) {
lv_obj_t *obj = lv_event_get_target(e);
for (auto &device : devices) {
if (obj == device.second) {
bool turnOn = lv_obj_has_state(device.second, LV_STATE_CHECKED);
std::string status = turnOn ? "on" : "off";

spdlog::debug("Turning power device {} {}", device.first, status);

json params;
params["device"] = device.first;
params["action"] = status;
ws.send_jsonrpc("machine.device_power.post_device", params, [this](json& j) {
this->handle_device_callback(j);
});
break;
}
}
}
}
40 changes: 40 additions & 0 deletions src/power_panel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef __POWER_PANEL_H__
#define __POWER_PANEL_H__

#include "button_container.h"
#include "lvgl/lvgl.h"
#include "websocket_client.h"

#include <string>
#include <mutex>

class PowerPanel {
public:
PowerPanel(KWebSocketClient &ws, std::mutex &l);
~PowerPanel();

void create_devices(json &j);

void foreground();
void handle_callback(lv_event_t *event);

static void _handle_callback(lv_event_t *event) {
PowerPanel *panel = (PowerPanel*)event->user_data;
panel->handle_callback(event);
};

private:
void create_device(json &j);
void handle_device_callback(json &j);

KWebSocketClient &ws;
std::mutex &lv_lock;

lv_obj_t *cont;
ButtonContainer back_btn;

std::map<std::string, lv_obj_t*> devices;

};

#endif //__POWER_PANEL_H__
17 changes: 17 additions & 0 deletions src/printertune_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ LV_IMG_DECLARE(chart_img);

#ifndef ZBOLT
LV_IMG_DECLARE(belts_calibration_img);
LV_IMG_DECLARE(power_devices_img);
#else
LV_IMG_DECLARE(print);
#endif

PrinterTunePanel::PrinterTunePanel(KWebSocketClient &c, std::mutex &l, lv_obj_t *parent, FineTunePanel &finetune)
Expand All @@ -26,6 +29,7 @@ PrinterTunePanel::PrinterTunePanel(KWebSocketClient &c, std::mutex &l, lv_obj_t
, belts_calibration_panel(c, l)
, tmc_tune_panel(c)
, tmc_status_panel(c, l)
, power_panel(c, l)
, bedmesh_btn(cont, &bedmesh_img, "Bed Mesh", &PrinterTunePanel::_handle_callback, this)
, finetune_btn(cont, &fine_tune_img, "Fine Tune", &PrinterTunePanel::_handle_callback, this)
, inputshaper_btn(cont, &inputshaper_img, "Input Shaper", &PrinterTunePanel::_handle_callback, this)
Expand All @@ -37,6 +41,11 @@ PrinterTunePanel::PrinterTunePanel(KWebSocketClient &c, std::mutex &l, lv_obj_t
, limits_btn(cont, &limit_img, "Limits", &PrinterTunePanel::_handle_callback, this)
, tmc_tune_btn(cont, &motor_img, "TMC Autotune", &PrinterTunePanel::_handle_callback, this)
, tmc_status_btn(cont, &chart_img, "TMC Metrics", &PrinterTunePanel::_handle_callback, this)
#ifndef ZBOLT
, power_devices_btn(cont, &power_devices_img, "Power Devices", &PrinterTunePanel::_handle_callback, this)
#else
, power_devices_btn(cont, &print, "Power Devices", &PrinterTunePanel::_handle_callback, this)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just start using material icons for zbolt too when there's no zbolt equivalent.

#endif
{
lv_obj_move_background(cont);

Expand All @@ -61,6 +70,7 @@ PrinterTunePanel::PrinterTunePanel(KWebSocketClient &c, std::mutex &l, lv_obj_t
lv_obj_set_grid_cell(limits_btn.get_container(), LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_START, 2, 1);
lv_obj_set_grid_cell(tmc_tune_btn.get_container(), LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_START, 2, 1);
lv_obj_set_grid_cell(tmc_status_btn.get_container(), LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_START, 2, 1);
lv_obj_set_grid_cell(power_devices_btn.get_container(), LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_START, 2, 1);
// lv_obj_set_grid_cell(restart_firmware_btn.get_container(), LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_START, 2, 1);
}

Expand All @@ -79,6 +89,10 @@ BedMeshPanel& PrinterTunePanel::get_bedmesh_panel() {
return bedmesh_panel;
}

PowerPanel& PrinterTunePanel::get_power_panel() {
return power_panel;
}

void PrinterTunePanel::init(json &j) {
limits_panel.init(j);

Expand Down Expand Up @@ -123,6 +137,9 @@ void PrinterTunePanel::handle_callback(lv_event_t *event) {
} else if (btn == tmc_status_btn.get_container()) {
spdlog::trace("tmc metrics pressed");
tmc_status_panel.foreground();
} else if (btn == power_devices_btn.get_container()) {
spdlog::trace("power devices pressed");
power_panel.foreground();
}
}
}
4 changes: 4 additions & 0 deletions src/printertune_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "belts_calibration_panel.h"
#include "tmc_tune_panel.h"
#include "tmc_status_panel.h"
#include "power_panel.h"
#include "button_container.h"
#include "lvgl/lvgl.h"

Expand All @@ -19,6 +20,7 @@ class PrinterTunePanel {

lv_obj_t *get_container();
BedMeshPanel &get_bedmesh_panel();
PowerPanel &get_power_panel();
void init(json &j);
void handle_callback(lv_event_t *event);

Expand All @@ -36,13 +38,15 @@ class PrinterTunePanel {
BeltsCalibrationPanel belts_calibration_panel;
TmcTunePanel tmc_tune_panel;
TmcStatusPanel tmc_status_panel;
PowerPanel power_panel;
ButtonContainer bedmesh_btn;
ButtonContainer finetune_btn;
ButtonContainer inputshaper_btn;
ButtonContainer belts_calibration_btn;
ButtonContainer limits_btn;
ButtonContainer tmc_tune_btn;
ButtonContainer tmc_status_btn;
ButtonContainer power_devices_btn;

};

Expand Down
Loading