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
117 changes: 89 additions & 28 deletions src/charge_mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void charge_mode_wait_for_zero() {
// Generate stop condition
if (data_buffer.getCounter() >= 10){
if (data_buffer.getSd() < charge_mode_config.eeprom_charge_mode_data.set_point_sd_margin &&
abs(data_buffer.getMean()) < charge_mode_config.eeprom_charge_mode_data.set_point_mean_margin) {
fabsf(data_buffer.getMean()) < charge_mode_config.eeprom_charge_mode_data.set_point_mean_margin) {
break;
}
}
Expand Down Expand Up @@ -497,28 +497,67 @@ void charge_mode_wait_for_cup_return() {
}


void charge_mode_update_target_weight_from_digits() {
switch (charge_mode_config.eeprom_charge_mode_data.decimal_places) {
case DP_2:
charge_mode_config.target_charge_weight = charge_weight_digits[4] * 100 + \
charge_weight_digits[3] * 10 + \
charge_weight_digits[2] * 1 + \
charge_weight_digits[1] * 0.1 + \
charge_weight_digits[0] * 0.01;
break;
case DP_3:
charge_mode_config.target_charge_weight = charge_weight_digits[4] * 10 + \
charge_weight_digits[3] * 1 + \
charge_weight_digits[2] * 0.1 + \
charge_weight_digits[1] * 0.01 + \
charge_weight_digits[0] * 0.001;
break;
default:
charge_mode_config.target_charge_weight = 0;
break;
}
}

void charge_mode_load_digits_from_profile() {
profile_t *p = profile_get_selected();
float weight = p->last_charge_weight;

if (charge_mode_config.eeprom_charge_mode_data.decimal_places == DP_2) {
// DP_2 = 123.45 (charge_weight_digits[4] * 100 + [3] * 10 + [2] * 1 + [1] * 0.1 + [0] * 0.01)
int w = (int)(weight * 100.0f + 0.5f);
charge_weight_digits[4] = (w / 10000) % 10;
charge_weight_digits[3] = (w / 1000) % 10;
charge_weight_digits[2] = (w / 100) % 10;
charge_weight_digits[1] = (w / 10) % 10;
charge_weight_digits[0] = w % 10;
} else {
// DP_3 = 12.345 (charge_weight_digits[4] * 10 + [3] * 1 + [2] * 0.1 + [1] * 0.01 + [0] * 0.001)
int w = (int)(weight * 1000.0f + 0.5f);
charge_weight_digits[4] = (w / 10000) % 10;
charge_weight_digits[3] = (w / 1000) % 10;
charge_weight_digits[2] = (w / 100) % 10;
charge_weight_digits[1] = (w / 10) % 10;
charge_weight_digits[0] = w % 10;
}
}

void charge_mode_save_digits_to_profile() {
charge_mode_update_target_weight_from_digits();
profile_t *p = profile_get_selected();
p->last_charge_weight = charge_mode_config.target_charge_weight;
profile_data_save();
}

void charge_mode_update_weight_from_profile() {
profile_t *p = profile_get_selected();
charge_mode_config.target_charge_weight = p->last_charge_weight;
}

uint8_t charge_mode_menu(bool charge_mode_skip_user_input) {
// Create target weight, if the charge mode weight is built by charge_weight_digits
if (!charge_mode_skip_user_input) {
switch (charge_mode_config.eeprom_charge_mode_data.decimal_places) {
case DP_2:
charge_mode_config.target_charge_weight = charge_weight_digits[4] * 100 + \
charge_weight_digits[3] * 10 + \
charge_weight_digits[2] * 1 + \
charge_weight_digits[1] * 0.1 + \
charge_weight_digits[0] * 0.01;
break;
case DP_3:
charge_mode_config.target_charge_weight = charge_weight_digits[4] * 10 + \
charge_weight_digits[3] * 1 + \
charge_weight_digits[2] * 0.1 + \
charge_weight_digits[1] * 0.01 + \
charge_weight_digits[0] * 0.001;
break;
default:
charge_mode_config.target_charge_weight = 0;
break;
}
charge_mode_update_target_weight_from_digits();
}

// If the display task is never created then we shall create one, otherwise we shall resume the task
Expand Down Expand Up @@ -716,13 +755,20 @@ bool http_rest_charge_mode_state(struct fs_file *file, int num_params, char *par
// s4 (string): Profile Name
// s5 (string): Elapsed time in seconds, live during charging

static char charge_mode_json_buffer[160]; // Increased to fit s5
static char charge_mode_json_buffer[512]; // Increased to be safe
char elapsed_time_buffer[16] = {0};

// Control
for (int idx = 0; idx < num_params; idx += 1) {
if (strcmp(params[idx], "s0") == 0) {
charge_mode_config.target_charge_weight = strtof(values[idx], NULL);

// Save to profile
profile_t *p = profile_get_selected();
if (p) {
p->last_charge_weight = charge_mode_config.target_charge_weight;
profile_data_save();
}
}
else if (strcmp(params[idx], "s2") == 0) {
charge_mode_state_t new_state = (charge_mode_state_t) atoi(values[idx]);
Expand All @@ -746,19 +792,30 @@ bool http_rest_charge_mode_state(struct fs_file *file, int num_params, char *par
}
}

// Handle the special case
// Handle the special cases for JSON floats
float current_measurement = scale_get_current_measurement();
char weight_string[16];
if (isnanf(current_measurement)) {
sprintf(weight_string, "\"nan\"");
if (isnan(current_measurement)) {
sprintf(weight_string, "nan");
}
else if (isinff(current_measurement)) {
sprintf(weight_string, "\"inf\"");
else if (isinf(current_measurement)) {
sprintf(weight_string, "inf");
}
else {
sprintf(weight_string, "%0.3f", current_measurement);
}

char target_weight_string[16];
if (isnan(charge_mode_config.target_charge_weight)) {
sprintf(target_weight_string, "nan");
}
else if (isinf(charge_mode_config.target_charge_weight)) {
sprintf(target_weight_string, "inf");
}
else {
sprintf(target_weight_string, "%0.3f", charge_mode_config.target_charge_weight);
}

// Format elapsed time
if (charge_mode_config.charge_mode_state == CHARGE_MODE_WAIT_FOR_COMPLETE) {
TickType_t now = xTaskGetTickCount();
Expand All @@ -768,17 +825,21 @@ bool http_rest_charge_mode_state(struct fs_file *file, int num_params, char *par
snprintf(elapsed_time_buffer, sizeof(elapsed_time_buffer), "%.2f", last_charge_elapsed_seconds);
}

// Safely get profile name
profile_t *selected_profile = profile_get_selected();
const char *profile_name = (selected_profile != NULL) ? selected_profile->name : "Unknown";

// Response
snprintf(charge_mode_json_buffer,
sizeof(charge_mode_json_buffer),
"%s"
"{\"s0\":%0.3f,\"s1\":%s,\"s2\":%d,\"s3\":%lu,\"s4\":\"%s\",\"s5\":\"%s\"}",
"{\"s0\":%0.3f,\"s1\":\"%s\",\"s2\":%d,\"s3\":%lu,\"s4\":\"%s\",\"s5\":\"%s\"}",
http_json_header,
charge_mode_config.target_charge_weight,
weight_string,
(int) charge_mode_config.charge_mode_state,
charge_mode_config.charge_mode_event,
profile_get_selected()->name,
profile_name,
elapsed_time_buffer);

// Clear events
Expand Down
4 changes: 4 additions & 0 deletions src/charge_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ bool charge_mode_config_init(void);
uint8_t charge_mode_menu(bool charge_mode_skip_user_input);
bool charge_mode_config_save(void);

void charge_mode_load_digits_from_profile();
void charge_mode_save_digits_to_profile();
void charge_mode_update_weight_from_profile();

// REST interface
bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *params[], char *values[]);
bool http_rest_charge_mode_state(struct fs_file *file, int num_params, char *params[], char *values[]);
Expand Down
2 changes: 2 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ bool string_to_boolean(char * s);

int float_to_string(char * output_decimal_str, float var, decimal_places_t decimal_places);

uint32_t software_crc32(void * data, size_t length);

/**
* @brief Load configuration from persistent storage.
*/
Expand Down
53 changes: 35 additions & 18 deletions src/html/web_portal.html
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,8 @@ <h3 class="font-bold text-lg">Error</h3>
});

var pollSetTimeoutId;
var lastProfileNameOnServer = "";
var lastChargeWeightOnServer = -1;

// Set Charge Mode Set Point with REST interface
function setChargeWeight() {
Expand All @@ -980,9 +982,10 @@ <h3 class="font-bold text-lg">Error</h3>
fetch(uri)
.then(response => {
_restartPoll(); // Start the poll immediately to update the charge status
return response.json();
})
.catch(error => {
console.error("Error setting charge weight");
console.error("Error setting charge weight:", error);
});
}

Expand All @@ -1002,9 +1005,10 @@ <h3 class="font-bold text-lg">Error</h3>
fetch(uri)
.then(response => {
_restartPoll(); // Start the poll immediately to update the charge status
return response.json();
})
.catch(error => {
console.error("Error setting charge mode status");
console.error("Error setting charge mode status:", error);
});
}

Expand Down Expand Up @@ -1057,7 +1061,7 @@ <h3 class="font-bold text-lg">Error</h3>
currentWeightDecimal.innerText = String(weight);

var currentWeightProgressPencentage = document.getElementById("currentWeightProgressPencentage");
currentWeightProgressPencentage.value = percentage;
currentWeightProgressPencentage.value = isFinite(percentage) ? percentage : 0;
}

function _setStartStopButtonWidget(isStart) {
Expand Down Expand Up @@ -1129,32 +1133,43 @@ <h3 class="font-bold text-lg">Error</h3>
function pollChargeModeStatus() {
fetch("/rest/charge_mode_state")
.then(response => {
return response.json()
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// console.log(data);
// Parse data
const charge_weight_set_point = data["s0"];
const current_charge_weight = data["s1"];
const charge_weight_set_point = parseFloat(data["s0"]);
const current_charge_weight = parseFloat(data["s1"]);
const charge_mode_state = data["s2"];
const charge_mode_event = data["s3"];
const profile_name = data["s4"];
const charge_time_seconds = data["s5"] || "-.--";

var percentage = 0;
if (charge_weight_set_point == 0) {
percentage = 0;
}
else {
if (isFinite(charge_weight_set_point) && charge_weight_set_point != 0) {
percentage = current_charge_weight / charge_weight_set_point * 100.0;
}

// Update web element
_setCurrentWeight(current_charge_weight, percentage);
_setCurrentWeight(data["s1"], percentage);
_setChargeModeStateWidget(charge_mode_state);

profileName = document.getElementById("profileName");
profileName.innerText = String(profile_name);
// Update charge weight input if profile changed or weight changed on server
if (profile_name !== lastProfileNameOnServer || Math.abs(charge_weight_set_point - lastChargeWeightOnServer) > 0.0001) {
// Only update if the user isn't currently focusing the input
if (document.activeElement.id !== "chargeWeightInput") {
document.getElementById("chargeWeightInput").value = charge_weight_set_point;
}
lastProfileNameOnServer = profile_name;
lastChargeWeightOnServer = charge_weight_set_point;
}

const profileNameElement = document.getElementById("profileName");
if (profileNameElement) {
profileNameElement.innerText = String(profile_name);
}

// Find the charge time element and update its text content
const chargeTimeElement = document.getElementById('chargeTimeValue');
Expand All @@ -1180,14 +1195,16 @@ <h3 class="font-bold text-lg">Error</h3>
}

// Show modal
const dialogModal = document.getElementById(dialog_name);
if (dialogModal) {
dialogModal.showModal();
if (dialog_name) {
const dialogModal = document.getElementById(dialog_name);
if (dialogModal) {
dialogModal.showModal();
}
}
}
})
.catch(error => {
console.error("Error reading charge mode settings");
console.error("Error reading charge mode settings:", error);
_setCurrentWeight("---", 0);
_setChargeModeStateWidget(ChargeModeState.WAIT);
})
Expand Down
29 changes: 27 additions & 2 deletions src/mui_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ uint8_t render_charge_mode_next_button(mui_t * ui, uint8_t msg) {
case MUIF_MSG_VALUE_INCREMENT:
case MUIF_MSG_VALUE_DECREMENT:
mui_SaveForm(ui);

// Load last charge weight from profile to digits
charge_mode_load_digits_from_profile();

if (charge_mode_config.eeprom_charge_mode_data.decimal_places == DP_2) {
ui->arg = 11; // goto form 11
}
Expand All @@ -165,6 +169,26 @@ uint8_t render_charge_mode_next_button(mui_t * ui, uint8_t msg) {
}


uint8_t render_charge_weight_next_button(mui_t * ui, uint8_t msg) {
switch (msg) {
case MUIF_MSG_CURSOR_SELECT:
case MUIF_MSG_VALUE_INCREMENT:
case MUIF_MSG_VALUE_DECREMENT:
mui_SaveForm(ui);

// Save digits to profile
charge_mode_save_digits_to_profile();

return mui_GotoFormAutoCursorPosition(ui, ui->arg);
default:
mui_u8g2_btn_goto_wm_fi(ui, msg);
break;
}

return 0;
}


uint8_t render_profile_misc_details(mui_t *ui, uint8_t msg) {
switch(msg)
{
Expand Down Expand Up @@ -253,6 +277,7 @@ muif_t muif_list[] = {
MUIF_BUTTON("BN", mui_u8g2_btn_goto_wm_fi),

MUIF_BUTTON("B1", render_charge_mode_next_button),
MUIF_BUTTON("B2", render_charge_weight_next_button),

// Leave
MUIF_VARIABLE("LV", &exit_state, mui_u8g2_btn_exit_wm_fi),
Expand Down Expand Up @@ -334,7 +359,7 @@ fds_t fds_data[] = {
MUI_XY("SU", 106, 35)

MUI_STYLE(0)
MUI_XYAT("BN",115, 59, 13, "Next")
MUI_XYAT("B2",115, 59, 13, "Next")
MUI_XYAT("BN",14, 59, 10, "Back")

MUI_STYLE(3)
Expand All @@ -357,7 +382,7 @@ fds_t fds_data[] = {
MUI_XY("SU", 106, 35)

MUI_STYLE(0)
MUI_XYAT("BN",115, 59, 13, "Next")
MUI_XYAT("B2",115, 59, 13, "Next")
MUI_XYAT("BN",14, 59, 10, "Back")

MUI_STYLE(3)
Expand Down
Loading