diff --git a/main/include/nconfig.h b/main/include/nconfig.h
index 493a0e8..dc880df 100644
--- a/main/include/nconfig.h
+++ b/main/include/nconfig.h
@@ -44,6 +44,7 @@ enum nconfig_type
USB_CURRENT_LIMIT, ///< The maximum current limit for the USB out.
PAGE_USERNAME, ///< Webpage username
PAGE_PASSWORD, ///< Webpage password
+ SENSOR_PERIOD_MS, ///< Sensor period
NCONFIG_TYPE_MAX, ///< Sentinel for the maximum number of configuration types.
};
diff --git a/main/nconfig/nconfig.c b/main/nconfig/nconfig.c
index 0f65043..3bc97df 100644
--- a/main/nconfig/nconfig.c
+++ b/main/nconfig/nconfig.c
@@ -30,6 +30,7 @@ const static char* keys[NCONFIG_TYPE_MAX] = {
[USB_CURRENT_LIMIT] = "usb_climit",
[PAGE_USERNAME] = "username",
[PAGE_PASSWORD] = "password",
+ [SENSOR_PERIOD_MS] = "sensor_period",
};
struct default_value
@@ -54,6 +55,7 @@ struct default_value const default_values[] = {
{USB_CURRENT_LIMIT, "3.0"},
{PAGE_USERNAME, "admin"},
{PAGE_PASSWORD, "password"},
+ {SENSOR_PERIOD_MS, "1000"},
};
esp_err_t init_nconfig()
diff --git a/main/service/monitor.c b/main/service/monitor.c
index 7469dd0..fe1ac09 100644
--- a/main/service/monitor.c
+++ b/main/service/monitor.c
@@ -289,6 +289,25 @@ void init_status_monitor()
xTaskCreate(shutdown_load_sw_task, "shutdown_sw_task", configMINIMAL_STACK_SIZE * 3, NULL, 15,
&shutdown_task_handle);
- ESP_ERROR_CHECK(esp_timer_start_periodic(sensor_timer, 1000000));
+ nconfig_read(SENSOR_PERIOD_MS, buf, sizeof(buf));
+ ESP_ERROR_CHECK(esp_timer_start_periodic(sensor_timer, strtol(buf, NULL, 10) * 1000));
ESP_ERROR_CHECK(esp_timer_start_periodic(wifi_status_timer, 1000000 * 5));
}
+
+esp_err_t update_sensor_period(int period)
+{
+ if (period < 500 || period > 10000) // 0.5 sec ~ 10 sec
+ {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ char buf[10];
+ sprintf(buf, "%d", period);
+ esp_err_t err = nconfig_write(SENSOR_PERIOD_MS, buf);
+ if (err != ESP_OK) {
+ return err;
+ }
+
+ esp_timer_stop(sensor_timer);
+ return esp_timer_start_periodic(sensor_timer, period * 1000);
+}
\ No newline at end of file
diff --git a/main/service/monitor.h b/main/service/monitor.h
index 138b165..72e6966 100644
--- a/main/service/monitor.h
+++ b/main/service/monitor.h
@@ -20,5 +20,6 @@ typedef struct
} sensor_data_t;
void init_status_monitor();
+esp_err_t update_sensor_period(int period);
#endif // ODROID_REMOTE_HTTP_MONITOR_H
diff --git a/main/service/setting.c b/main/service/setting.c
index cddd0fc..ac9504a 100644
--- a/main/service/setting.c
+++ b/main/service/setting.c
@@ -6,6 +6,7 @@
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_timer.h"
+#include "monitor.h"
#include "nconfig.h"
#include "webserver.h"
#include "wifi.h"
@@ -47,6 +48,11 @@ static esp_err_t setting_get_handler(httpd_req_t* req)
cJSON_AddStringToObject(root, "baudrate", buf);
}
+ if (nconfig_read(SENSOR_PERIOD_MS, buf, sizeof(buf)) == ESP_OK)
+ {
+ cJSON_AddStringToObject(root, "period", buf);
+ }
+
// Add current limits to the response
if (nconfig_read(VIN_CURRENT_LIMIT, buf, sizeof(buf)) == ESP_OK)
{
@@ -174,6 +180,7 @@ static esp_err_t setting_post_handler(httpd_req_t* req)
cJSON* net_type_item = cJSON_GetObjectItem(root, "net_type");
cJSON* ssid_item = cJSON_GetObjectItem(root, "ssid");
cJSON* baud_item = cJSON_GetObjectItem(root, "baudrate");
+ cJSON* period_item = cJSON_GetObjectItem(root, "period");
cJSON* vin_climit_item = cJSON_GetObjectItem(root, "vin_current_limit");
cJSON* main_climit_item = cJSON_GetObjectItem(root, "main_current_limit");
cJSON* usb_climit_item = cJSON_GetObjectItem(root, "usb_current_limit");
@@ -289,6 +296,13 @@ static esp_err_t setting_post_handler(httpd_req_t* req)
change_baud_rate(strtol(baudrate, NULL, 10));
httpd_resp_sendstr(req, "{\"status\":\"baudrate_updated\"}");
}
+ else if (period_item && cJSON_IsString(period_item))
+ {
+ const char* period_str = period_item->valuestring;
+ ESP_LOGI(TAG, "Received period set request: %s", period_str);
+ update_sensor_period(strtol(period_str, NULL, 10));
+ httpd_resp_sendstr(req, "{\"status\":\"period_updated\"}");
+ }
else if (vin_climit_item || main_climit_item || usb_climit_item)
{
char num_buf[10];
diff --git a/page/index.html b/page/index.html
index 0290287..63246a1 100644
--- a/page/index.html
+++ b/page/index.html
@@ -359,7 +359,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -380,7 +390,6 @@
-
diff --git a/page/src/api.js b/page/src/api.js
index 9c302ee..aac1317 100644
--- a/page/src/api.js
+++ b/page/src/api.js
@@ -104,7 +104,6 @@ export async function postNetworkSettings(payload) {
* Posts the selected UART baud rate to the server.
* @param {string} baudrate The selected baud rate.
* @returns {Promise
} A promise that resolves to the raw fetch response.
- * @throws {Error} Throws an error if the request fails.
*/
export async function postBaudRateSetting(baudrate) {
const response = await fetch('/api/setting', {
@@ -113,7 +112,24 @@ export async function postBaudRateSetting(baudrate) {
'Content-Type': 'application/json',
...getAuthHeaders(),
},
- body: JSON.stringify({baudrate}),
+ body: JSON.stringify({ baudrate }),
+ });
+ return await handleResponse(response);
+}
+
+/**
+ * Posts the selected sensor period to the server.
+ * @param {string} period The selected period in milliseconds.
+ * @returns {Promise} A promise that resolves to the raw fetch response.
+ */
+export async function postPeriodSetting(period) {
+ const response = await fetch('/api/setting', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ ...getAuthHeaders(),
+ },
+ body: JSON.stringify({ period }),
});
return await handleResponse(response);
}
diff --git a/page/src/dom.js b/page/src/dom.js
index 0e1e420..f5af806 100644
--- a/page/src/dom.js
+++ b/page/src/dom.js
@@ -76,6 +76,9 @@ export const apPasswordInput = document.getElementById('ap-password');
// --- Device Settings Elements ---
export const baudRateSelect = document.getElementById('baud-rate-select');
export const baudRateApplyButton = document.getElementById('baud-rate-apply-button');
+export const periodSlider = document.getElementById('period-slider');
+export const periodValue = document.getElementById('period-value');
+export const periodApplyButton = document.getElementById('period-apply-button');
export const rebootButton = document.getElementById('reboot-button');
// --- Current Limit Settings Elements ---
diff --git a/page/src/events.js b/page/src/events.js
index 75edcea..2f0bad0 100644
--- a/page/src/events.js
+++ b/page/src/events.js
@@ -77,8 +77,9 @@ export function setupEventListeners() {
dom.networkApplyButton.addEventListener('click', ui.applyNetworkSettings);
dom.apModeApplyButton.addEventListener('click', ui.applyApModeSettings);
dom.baudRateApplyButton.addEventListener('click', ui.applyBaudRateSettings);
+ dom.periodApplyButton.addEventListener('click', ui.applyPeriodSettings);
- // --- Device Settings (Reboot) ---
+ // --- Device Settings (Reboot & Period Slider) ---
if (dom.rebootButton) {
dom.rebootButton.addEventListener('click', () => {
if (confirm('Are you sure you want to reboot the device?')) {
@@ -101,6 +102,12 @@ export function setupEventListeners() {
});
}
+ if (dom.periodSlider) {
+ dom.periodSlider.addEventListener('input', () => {
+ dom.periodValue.textContent = dom.periodSlider.value;
+ });
+ }
+
// --- Current Limit Settings ---
dom.vinSlider.addEventListener('input', () => updateSliderValue(dom.vinSlider, dom.vinValueSpan));
dom.mainSlider.addEventListener('input', () => updateSliderValue(dom.mainSlider, dom.mainValueSpan));
diff --git a/page/src/ui.js b/page/src/ui.js
index 0749393..4819917 100644
--- a/page/src/ui.js
+++ b/page/src/ui.js
@@ -301,6 +301,24 @@ export async function applyBaudRateSettings() {
}
}
+/**
+ * Applies the selected sensor period by sending it to the server.
+ */
+export async function applyPeriodSettings() {
+ const period = dom.periodSlider.value;
+ dom.periodApplyButton.disabled = true;
+ dom.periodApplyButton.innerHTML = ` Applying...`;
+
+ try {
+ await api.postPeriodSetting(period);
+ } catch (error) {
+ console.error('Error applying period:', error);
+ } finally {
+ dom.periodApplyButton.disabled = false;
+ dom.periodApplyButton.innerHTML = 'Apply';
+ }
+}
+
/**
* Fetches and displays the current network and device settings in the settings modal.
*/
@@ -338,6 +356,10 @@ export async function initializeSettings() {
if (data.baudrate) {
dom.baudRateSelect.value = data.baudrate;
}
+ if (data.period) {
+ dom.periodSlider.value = data.period;
+ dom.periodValue.textContent = data.period;
+ }
} catch (error) {
console.error('Error initializing settings:', error);