diff --git a/webserver/preferences.html b/webserver/preferences.html index d5f38c5..b23e024 100644 --- a/webserver/preferences.html +++ b/webserver/preferences.html @@ -58,34 +58,42 @@

CO2 Gadget Preferences

Connectivity
- - ℹ️ Should the device connect to a WiFi network? +
+ + +
- - ℹ️ Should the device use the Bluetooth Low Energy (BLE) connection? Use with Sensirion's MyAmbiance App or others. +
+ + +
- - ℹ️ Should the device use the MQTT connection? Use with Home Assistant or others. If not used, disable to save energy and resources. Needs WiFi to activate. +
+ + +
- - ℹ️ Should the device use the ESP-NOW connection? Use with other ESP32 devices. If not used, disable to save energy and resources. +
+ + +
@@ -95,102 +103,110 @@

CO2 Gadget Preferences

WiFi Credentials
- - ℹ️ The name of your WiFi network. + +
- - ℹ️ The password for your WiFi network. Disabled for security reasons. + +
Host Name
- - ℹ️ The hostname of the device on the network. + +
Fixed IP
- - ℹ️ Use a fixed IP address for the device. This is useful for devices that need to be accessed by a fixed IP address. +
+ +
-
+
+
- - ℹ️ The fixed IP address for the device. + +
- - ℹ️ The gateway IP address for the device. + +
- - ℹ️ The subnet mask for the device. + +
- - ℹ️ The primary DNS server for the device. + +
- - ℹ️ The secondary DNS server for the device. + +
@@ -202,62 +218,64 @@

CO2 Gadget Preferences

MQTT Configuration
- - ℹ️ The client ID for the MQTT connection. Must be unique for each device. + +
- - ℹ️ The root topic for the MQTT connection. All MQTT messages will be published under this topic. + +
- - ℹ️ The MQTT broker address. Use the IP address or hostname of the MQTT broker. + +
- - ℹ️ The user name for the MQTT connection. Leave empty if not used. + +
- - ℹ️ The password for the MQTT connection. Leave empty if not used. Disabled for security reasons. + +
- - ℹ️ Time between MQTT publish events. Lower values will increase the frequency of MQTT messages. + +
- - ℹ️ Time to keep the MQTT connection alive. Lower values may cause the connection to drop. + +
- - ℹ️ Show MQTT messages in the serial console. Useful for debugging MQTT connections. +
+ + +
@@ -268,41 +286,41 @@

CO2 Gadget Preferences

ESP-NOW Configuration
- - ℹ️ The channel for the ESP-NOW connection. Must be the same for all devices. + +
- - ℹ️ The board ID for the ESP-NOW connection. Must be unique for each device. + +
- - ℹ️ The address of the peer device for the ESP-NOW connection. Must be unique for each device. + +
- - ℹ️ Time between ESPNOW publish events. Lower values will increase the frequency of ESPNOW messages. + +
- - ℹ️ Time to keep the ESPNOW connection alive. Lower values may cause the connection to drop. + +
@@ -315,41 +333,44 @@

CO2 Gadget Preferences

CO2 Sensor -
- - +
ℹ️ - Custom calibration value for the CO2 sensor. This value is + Custom calibration value for the CO2 sensor. This value is used to adjust the sensor readings. Set to ~415 to calibrate the sensor to outdoor air. Use with caution. + + +
+
-
- - ℹ️ Enable automatic self-calibration of the CO2 sensor. Not recommended if the sensor is not exposed to fresh air (~420ppm) at least once a week. +
+ + +
- - ℹ️ CO2 level to be considered "warning". + +
- - ℹ️ CO2 level to be considered "danger". + +
@@ -357,18 +378,20 @@

CO2 Gadget Preferences

Temperature Sensor
- - ℹ️ Offset value to adjust the temperature readings. Use this value to calibrate the temperature sensor. For Sensirion sensors, this value is deducted from the temperature readings. Takes a while to update. + +
- - ℹ️ Show temperature readings in Fahrenheit instead of Celsius. +
+ + +
@@ -376,26 +399,28 @@

CO2 Gadget Preferences

Barometer Sensor
- - ℹ️ Altitude in meters above sea level. This value is used to adjust CO2 based on the barometric pressure for Sensirion sensors. + +
- - ℹ️ Interval between sensor readings. Lower values will increase the frequency of sensor readings. + +
- - ℹ️ Enable debug output for the sensors. This will print sensor data to the serial console. +
+ + +
@@ -407,19 +432,19 @@

CO2 Gadget Preferences

NeoPixel
- - ℹ️ Set the brightness of the NeoPixel. Lower values will decrease the brightness of the NeoPixel. + +
- - ℹ️ The type of NeoPixel used. 0 = NEO_GRB + NEO_KHZ800, 1 = NEO_RGB + NEO_KHZ800, 2 = NEO_RGBW + NEO_KHZ800. + +
@@ -428,8 +453,10 @@

CO2 Gadget Preferences

Buzzer
- - @@ -440,36 +467,36 @@

CO2 Gadget Preferences

- ℹ️ - Time between buzzer beeps. Set to OFF to disable the buzzer.
- - - ℹ️ - The tone of the buzzer beep. Higher values will increase the pitch of the beep.
- - - ℹ️ - The duration of the buzzer beep. Longer values will increase the duration of the beep.
- - ℹ️ Check this box if you are using a relay to control the GPIO outputs. This will adjust the logic of the outputs. +
+ + +
@@ -478,29 +505,28 @@

CO2 Gadget Preferences

Battery
- - ℹ️ - The voltage at which the battery is considered discharged. Used to calculate the battery + The voltage (in Millivolts) at which the battery is considered discharged. Used to calculate the battery level. + +
- - ℹ️ - The voltage at which the battery is considered fully charged. Used to calculate the battery + The voltage (in Millivolts) at which the battery is considered fully charged. Used to calculate the battery level. You should have a very good reason to modify this value. + +
- - - 0 Volts ℹ️ - The reference voltage for the battery level calculation. Used to calculate the battery + The reference voltage (in Millivolts) for the battery level calculation. Used to calculate the battery level. Must be set so that the battery voltage is shown correctly. If you don't have a multimeter, connect a fully charged battery and set this value to read 4.20 Volts. + +
@@ -509,60 +535,70 @@

CO2 Gadget Preferences

Display Preferences
- - ℹ️ Show temperature readings on the display. +
+ + +
- - ℹ️ Show humidity readings on the display. +
+ + +
- - ℹ️ Show battery level on the display. +
+ + +
- - ℹ️ Time to turn off the display after the last button press. Set to 0 to disable this feature. + +
- - ℹ️ Turn off the display when USB power is detected. +
+ + +
- - ℹ️ Reverse the display orientation. +
+ + +
- + ℹ️ + Set the display brightness. Lower values will decrease the brightness of the display. + - ℹ️ - Set the display brightness. Lower values will decrease the brightness of the display.
@@ -595,10 +631,10 @@

Calibration Instructions

Current CO2 Value: ppm

- - +
+ + +
diff --git a/webserver/style.css b/webserver/style.css index fae9465..96a6c68 100644 --- a/webserver/style.css +++ b/webserver/style.css @@ -12,6 +12,8 @@ --header-font-color: #333; --header-border-color: #ddd; --input-border-color: #ccc; + --input-border-color-valid: #4caf50; + --input-border-color-error: red; --input-background-color: #fff; --button-background-color: #4caf50; --button-hover-background-color: #45a049; @@ -29,6 +31,8 @@ --modal-bg-color: #f1f1f1; --modal-overlay-bg-color: rgba(0, 0, 0, 0.4); --unchecked-font-color: orange; + --form-error-color: white; + --form-error-bg-color: red; } [theme="dark"] { @@ -45,6 +49,8 @@ --header-font-color: #ecf0f1; --header-border-color: #1c2833; --input-border-color: #34495e; + --input-border-color-valid: #4caf50; + --input-border-color-error: red; --input-background-color: #3b4a5a; --button-background-color: #1abc9c; --button-hover-background-color: #16a085; @@ -62,6 +68,8 @@ --modal-bg-color: #3b4a5a; --modal-overlay-bg-color: rgba(0, 0, 0, 0.8); --unchecked-font-color: yellow; + --form-error-color: white; + --form-error-bg-color: red; } /* For small screens */ @@ -191,6 +199,7 @@ h4 { display: flex; align-items: center; margin-bottom: 15px; + position: relative; } .form-group label { @@ -201,6 +210,10 @@ h4 { .form-group input[type="text"], .form-group input[type="password"], .form-group input[type="number"] { + flex: 1; +} +.form-group label.flex2, +.form-group input.flex2 { flex: 2; } @@ -218,6 +231,7 @@ h4 { .flex-align-center { display: flex; + flex-flow: wrap; align-items: center; } @@ -231,7 +245,7 @@ h4 { } .flex-align-center .tooltip-icon { - margin-right: 5px; + margin-right: 12px; } #vRef + #currentVoltage { @@ -259,6 +273,10 @@ legend { color: var(--header-font-color); } +fieldset + fieldset + legend { + font-size: 1em; +} + label { display: inline-block; margin-bottom: 5px; @@ -271,7 +289,6 @@ input[type="password"], input[type="number"] { width: 100%; padding: 10px; - margin-bottom: 10px; box-sizing: border-box; border: 1px solid var(--input-border-color); background-color: var(--input-background-color); @@ -279,6 +296,9 @@ input[type="number"] { font-size: 14px; color: var(--font-color); } +select{ + width: 50%; +} input[type="checkbox"] { width: auto; @@ -514,17 +534,21 @@ button:hover { .tooltip-icon { cursor: pointer; - margin-left: 5px; + margin-top: -5px; + padding: 5px 10px; } .tooltip-text { visibility: hidden; - width: 180px; + width: auto; + top: calc(100% + 2px); + left: 16px; + max-width: 600px; background-color: var(--tooltip-bg-color); color: var(--tooltip-text-color); text-align: center; - border-radius: 6px; - padding: 8px 8px; + border-radius: 0 10px 10px 10px; + padding: 10px 18px; position: absolute; z-index: 1; animation: fadeInOut 2s ease-in-out; @@ -741,7 +765,7 @@ button:hover { } input.valid { - border-color: #468847; + border-color: var(--input-border-color-valid); background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAgVBMVEUAAABetV5buFtcuFxcuVxdu11cuFxbuFtcuFxcuFxbtltcuFxbtltetl5cuFxct1xduV1fuF9cuFxcuFxbultcuFxduF1gtWBduV1cuFxcuVxcuFxcuFxcuFxet15dt11cuFxcuFxbt1teuF5duV1euF5cuVxcuFxcuFxcuFwAAADG3XcxAAAAKXRSTlMAJrDPRSnn1OjCKvM4MamLFivp8jvI1xgs6jpL++w5UvrxUU83RMe6MlhBCPsAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AwTFzUBkZPjhwAAAHBJREFUGNNjYCAJMDIxsyDzWdk0NdmR+RyampqcCD4XiM/Nw8DLxy8A4gsKAfnCIgwMopqaYuIMDBIwPgOzJkhEQhLElwIplZYBMmWFQXw5iGHyCppgoCgHM14JLKLIg7BQGSiiqILsRFU1dQ3iPQgAPhMLEPHXqSUAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMTItMTlUMjM6NTM6MDErMDE6MDCbiS6WAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE2LTEyLTE5VDIzOjUzOjAxKzAxOjAw6tSWKgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=); background-position: right 5px center; background-repeat: no-repeat; @@ -750,7 +774,7 @@ input.valid { } input.error { - border-color: #ff0000; + border-color: var(--input-border-color-error); background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAARCAYAAAA/mJfHAAAA4UlEQVQ4Ed2TwRXCIAyGu4ILeJCEevHkCl3BFVzBFVzBFXosubmCK7gCK+ALJTzKC+3zqL0kkOTrTwhd91MfHc2Z0FxboqmHG532u1Y87zPIWfDOQuCiHEiOs+bJMWfhTYiHOr5Yc1JK5oIwIdwloQDFGK8lplpWU8KSPzqEV71PPVxUSLnZACY18YiBEIeyZtXnC6iVyPorEP+Fm6sdbbNPtcQIqi5CVM12o/ECbIDiqNTAzVlTjubnIcZhCYsXMYoI1U4WH0VRBEkiN76IqUMtudkmoDrhCejXnlsG/afzAYJhvyckpo4NAAAAAElFTkSuQmCC); background-position: right 5px center; background-repeat: no-repeat; @@ -760,8 +784,99 @@ input.error { .form-error { display: block; - color: #ff0000; - margin: 0 0 1em; + color: var(--form-error-color); + background-color: var(--form-error-bg-color); + margin: 1px 0.7em 1em 1em; font-size: 0.9em; text-align: center; -} \ No newline at end of file + border: 1px solid var(--form-error-bg-color); + border-radius: 0 0 10px 10px; + order: 1; + padding: 10px; + width: 100%; +} + +/* From https://getcssscan.com/css-checkboxes-examples +*/ + .checkbox-wrapper-1 *, + .checkbox-wrapper-1 ::after, + .checkbox-wrapper-1 ::before { + box-sizing: border-box; + } + .checkbox-wrapper-1 [type=checkbox].substituted { + margin: 0; + width: 0; + height: 0; + display: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + } + .checkbox-wrapper-1 [type=checkbox].substituted + label:before { + content: ""; + display: inline-block; + vertical-align: top; + height: 1.15em; + width: 1.15em; + margin-right: 0.6em; + color: rgba(0, 0, 0, 0.275); + border: solid 0.06em; + box-shadow: 0 0 0.04em, 0 0.06em 0.16em -0.03em inset, 0 0 0 0.07em transparent inset; + border-radius: 0.2em; + background: url('data:image/svg+xml;charset=UTF-8,') no-repeat center, white; + background-size: 0; + will-change: color, border, background, background-size, box-shadow; + transform: translate3d(0, 0, 0); + transition: color 0.1s, border 0.1s, background 0.15s, box-shadow 0.1s; + cursor: pointer; + } + .checkbox-wrapper-1 [type=checkbox].substituted:enabled:active + label:before, + .checkbox-wrapper-1 [type=checkbox].substituted:enabled + label:active:before { + box-shadow: 0 0 0.04em, 0 0.06em 0.16em -0.03em transparent inset, 0 0 0 0.07em rgba(0, 0, 0, 0.1) inset; + background-color: #f0f0f0; + } + .checkbox-wrapper-1 [type=checkbox].substituted:checked + label:before { + background-color: #3B99FC; + background-size: 0.75em; + color: rgba(0, 0, 0, 0.075); + } + .checkbox-wrapper-1 [type=checkbox].substituted:checked:enabled:active + label:before, + .checkbox-wrapper-1 [type=checkbox].substituted:checked:enabled + label:active:before { + background-color: #0a7ffb; + color: rgba(0, 0, 0, 0.275); + } + .checkbox-wrapper-1 [type=checkbox].substituted:focus + label:before { + box-shadow: 0 0 0.04em, 0 0.06em 0.16em -0.03em transparent inset, 0 0 0 0.07em rgba(0, 0, 0, 0.1) inset, 0 0 0 3.3px rgba(65, 159, 255, 0.55), 0 0 0 5px rgba(65, 159, 255, 0.3); + } + .checkbox-wrapper-1 [type=checkbox].substituted:focus:active + label:before, + .checkbox-wrapper-1 [type=checkbox].substituted:focus + label:active:before { + box-shadow: 0 0 0.04em, 0 0.06em 0.16em -0.03em transparent inset, 0 0 0 0.07em rgba(0, 0, 0, 0.1) inset, 0 0 0 3.3px rgba(65, 159, 255, 0.55), 0 0 0 5px rgba(65, 159, 255, 0.3); + } + .checkbox-wrapper-1 [type=checkbox].substituted:disabled + label:before { + opacity: 0.5; + } + + .checkbox-wrapper-1 [type=checkbox].substituted.dark + label:before { + color: rgba(255, 255, 255, 0.275); + background-color: #222; + background-image: url('data:image/svg+xml;charset=UTF-8,'); + } + .checkbox-wrapper-1 [type=checkbox].substituted.dark:enabled:active + label:before, + .checkbox-wrapper-1 [type=checkbox].substituted.dark:enabled + label:active:before { + background-color: #444; + box-shadow: 0 0 0.04em, 0 0.06em 0.16em -0.03em transparent inset, 0 0 0 0.07em rgba(255, 255, 255, 0.1) inset; + } + .checkbox-wrapper-1 [type=checkbox].substituted.dark:checked + label:before { + background-color: #a97035; + color: rgba(255, 255, 255, 0.075); + } + .checkbox-wrapper-1 [type=checkbox].substituted.dark:checked:enabled:active + label:before, + .checkbox-wrapper-1 [type=checkbox].substituted.dark:checked:enabled + label:active:before { + background-color: #c68035; + color: rgba(0, 0, 0, 0.275); + } + .checkbox-wrapper-1 [type=checkbox].substituted + label { + -webkit-user-select: none; + user-select: none; + cursor: pointer; + }