diff --git a/ESPlant-Firmware/dependencies.lock b/ESPlant-Firmware/dependencies.lock index f27fb5e4..cd5b430c 100644 --- a/ESPlant-Firmware/dependencies.lock +++ b/ESPlant-Firmware/dependencies.lock @@ -15,7 +15,7 @@ dependencies: component_hash: null source: type: idf - version: 5.3.0 + version: 5.2.1 joltwallet/littlefs: component_hash: 703c642136031deca2579bdc19721a397f9fd9033b1c667c7b89fe23fa394c40 source: diff --git a/ESPlant-Firmware/frontend/.prettierrc b/ESPlant-Firmware/frontend/.prettierrc new file mode 100644 index 00000000..5a938ce1 --- /dev/null +++ b/ESPlant-Firmware/frontend/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 4, + "useTabs": false +} diff --git a/ESPlant-Firmware/frontend/mock/cloudSetupBlumy.mock.ts b/ESPlant-Firmware/frontend/mock/cloudSetupBlumy.mock.ts new file mode 100644 index 00000000..9f18063f --- /dev/null +++ b/ESPlant-Firmware/frontend/mock/cloudSetupBlumy.mock.ts @@ -0,0 +1,8 @@ +import { defineMock } from "vite-plugin-mock-dev-server"; + +export default defineMock({ + url: "/api/cloudSetup/blumy", + body: { + token: "blumy_c8nu8r9zr23rch" + }, +}); diff --git a/ESPlant-Firmware/frontend/mock/cloudSetupHttp.mock.ts b/ESPlant-Firmware/frontend/mock/cloudSetupHttp.mock.ts new file mode 100644 index 00000000..20759482 --- /dev/null +++ b/ESPlant-Firmware/frontend/mock/cloudSetupHttp.mock.ts @@ -0,0 +1,10 @@ +import { defineMock } from "vite-plugin-mock-dev-server"; + +export default defineMock({ + url: "/api/cloudSetup/http", + body: { + sensorId: "45", + url: "http://blumy-server.com", + auth: "???", + }, +}); diff --git a/ESPlant-Firmware/frontend/mock/cloudSetupMqtt.mock.ts b/ESPlant-Firmware/frontend/mock/cloudSetupMqtt.mock.ts new file mode 100644 index 00000000..9ca0fee9 --- /dev/null +++ b/ESPlant-Firmware/frontend/mock/cloudSetupMqtt.mock.ts @@ -0,0 +1,14 @@ +import { defineMock } from "vite-plugin-mock-dev-server"; + +export default defineMock({ + url: "/api/cloudSetup/mqtt", + body: { + sensorId: "45", + server: "blumy-server.com", + port: 1883, + username: "blumy-user", + password: "blumy123", + topic: "blumy-topic", + clientId: "blumy-client", + }, +}); diff --git a/ESPlant-Firmware/frontend/mock/getSensorData.mock.ts b/ESPlant-Firmware/frontend/mock/getSensorData.mock.ts new file mode 100644 index 00000000..693881dd --- /dev/null +++ b/ESPlant-Firmware/frontend/mock/getSensorData.mock.ts @@ -0,0 +1,13 @@ +import { defineMock } from "vite-plugin-mock-dev-server"; + +export default defineMock({ + url: "/api/sensor/data", + body: { + temperature: 25.5, + humidity: 50, + light: 0.7, + moisture: 645, + voltage: 2.8, + usb: true, + }, +}); diff --git a/ESPlant-Firmware/frontend/mock/getUpdateFirmwareUrl.mock.ts b/ESPlant-Firmware/frontend/mock/getUpdateFirmwareUrl.mock.ts new file mode 100644 index 00000000..10048107 --- /dev/null +++ b/ESPlant-Firmware/frontend/mock/getUpdateFirmwareUrl.mock.ts @@ -0,0 +1,7 @@ +import { defineMock } from "vite-plugin-mock-dev-server"; + +export default defineMock({ + url: "/api/update/firmware", + method: "GET", + body: { url: "http://cloud.blumy.com/firmware.bin" }, +}); diff --git a/ESPlant-Firmware/frontend/mock/networks.mock.ts b/ESPlant-Firmware/frontend/mock/networks.mock.ts index d8147dce..a88502e8 100644 --- a/ESPlant-Firmware/frontend/mock/networks.mock.ts +++ b/ESPlant-Firmware/frontend/mock/networks.mock.ts @@ -6,42 +6,37 @@ export default defineMock({ { rssi: -55, ssid: "MyWiFi", - bssid: "00:11:22:33:44:55", - channel: 1, secure: 4, - hidden: false, }, { rssi: -66, ssid: "MyWiFi2", - bssid: "00:11:22:33:44:56", - channel: 6, secure: 3, - hidden: false, }, { rssi: -77, ssid: "MyWiFi3", - bssid: "00:11:22:33:44:57", - channel: 11, secure: 2, - hidden: false, }, { rssi: -77, ssid: "FRITZ!Box 7490", - bssid: "00:11:22:33:44:57", - channel: 11, secure: 7, - hidden: false, }, { rssi: -30, ssid: "Strongest WiFi alive", - bssid: "00:11:22:33:44:57", - channel: 11, secure: 7, - hidden: false, + }, + { + rssi: -30, + ssid: "Duplicate Wifi", + secure: 7, + }, + { + rssi: -60, + ssid: "Duplicate Wifi", + secure: 7, }, ], }); diff --git a/ESPlant-Firmware/frontend/mock/cloudSetup.mock.ts b/ESPlant-Firmware/frontend/mock/updateFirmware.mock.ts similarity index 66% rename from ESPlant-Firmware/frontend/mock/cloudSetup.mock.ts rename to ESPlant-Firmware/frontend/mock/updateFirmware.mock.ts index ceacbef5..0273d97c 100644 --- a/ESPlant-Firmware/frontend/mock/cloudSetup.mock.ts +++ b/ESPlant-Firmware/frontend/mock/updateFirmware.mock.ts @@ -2,7 +2,8 @@ import { defineMock } from "vite-plugin-mock-dev-server"; export default defineMock( { - url: "/api/cloudSetup", + url: "/api/update/firmware", + method: "POST", body: "OK", } ); \ No newline at end of file diff --git a/ESPlant-Firmware/frontend/mock/sensor-value.mock.ts b/ESPlant-Firmware/frontend/mock/updatePercentage.mock.ts similarity index 63% rename from ESPlant-Firmware/frontend/mock/sensor-value.mock.ts rename to ESPlant-Firmware/frontend/mock/updatePercentage.mock.ts index cb2e0caf..f30ace8f 100644 --- a/ESPlant-Firmware/frontend/mock/sensor-value.mock.ts +++ b/ESPlant-Firmware/frontend/mock/updatePercentage.mock.ts @@ -2,7 +2,7 @@ import { defineMock } from "vite-plugin-mock-dev-server"; export default defineMock( { - url: "/api/sensor/value", - body: 234, + url: "/api/update/percentage", + body: 20, } ); \ No newline at end of file diff --git a/ESPlant-Firmware/frontend/src/api.ts b/ESPlant-Firmware/frontend/src/api.ts index 843dcd99..27890645 100644 --- a/ESPlant-Firmware/frontend/src/api.ts +++ b/ESPlant-Firmware/frontend/src/api.ts @@ -2,10 +2,7 @@ import { loadingState } from "./states"; export type Network = { rssi: number; ssid: string; - bssid: string; - channel: number; secure: number; - hidden: boolean; }; export enum WifiStatus { @@ -18,11 +15,43 @@ export enum WifiStatus { ERROR = 10, } -export enum ResetFlag { - SENSOR_FLAG = 0, - CONFIGURATION_FLAG = 1, +export interface SensorData { + temperature: number; + humidity: number; + light: number; + moisture: number; + voltage: number; + usb: boolean; } +export interface HttpCloudConfiguration extends Record { + type: "http"; + sensorId: string; + url: string; + auth: string; +} + +export interface MqttCloudConfiguration extends Record { + type: "mqtt"; + sensorId: string; + server: string; + port: string; + username: string; + password: string; + topic: string; + clientId: string; +} + +export interface BlumyCloudConfiguration extends Record { + type: "cloud"; + token: string; +} + +export type CloudConfiguration = + | HttpCloudConfiguration + | MqttCloudConfiguration + | BlumyCloudConfiguration; + /* fetch loading state indicator */ const fetch = new Proxy(window.fetch, { apply: async (target, thisArgs, args) => { @@ -36,14 +65,20 @@ const fetch = new Proxy(window.fetch, { }, }); -async function postDataToEsp(url: string, params: Record | string) { - const body = typeof params === "string" ? params : Object.entries(params).map(([key, value]) => key + "=" + value).join("\n") + "\n"; +async function postDataToEsp( + url: string, + params?: Record | string +) { + const body = params + ? typeof params === "string" + ? params + : Object.entries(params) + .map(([key, value]) => key + "=" + value) + .join("\n") + "\n" + : undefined; return await fetch("/api" + url, { method: "POST", body, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, }); } @@ -56,43 +91,19 @@ async function getDataFromEsp(url: string) { }); } -async function uploadFile(file: File, url: string) { - const formData = new FormData(); - formData.append("upload", file); - return await fetch("/api" + url, { - method: "POST", - body: formData, - }); -} - -export async function setPlantName(name: string) { - return await postDataToEsp("/plantName", name); +export async function connectToNetwork(ssid: string, password: string) { + return await postDataToEsp("/connect", { ssid, password }); } -export async function getPlantName() { - return await getDataFromEsp("/plantName"); +export async function resetEsp() { + return await postDataToEsp("/reset"); } export async function getNetworks(): Promise { return await getDataFromEsp("/networks"); } -export async function getConnectedNetwork(): Promise { - return await getDataFromEsp("/connectedNetwork"); -} - -export async function connectToNetwork(ssid: string, password: string) { - return await postDataToEsp("/connect", {ssid, password}); -} - -export async function resetEsp(resetFlag: ResetFlag) { - return await postDataToEsp("/reset", String(resetFlag)); -} - -/** - * @returns WifiStatus - */ -export async function isEspConnected(): Promise { +export async function isConnected(): Promise { const res = await getDataFromEsp("/isConnected"); if (res == null) { return WifiStatus.ERROR; @@ -100,41 +111,38 @@ export async function isEspConnected(): Promise { return Number(res); } -export interface HttpCloudConfiguration extends Record{ - type: 'http' - sensorId: string, - url: string - auth: string -} - -export interface MqttCloudConfiguration extends Record{ - type: 'mqtt' - sensorId: string, - server: string, - port: string, - username: string, - password: string, - topic: string, - clientId: string -} - -export interface BlumyCloudConfiguration extends Record { - type: 'cloud' - token: string +export async function getConnectedNetwork(): Promise<{ ssid: string, status: WifiStatus }> { + return await getDataFromEsp("/connectedNetwork"); } -export type CloudConfiguration = HttpCloudConfiguration | MqttCloudConfiguration | BlumyCloudConfiguration; - export async function setCloudCredentials(config: CloudConfiguration) { - if (config.type === 'http') { + if (config.type === "http") { return await postDataToEsp("/cloudSetup/http", config); - } else if (config.type === 'mqtt') { + } else if (config.type === "mqtt") { return await postDataToEsp("/cloudSetup/mqtt", config); - } else if (config.type === 'cloud') { + } else if (config.type === "cloud") { return await postDataToEsp("/cloudSetup/blumy", config); } } +export async function getCloudCredentials( + type: T +): Promise< + T extends "http" + ? HttpCloudConfiguration + : T extends "mqtt" + ? MqttCloudConfiguration + : BlumyCloudConfiguration +> { + if (type === "http") { + return await getDataFromEsp("/cloudSetup/http"); + } else if (type === "mqtt") { + return await getDataFromEsp("/cloudSetup/mqtt"); + } else if (type === "cloud") { + return await getDataFromEsp("/cloudSetup/blumy"); + } +} + export async function setSleepTimeout(timeout: number) { timeout = Math.round(timeout); return await postDataToEsp("/timeouts/sleep", timeout.toString()); @@ -144,18 +152,34 @@ export async function getSleepTimeout() { return Number(await getDataFromEsp("/timeouts/sleep")); } +export async function setConfigurationModeTimeout(timeout: number) { + timeout = Math.round(timeout); + return await postDataToEsp( + "/timeouts/configurationMode", + timeout.toString() + ); +} + +export async function getConfigurationModeTimeout() { + return Number(await getDataFromEsp("/timeouts/configurationMode")); +} + export async function getUpdatePercentage() { return Number(await getDataFromEsp("/update/percentage")); } -export async function updateFs(file: File) { - return await uploadFile(file, "/update/littlefs"); +export async function getSensorData(): Promise { + return await getDataFromEsp("/sensor/data"); } -export async function updateFirmware(file: File) { - return await uploadFile(file, "/update/firmware"); +export async function hardResetEsp() { + return await postDataToEsp("/hardReset"); } -export async function getSensorValue() { - return Number(await getDataFromEsp("/sensor/value")); -} \ No newline at end of file +export async function updateFirmware(url: string) { + return await postDataToEsp("/update/firmware", url); +} + +export async function getUpdateFirmwareUrl(): Promise<{ url: string }> { + return await getDataFromEsp("/update/firmware"); +} diff --git a/ESPlant-Firmware/frontend/src/first-setup-screen.ts b/ESPlant-Firmware/frontend/src/first-setup-screen.ts index 0ffd99c8..7038f40c 100644 --- a/ESPlant-Firmware/frontend/src/first-setup-screen.ts +++ b/ESPlant-Firmware/frontend/src/first-setup-screen.ts @@ -5,8 +5,9 @@ import "./elements/dots-stepper-element"; import "./elements/header-element"; import "./elements/loader-bar-element"; import "./pages/cloud-page"; -import "./pages/name-page"; +import "./pages/home-page"; import "./pages/reset-page"; +import "./pages/timeout-page"; import "./pages/update-page"; import "./pages/welcome-page"; import "./pages/wifi-scanner-page"; @@ -27,8 +28,8 @@ export class FirstSetupScreen extends LitElement { width: 100%; } .page { - padding: 0 1rem; - max-width: 24rem; + padding: 0 1rem 1rem 1rem; + max-width: 30rem; width: 100%; box-sizing: border-box; } @@ -70,10 +71,10 @@ export class FirstSetupScreen extends LitElement { @next="${this.next}" @back="${this.back}" >`, - html``, + >`, html``, html``, + html``, ]; } diff --git a/ESPlant-Firmware/frontend/src/home-screen.ts b/ESPlant-Firmware/frontend/src/home-screen.ts deleted file mode 100644 index fb8110a4..00000000 --- a/ESPlant-Firmware/frontend/src/home-screen.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { getSensorValue } from "./api"; -import { css, html, LitElement } from "lit"; -import { customElement, state } from "lit/decorators.js"; -import "./elements/dots-stepper-element"; -import "./elements/header-element"; -import "./elements/loader-bar-element"; -import "./pages/page-elements/mqtt-form-element"; -import "./pages/name-page"; -import "./pages/update-page"; -import "./pages/welcome-page"; -import "./pages/wifi-scanner-page"; -import "./pages/wifi-setup-page"; - -@customElement("home-screen") -export class HomeScreen extends LitElement { - static styles = css` - :host { - display: flex; - flex-direction: column; - align-items: center; - row-gap: 1rem; - width: 100%; - } - .page { - padding: 0 1rem; - max-width: 24rem; - width: 100%; - box-sizing: border-box; - } - `; - - @state() - loading = false; - @state() - sensorValue = 0; - - shouldGetSensorValue = true; - - constructor() { - super(); - (async () => { - while (this.shouldGetSensorValue) { - this.sensorValue = await getSensorValue(); - await new Promise((resolve) => setTimeout(resolve, 1000)); - } - })(); - } - - disconnectedCallback() { - super.disconnectedCallback(); - this.shouldGetSensorValue = false; - } - - render() { - return html` - - -

- Zuletzt gelesener Feuchtigkeitswert: -

-
- ${this.sensorValue} -
- `; - } -} diff --git a/ESPlant-Firmware/frontend/src/pages/cloud-page.ts b/ESPlant-Firmware/frontend/src/pages/cloud-page.ts index de3df948..1af82ec1 100644 --- a/ESPlant-Firmware/frontend/src/pages/cloud-page.ts +++ b/ESPlant-Firmware/frontend/src/pages/cloud-page.ts @@ -1,48 +1,117 @@ import { html } from "lit"; -import { customElement, state } from "lit/decorators.js"; +import { customElement, query, state } from "lit/decorators.js"; +import { + CloudConfiguration, + getCloudCredentials, + setCloudCredentials, +} from "../api"; import { BasePage } from "./base-page"; +import "./page-elements/cloud-form-element"; +import { CloudFormElement } from "./page-elements/cloud-form-element"; import "./page-elements/collapsible-element"; import "./page-elements/http-form-element"; +import { HttpFormElement } from "./page-elements/http-form-element"; import "./page-elements/mqtt-form-element"; -import "./page-elements/cloud-form-element"; -import { CloudConfiguration, setCloudCredentials } from "../api"; +import { MqttFormElement } from "./page-elements/mqtt-form-element"; @customElement("cloud-page") export class CloudPage extends BasePage { @state() errorText: string = ""; - @state() apiConfig: CloudConfiguration; - @state() openState: Record = { - 'cloud': true, - 'http': false, - 'mqtt': false, - } + @state() configurationState: Record< + CloudConfiguration["type"], + { open: boolean; configuration?: CloudConfiguration } + > = { + cloud: { open: true }, + http: { open: false }, + mqtt: { open: false }, + }; + @state() configured: boolean = false; + + @query("cloud-form-element") cloudFormElement: CloudFormElement; + @query("http-form-element") httpFormElement: HttpFormElement; + @query("mqtt-form-element") mqttFormElement: MqttFormElement; private async submit() { - if (this.apiConfig == undefined) { - this.errorText = 'Bitte konfiguriere mindestens eine Schnittstelle.'; + const configuredStates = Object.entries(this.configurationState).filter( + ([, value]) => value.open && value.configuration + ); + if (configuredStates.length === 0) { + this.errorText = + "Bitte konfiguriere mindestens eine Schnittstelle."; return; } + configuredStates.forEach(async ([key]) => { + if (key == "cloud") { + const apiConfig = this.cloudFormElement.getConfig(); + const res = await setCloudCredentials(apiConfig); + if (!res.ok) { + this.errorText = "Fehler, GerÀt antwortet nicht"; + return; + } + } else if (key == "http") { + const apiConfig = this.httpFormElement.getConfig(); + const res = await setCloudCredentials(apiConfig); + if (!res.ok) { + this.errorText = "Fehler, GerÀt antwortet nicht"; + return; + } + } else if (key == "mqtt") { + const apiConfig = this.mqttFormElement.getConfig(); + const res = await setCloudCredentials(apiConfig); + if (!res.ok) { + this.errorText = "Fehler, GerÀt antwortet nicht"; + return; + } + } + }); + this.next(); + } - const res = await setCloudCredentials(this.apiConfig); - if (!res.ok) { - this.errorText = "Fehler, GerÀt antwortet nicht"; - return; - } else { - this.next(); + private updateConfigured() { + this.configured = Object.values(this.configurationState).some( + (value) => + value.open && + value.configuration && + Object.values(value.configuration).every((v) => !!v) + ); + if (this.configured) { + this.errorText = ""; } } - private handleOpen(target: CloudConfiguration['type']) { - this.openState = { - 'cloud': false, - 'http': false, - 'mqtt': false, - [target]: true - } + private handleOpen(target: CloudConfiguration["type"]) { + this.configurationState[target].open = true; + this.updateConfigured(); } - private handleConfigChange(event: CustomEvent) { - this.apiConfig = event.detail; + private handleClose(target: CloudConfiguration["type"]) { + this.configurationState[target].open = false; + this.updateConfigured(); + } + + private handleChange(event: CustomEvent) { + this.configurationState[event.detail.type].configuration = event.detail; + this.updateConfigured(); + } + + async firstUpdated() { + const cloudCredentials = await getCloudCredentials("cloud"); + if (cloudCredentials) { + this.configurationState["cloud"].configuration = cloudCredentials; + this.cloudFormElement.setConfig(cloudCredentials); + } + this.cloudFormElement.tokenInput.input.focus(); + const httpCredentials = await getCloudCredentials("http"); + if (httpCredentials) { + this.configurationState["http"].configuration = httpCredentials; + this.httpFormElement.setConfig(httpCredentials); + } + const mqttCredentials = await getCloudCredentials("mqtt"); + if (mqttCredentials) { + this.configurationState["mqtt"].configuration = mqttCredentials; + this.mqttFormElement.setConfig(mqttCredentials); + } + this.updateConfigured(); } render() { @@ -50,24 +119,30 @@ export class CloudPage extends BasePage { Schnittstellen-Konfiguration this.handleOpen('cloud')} + ?open=${this.configurationState["cloud"].open} + @opened=${() => this.handleOpen("cloud")} + @closed=${() => this.handleClose("cloud")} + @handleChange=${() => this.handleChange} > - + this.handleOpen('http')} + ?open=${this.configurationState["http"].open} + @opened=${() => this.handleOpen("http")} + @closed=${() => this.handleClose("http")} + @handleChange=${() => this.handleChange} > - + this.handleOpen('mqtt')} + ?open=${this.configurationState["mqtt"].open} + @opened=${() => this.handleOpen("mqtt")} + @closed=${() => this.handleClose("mqtt")} + @handleChange=${() => this.handleChange} > - + @@ -85,7 +160,7 @@ export class CloudPage extends BasePage { name="Speichern" @click="${this.submit}" ?secondary="${true}" - ?disabled="${this.apiConfig == undefined}" + ?disabled="${!this.configured}" > `; diff --git a/ESPlant-Firmware/frontend/src/pages/funny-plant-names.ts b/ESPlant-Firmware/frontend/src/pages/funny-plant-names.ts deleted file mode 100644 index 0b5a0b8c..00000000 --- a/ESPlant-Firmware/frontend/src/pages/funny-plant-names.ts +++ /dev/null @@ -1,119 +0,0 @@ -export const funnyPlantNames = [ - "Sprout Reynolds", - "Fernando the Ficus", - "Pepper the Cactus", - "Basil Fawlty", - "Twiggy Stardust", - "Daisy Duke", - "Petaluma", - "Parsley Jackson", - "Leaf Erikson", - "Sir Pruneface", - "Olive Twister", - "Coco Chanel", - "Bamboo-zled", - "Snoop Dogwood", - "Twiggy Smalls", - "Flora Dora", - "Thorny Rose", - "Cacti Minogue", - "Lettuce Pray", - "Twiggy Marley", - "Holly Golightly", - "Cedar Skywalker", - "Basil the Great", - "Vine Diesel", - "Oscar Wilde'n'sea", - "Dandelionaire", - "Figgy Azalea", - "Mr. Pineapple", - "Fiddle Leaf Fig Newton", - "Rooty Goldberg", - "Petunia Pig", - "Bamboo-boo", - "Hyacinth Bucket", - "Parsley Whipped", - "Oprah Treefrey", - "Daisy Buchanan", - "Sir Willows-a-Lot", - "Demi Lovato Plant", - "Sherlock Gnomes", - "Fernando Valenzuela", - "Prickleback", - "Bonsai the Giant", - "Chia the Bomb", - "Wanda the Wandering Jew", - "Kale Sagan", - "Sage the Gemini", - "Tulip Neanderthalensis", - "Drake the Snake Plant", - "Thistle Beckham", - "Jasmine Timberlake", - "Beyonsea", - "Ginger Root Rogers", - "Cilantro Hitler", - "Pomegranate Pitt", - "Rhubarb Downey Jr.", - "Parsnip Hilton", - "Daisy Ridley", - "Sir Reginald Leafington", - "Aloe Blacc", - "Fennel Smith", - "Bruce Sprengsteen", - "Willow Smith", - "Pothos Malone", - "Katy Perennial", - "Sylvester Stalagmite", - "Sebastian the Crabapple", - "Huckleberry Houndstooth", - "Blossom Gallagher", - "Leaf Garrett", - "Daisy Dukes of Hazzard", - "Parsnip Turner", - "Sesame Cedar", - "Lemony Snicket", - "Sir Prune-a-lot", - "Ivy Longstocking", - "Pistachio Disguisey", - "Marigolden Globes", - "Basil Rathbone", - "Tulip Cruise", - "Twiggy Lawson", - "Ficus Alba", - "Pepper Potts", - "Lettuce Grohl", - "Daisy Duke of Earl", - "Cypress Hill", - "Saffron Connery", - "Gourd Ramsey", - "Bamboo Marley", - "Thyme Lord", - "Mr. Beet", - "Zucchini Minnelli", - "Cilantro Spice", - "Asparagus Spears", - "Jadeite Knight", - "Wisteria Lane", - "Carrot Top", - "Geranium Man", - "Sage Stallone", - "Tofu McPlantface", - "Basilisk", - "Fern Gully", - "Sproutnik", - "Pineapple Express", - "Agave Adams", - "Cauliflower Power", - "Pansy Skywalker", - "Lily Potter", - "Ziggy Stardust-filament", - "Rosemary's Baby", - "Succulent Simpson", - "Pepperoni", - "Tulip Diddy", - "Twiggy Ramone", - "Kale Luthor", - "Mossy Malone", - "Celery Dion", - "Daffodilma Hayek", -]; diff --git a/ESPlant-Firmware/frontend/src/pages/home-page.ts b/ESPlant-Firmware/frontend/src/pages/home-page.ts new file mode 100644 index 00000000..5c73f3f1 --- /dev/null +++ b/ESPlant-Firmware/frontend/src/pages/home-page.ts @@ -0,0 +1,123 @@ +import { BasePage } from "./base-page"; +import { css, html } from "lit"; +import { SensorData, getSensorData } from "../api"; +import { customElement, query, state } from "lit/decorators.js"; +import { InputElement } from "./page-elements/input-element"; + +@customElement("home-page") +export class HomePage extends BasePage { + static styles = css` + :host { + display: flex; + flex-direction: column; + align-items: center; + row-gap: 1rem; + width: 100%; + } + .page { + padding: 0 1rem; + max-width: 24rem; + width: 100%; + box-sizing: border-box; + } + `; + + @query("#temperature") temperatureElement: InputElement; + @query("#humidity") humidityElement: InputElement; + @query("#light") lightElement: InputElement; + @query("#moisture") moistureElement: InputElement; + @query("#voltage") voltageElement: InputElement; + @query("#usb") usbElement: InputElement; + + @state() + loading = false; + + timeout: number; + + async updateSensorData() { + const sensorData = await getSensorData(); + if (!sensorData) { + return; + } + this.temperatureElement.input.value = String(sensorData.temperature); + this.humidityElement.input.value = String(sensorData.humidity); + this.lightElement.input.value = String(sensorData.light); + this.moistureElement.input.value = String(sensorData.moisture); + this.voltageElement.input.value = String(sensorData.voltage); + this.usbElement.input.value = sensorData.usb + ? "angeschlossen" + : "nicht angeschlossen"; + this.timeout = window.setTimeout(() => this.updateSensorData(), 2000); + } + + constructor() { + super(); + this.updateSensorData(); + } + + disconnectedCallback() { + super.disconnectedCallback(); + if (this.timeout) { + window.clearTimeout(this.timeout); + } + } + + render() { + return html` +

+ Live Anzeige der Sensordaten +

+ + + + + + + + + + + + `; + } +} diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/button-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/button-element.ts index 1121905d..b59d64f7 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/button-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/button-element.ts @@ -25,7 +25,7 @@ export class ButtonElement extends LitElement { background-color: var(--secondary-base); color: var(--text-light); } - button:disabled { + button.disabled { opacity: 0.5; cursor: not-allowed; } diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/cloud-form-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/cloud-form-element.ts index 4af58d09..3c916b66 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/cloud-form-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/cloud-form-element.ts @@ -6,14 +6,27 @@ import { customElement, query } from "lit/decorators.js"; @customElement("cloud-form-element") export class CloudFormElement extends LitElement { @query("#token") tokenInput: InputElement; - + + public getConfig(): BlumyCloudConfiguration { + return { + type: "cloud", + token: this.tokenInput.input.value, + }; + } + + public setConfig(config: BlumyCloudConfiguration) { + this.tokenInput.input.value = config.token; + } + private handleChange() { - this.dispatchEvent(new CustomEvent('input-config', { - detail: { - type: 'cloud', - token: this.tokenInput.input.value, - } - })) + this.dispatchEvent( + new CustomEvent("input-config", { + detail: { + type: "cloud", + token: this.tokenInput.input.value, + }, + }) + ); } render() { diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/collapsible-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/collapsible-element.ts index ae079b3b..5a0cada7 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/collapsible-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/collapsible-element.ts @@ -36,14 +36,18 @@ export class CollapsibleElement extends LitElement { details[open] summary::marker { color: var(--text-light); } + + summary:before { + line-height: 1; + } details[open] summary:before { - content: "-"; + content: "☑"; margin-right: 0.5rem; } details:not([open]) summary:before { - content: "+"; + content: "☐"; margin-right: 0.5rem; } @@ -68,7 +72,7 @@ export class CollapsibleElement extends LitElement {
- + `; } } diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/http-form-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/http-form-element.ts index 69b9ed02..fe4e32e8 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/http-form-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/http-form-element.ts @@ -8,16 +8,33 @@ export class HttpFormElement extends LitElement { @query("#sensorId") sensorInput: InputElement; @query("#url") urlInput: InputElement; @query("#auth") authInput: InputElement; - + + public getConfig(): HttpCloudConfiguration { + return { + type: "http", + sensorId: this.sensorInput.input.value, + url: this.urlInput.input.value, + auth: this.authInput.input.value, + }; + } + + public setConfig(config: HttpCloudConfiguration) { + this.sensorInput.input.value = config.sensorId; + this.urlInput.input.value = config.url; + this.authInput.input.value = config.auth; + } + private handleChange() { - this.dispatchEvent(new CustomEvent('input', { - detail: { - type: 'http', - sensorId: this.sensorInput.input.value, - url: this.urlInput.input.value, - auth: this.authInput.input.value, - } - })) + this.dispatchEvent( + new CustomEvent("input", { + detail: { + type: "http", + sensorId: this.sensorInput.input.value, + url: this.urlInput.input.value, + auth: this.authInput.input.value, + }, + }) + ); } render() { diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/input-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/input-element.ts index ab87d515..665c438d 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/input-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/input-element.ts @@ -48,6 +48,7 @@ export class InputElement extends LitElement { | "url" | "week" = "text"; @property() initialValue: any; + @property() readonly: boolean; @query("#input") input: HTMLInputElement; @@ -65,6 +66,7 @@ export class InputElement extends LitElement { diff --git a/ESPlant-Firmware/frontend/src/pages/page-elements/mqtt-form-element.ts b/ESPlant-Firmware/frontend/src/pages/page-elements/mqtt-form-element.ts index f6e452e8..2230cdee 100644 --- a/ESPlant-Firmware/frontend/src/pages/page-elements/mqtt-form-element.ts +++ b/ESPlant-Firmware/frontend/src/pages/page-elements/mqtt-form-element.ts @@ -4,7 +4,7 @@ import { customElement, query } from "lit/decorators.js"; import { MqttCloudConfiguration } from "../../api"; @customElement("mqtt-form-element") -export class MqttForm extends LitElement { +export class MqttFormElement extends LitElement { @query("#sensorId") sensorInput: InputElement; @query("#server") serverInput: InputElement; @query("#port") portInput: InputElement; @@ -13,19 +13,44 @@ export class MqttForm extends LitElement { @query("#topic") topicInput: InputElement; @query("#client-id") clientIdInput: InputElement; + public getConfig(): MqttCloudConfiguration { + return { + type: "mqtt", + sensorId: this.sensorInput.input.value, + server: this.serverInput.input.value, + port: this.portInput.input.value, + username: this.userInput.input.value, + password: this.passwordInput.input.value, + topic: this.topicInput.input.value, + clientId: this.clientIdInput.input.value, + }; + } + + public setConfig(config: MqttCloudConfiguration) { + this.sensorInput.input.value = config.sensorId; + this.serverInput.input.value = config.server; + this.portInput.input.value = config.port; + this.userInput.input.value = config.username; + this.passwordInput.input.value = config.password; + this.topicInput.input.value = config.topic; + this.clientIdInput.input.value = config.clientId; + } + private handleChange() { - this.dispatchEvent(new CustomEvent('input', { - detail: { - type: 'mqtt', - sensorId: this.sensorInput.input.value, - server: this.serverInput.input.value, - port: this.portInput.input.value, - username: this.userInput.input.value, - password: this.passwordInput.input.value, - topic: this.topicInput.input.value, - clientId: this.clientIdInput.input.value, - } - })) + this.dispatchEvent( + new CustomEvent("input", { + detail: { + type: "mqtt", + sensorId: this.sensorInput.input.value, + server: this.serverInput.input.value, + port: this.portInput.input.value, + username: this.userInput.input.value, + password: this.passwordInput.input.value, + topic: this.topicInput.input.value, + clientId: this.clientIdInput.input.value, + }, + }) + ); } render() { diff --git a/ESPlant-Firmware/frontend/src/pages/reset-page.ts b/ESPlant-Firmware/frontend/src/pages/reset-page.ts index e76eaef2..a73e4e68 100644 --- a/ESPlant-Firmware/frontend/src/pages/reset-page.ts +++ b/ESPlant-Firmware/frontend/src/pages/reset-page.ts @@ -1,6 +1,6 @@ import { html } from "lit"; import { customElement, state } from "lit/decorators.js"; -import { resetEsp, ResetFlag } from "../api"; +import { resetEsp } from "../api"; import { BasePage } from "./base-page"; @customElement("reset-page") @@ -8,7 +8,7 @@ export class ResetPage extends BasePage { @state() errorText: string = ""; async reset() { - const res = await resetEsp(ResetFlag.SENSOR_FLAG); + const res = await resetEsp(); if (!res.ok) { this.errorText = "Fehler, GerĂ€t antwortet nicht"; return; @@ -19,10 +19,11 @@ export class ResetPage extends BasePage { return html` Reset - Das DrĂŒcken des Neustart-Buttons versetzt das GerĂ€t in den Sensor-Modus. - Es wird sich zu dem konfigurierten WLAN verbinden und Daten entsprechend - der Einstellungen versenden. Um das GerĂ€t spĂ€ter erneut zu konfigurieren, - drĂŒcke den Reset-Knopf auf dem GerĂ€t. + Das DrĂŒcken des Neustart-Buttons versetzt das GerĂ€t in den + Sensor-Modus. Es wird sich zu dem konfigurierten WLAN verbinden + und Daten entsprechend der Einstellungen versenden. Um das GerĂ€t + spĂ€ter erneut zu konfigurieren, drĂŒcke den Reset-Knopf auf dem + GerĂ€t. @@ -31,6 +32,11 @@ export class ResetPage extends BasePage { @click="${this.back}" ?secondary="${false}" > + this.updateProgress(), + 200 + ); + } + } + + disconnectedCallback() { + super.disconnectedCallback(); + + if (this.updateProgressTimeout) { + window.clearTimeout(this.updateProgressTimeout); + } + } + + async firstUpdated() { + const updateUrl = await getUpdateFirmwareUrl(); + if (updateUrl) { + this.urlElement.input.value = updateUrl.url; + } + } + + async isUpdateAvailable(url: string) { + // TODO check update server for updates and compare firmware versions + return true; + } + + async searchForUpdates() { + this.errorText = ""; + const url = this.urlElement.input.value; + if (!url) { + this.errorText = "Bitte gib eine URL ein"; return; } - console.log(this.littlefsElement.input.files[0]); - - if (this.littlefsElement.input.files[0]) { - let finished = false; - (async () => { - while (!finished) { - await new Promise((resolve) => setTimeout(resolve, 300)); - await getUpdatePercentage().then((percentage) => { - this.littlefsProgress = percentage; - }); - } - })(); - const res = await updateFs(this.littlefsElement.input.files[0]); - finished = true; - if (!res.ok) { - this.errorText = "Fehler, GerĂ€t antwortet nicht"; - return; - } - if (!this.errorText) { - this.littlefsProgress = 100; - } + + this.updateAvailable = await this.isUpdateAvailable(url); + if (this.updateAvailable) { + this.errorText = "Es ist ein Update verfĂŒgbar"; + } else { + this.errorText = "Kein Update verfĂŒgbar"; } - if (this.firmwareElement.input.files[0]) { - let finished = false; - (async () => { - while (!finished) { - await new Promise((resolve) => setTimeout(resolve, 300)); - await getUpdatePercentage().then((percentage) => { - this.firmwareProgress = percentage; - }); - } - })(); - const res = await updateFirmware( - this.firmwareElement.input.files[0] - ); - finished = true; - if (!res.ok) { - this.errorText = "Fehler, GerĂ€t antwortet nicht"; - return; - } - if (!this.errorText) { - this.firmwareProgress = 100; - } + } + + async updateFirmware() { + this.errorText = ""; + const url = this.urlElement.input.value; + if (!url) { + this.errorText = "Bitte gib eine URL ein"; + return; } - resetEsp(ResetFlag.CONFIGURATION_FLAG); - // TODO: open "Waiting for esp to restart" screen + + await updateFirmware(url); + this.updateProgress(); } render() { @@ -84,21 +90,13 @@ export class UpdatePage extends BasePage { Firmware aktualisieren - - @@ -112,11 +110,21 @@ export class UpdatePage extends BasePage { @click="${this.next}" ?secondary="${true}" > - + ${this.updateAvailable + ? html` + + ` + : html` + + `} `; } diff --git a/ESPlant-Firmware/frontend/src/pages/welcome-page.ts b/ESPlant-Firmware/frontend/src/pages/welcome-page.ts index 239bb214..d7cf96ee 100644 --- a/ESPlant-Firmware/frontend/src/pages/welcome-page.ts +++ b/ESPlant-Firmware/frontend/src/pages/welcome-page.ts @@ -1,7 +1,7 @@ import { StateController } from "@lit-app/state"; import { css, html } from "lit"; -import { customElement, state } from "lit/decorators.js"; -import { getConnectedNetwork, isEspConnected, WifiStatus } from "../api"; +import { customElement } from "lit/decorators.js"; +import { WifiStatus, getConnectedNetwork, isConnected } from "../api"; import { networkState } from "../states"; import { BasePage } from "./base-page"; @@ -26,12 +26,16 @@ export class WelcomePage extends BasePage { super(); (async () => { while (this.shouldReadWifiStatus) { - const wifiStatus = await isEspConnected(); + const wifiStatus = await isConnected(); if (wifiStatus == WifiStatus.CONNECTED) { const network = await getConnectedNetwork(); networkState.state = { - isConnected: true, - network: network, + isConnected: network.status == WifiStatus.CONNECTED, + network: { + rssi: 0, // TODO + ssid: network.ssid, + secure: 0, // TODO + }, }; } await new Promise((resolve) => setTimeout(resolve, 1000)); @@ -50,8 +54,8 @@ export class WelcomePage extends BasePage { Blumy ist aktuell ${networkState.state.isConnected - ? "mit dem Internet" - : "vom Internet"} + ? "mit dem Internet" + : "vom Internet"} ${networkState.state.isConnected diff --git a/ESPlant-Firmware/frontend/src/pages/wifi-setup-page.ts b/ESPlant-Firmware/frontend/src/pages/wifi-setup-page.ts index fefb99fe..73c4737c 100644 --- a/ESPlant-Firmware/frontend/src/pages/wifi-setup-page.ts +++ b/ESPlant-Firmware/frontend/src/pages/wifi-setup-page.ts @@ -1,6 +1,12 @@ import { html } from "lit"; import { customElement, query, state } from "lit/decorators.js"; -import { connectToNetwork, isEspConnected, Network, WifiStatus } from "../api"; +import { + connectToNetwork, + getConnectedNetwork, + isConnected, + Network, + WifiStatus, +} from "../api"; import { loadingState, networkState } from "../states"; import { BasePage } from "./base-page"; import { InputElement } from "./page-elements/input-element"; @@ -25,7 +31,7 @@ export class WifiSetupPage extends BasePage { // wait 500 ms for the device to connect to the network await new Promise((resolve) => setTimeout(resolve, 500)); for (let i = 0; i < 10; i++) { - const wifiStatus = await isEspConnected(); + const wifiStatus = await isConnected(); if (wifiStatus == WifiStatus.ERROR) { this.errorText = "Fehler, Sensor antwortet nicht"; @@ -48,9 +54,10 @@ export class WifiSetupPage extends BasePage { } else if (wifiStatus == WifiStatus.DISCONNECTED) { this.errorText = "Sensor ist nicht verbunden"; } else if (wifiStatus == WifiStatus.UNINITIALIZED) { - this.errorText = "Sensor ist nicht initialisiert. Versuche ihn neu zu starten."; + this.errorText = + "Sensor ist nicht initialisiert. Versuche ihn neu zu starten."; } else { - loadingState.state++;; + loadingState.state++; await new Promise((resolve) => setTimeout(resolve, 1000)); loadingState.state--; continue; @@ -68,6 +75,20 @@ export class WifiSetupPage extends BasePage { } } + async firstUpdated() { + if (networkState.state.network) { + return; + } + const network = await getConnectedNetwork(); + if (!network.ssid) { + return; + } + + networkState.state.network.ssid = network.ssid; + this.ssidElement.input.value = network.ssid; + this.passwordElement.input.focus(); + } + render() { return html` WLAN-Zugangsdaten eingeben diff --git a/ESPlant-Firmware/frontend/vite.config.ts b/ESPlant-Firmware/frontend/vite.config.ts index fe339640..9a8d8096 100644 --- a/ESPlant-Firmware/frontend/vite.config.ts +++ b/ESPlant-Firmware/frontend/vite.config.ts @@ -1,27 +1,23 @@ import { resolve } from "path"; import { defineConfig } from "vite"; import { viteSingleFile } from "vite-plugin-singlefile"; -import mockDevServerPlugin from 'vite-plugin-mock-dev-server' +import mockDevServerPlugin from "vite-plugin-mock-dev-server"; export default defineConfig({ - plugins: [ - mockDevServerPlugin(), - // viteSingleFile(), - ], - build: { - rollupOptions: { - input: { - index: resolve(__dirname, "index.html"), - home: resolve(__dirname, "home.html"), - }, + plugins: [mockDevServerPlugin(), viteSingleFile()], + build: { + rollupOptions: { + input: { + index: resolve(__dirname, "index.html"), + }, + }, + outDir: "../data", + target: "es2022", + modulePreload: false, + }, + server: { + proxy: { + "/api": {}, + }, }, - outDir: "../data", - target: "es2022", - modulePreload: false, - }, - server: { - proxy: { - '/api': {} - } - } }); diff --git a/ESPlant-Firmware/main/configuration_mode_server.c b/ESPlant-Firmware/main/configuration_mode_server.c index 2f225e4f..38552441 100644 --- a/ESPlant-Firmware/main/configuration_mode_server.c +++ b/ESPlant-Firmware/main/configuration_mode_server.c @@ -442,20 +442,41 @@ esp_err_t get_api_connectedNetwork_handler(httpd_req_t *req) httpd_resp_send_404(req); return ESP_FAIL; } + plantfi_sta_status_t status = plantfi_get_sta_status(); + + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "ssid", ssid); + // cJSON_AddStringToObject(root, "password", password); + cJSON_AddNumberToObject(root, "status", status); + + char *resp = cJSON_Print(root); + cJSON_Delete(root); - httpd_resp_send(req, ssid, HTTPD_RESP_USE_STRLEN); + httpd_resp_set_type(req, "application/json"); + httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); + free(resp); return ESP_OK; } -esp_err_t get_api_sensor_value_handler(httpd_req_t *req) +esp_err_t get_api_sensor_data_handler(httpd_req_t *req) { - sensors_moisture_sensor_output_t moisture_output; - sensors_read_moisture(&moisture_output); + sensors_full_data_t sensors_data; + sensors_full_read(&sensors_data); - int moisture = moisture_output.measurement; - char resp[10]; - sprintf(resp, "%d", moisture); + cJSON *root = cJSON_CreateObject(); + cJSON_AddNumberToObject(root, "temperature", sensors_data.temperature); + cJSON_AddNumberToObject(root, "humidity", sensors_data.humidity); + cJSON_AddNumberToObject(root, "light", sensors_data.light); + cJSON_AddNumberToObject(root, "moisture", sensors_data.moisture_measurement); + cJSON_AddNumberToObject(root, "voltage", sensors_data.voltage); + cJSON_AddBoolToObject(root, "usb", sensors_data.is_usb_connected); + + char *resp = cJSON_Print(root); + cJSON_Delete(root); + + httpd_resp_set_type(req, "application/json"); httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); + free(resp); return ESP_OK; } @@ -480,15 +501,15 @@ esp_err_t post_api_update_firmware_handler(httpd_req_t *req) return ESP_FAIL; } + plantstore_setFirmwareUpdateUrl(url); + esp_http_client_config_t config = { .url = url, .cert_pem = NULL, .timeout_ms = 10000, }; - esp_https_ota_config_t ota_config = { - .http_config = config - .url = url, - }; + esp_https_ota_config_t ota_config; + ota_config.http_config = &config; esp_https_ota_handle_t handle = NULL; esp_err_t err = esp_https_ota_begin(&ota_config, &handle); if (err != ESP_OK) @@ -535,10 +556,24 @@ esp_err_t post_api_update_firmware_handler(httpd_req_t *req) esp_restart(); } -esp_err_t post_api_update_littlefs_handler(httpd_req_t *req) +esp_err_t get_api_update_firmware_handler(httpd_req_t *req) { - const char resp[] = "Not Implemented"; + char url[100]; + if (!plantstore_getFirmwareUpdateUrl(url, sizeof(url))) + { + httpd_resp_send_404(req); + return ESP_FAIL; + } + + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "url", url); + + char *resp = cJSON_Print(root); + cJSON_Delete(root); + + httpd_resp_set_type(req, "application/json"); httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); + free(resp); return ESP_OK; } @@ -628,10 +663,10 @@ httpd_uri_t get_api_connectedNetwork = { .handler = get_api_connectedNetwork_handler, .user_ctx = NULL}; -httpd_uri_t get_api_sensorValue = { - .uri = "/api/sensor/value", +httpd_uri_t get_api_sensorData = { + .uri = "/api/sensor/data", .method = HTTP_GET, - .handler = get_api_sensor_value_handler, + .handler = get_api_sensor_data_handler, .user_ctx = NULL}; httpd_uri_t post_api_hardReset = { @@ -658,10 +693,10 @@ httpd_uri_t post_api_update_firmware = { .handler = post_api_update_firmware_handler, .user_ctx = NULL}; -httpd_uri_t post_api_update_littlefs = { - .uri = "/api/update/littlefs", - .method = HTTP_POST, - .handler = post_api_update_littlefs_handler, +httpd_uri_t get_api_update_firmware = { + .uri = "/api/update/firmware", + .method = HTTP_GET, + .handler = get_api_update_firmware_handler, .user_ctx = NULL}; /* Function for starting the webserver */ @@ -691,14 +726,16 @@ httpd_handle_t start_webserver(void) httpd_register_uri_handler(server, &get_api_cloudSetup_blumy); httpd_register_uri_handler(server, &post_api_timeouts_sleep); httpd_register_uri_handler(server, &get_api_timeouts_sleep); + httpd_register_uri_handler(server, &get_api_timeouts_configurationMode); + httpd_register_uri_handler(server, &post_api_timeouts_configurationMode); httpd_register_uri_handler(server, &get_api_update_percentage); httpd_register_uri_handler(server, &get_api_connectedNetwork); - httpd_register_uri_handler(server, &get_api_sensorValue); + httpd_register_uri_handler(server, &get_api_sensorData); httpd_register_uri_handler(server, &post_api_hardReset); httpd_register_uri_handler(server, &get); httpd_register_uri_handler(server, &post_api_update_firmware); - httpd_register_uri_handler(server, &post_api_update_littlefs); + httpd_register_uri_handler(server, &get_api_update_firmware); } /* If server failed to start, handle will be NULL */ return server; diff --git a/ESPlant-Firmware/main/peripherals/sensors.c b/ESPlant-Firmware/main/peripherals/sensors.c index bde4321b..5c6db573 100644 --- a/ESPlant-Firmware/main/peripherals/sensors.c +++ b/ESPlant-Firmware/main/peripherals/sensors.c @@ -14,6 +14,8 @@ const unsigned long maxStabilizationTime = 500; const int stabilizationDifference = 5; +bool isSensorsInit = false; + unsigned long millis() { return esp_timer_get_time() / 1000; @@ -316,6 +318,7 @@ void sensors_initSensors() adc_initAdc(); initAht(TEMPERATURE_SENSOR_SDA, TEMPERATURE_SENSOR_SCL); + isSensorsInit = true; } void sensors_deinitSensors() @@ -331,6 +334,10 @@ void sensors_deinitSensors() void sensors_full_read(sensors_full_data_t *data) { + if (!isSensorsInit) + { + sensors_initSensors(); + } data->light = sensors_readLightPercentage(); data->voltage = sensors_readVoltage(); sensors_aht_data_t aht_data; diff --git a/ESPlant-Firmware/main/plantstore.c b/ESPlant-Firmware/main/plantstore.c index 47cb2512..4c7429fe 100644 --- a/ESPlant-Firmware/main/plantstore.c +++ b/ESPlant-Firmware/main/plantstore.c @@ -168,6 +168,23 @@ void plantstore_setConfigurationModeTimeoutMs(int32_t timeoutMs) nvs_close(nvs_handle); } +void plantstore_setFirmwareUpdateUrl(char *url) +{ + nvs_handle_t nvs_handle = plantstore_openNvsReadWrite(); + ESP_ERROR_CHECK(nvs_set_str(nvs_handle, FIRMWARE_UPDATE_URL_KEY, url)); + ESP_ERROR_CHECK(nvs_commit(nvs_handle)); + nvs_close(nvs_handle); +} + +bool plantstore_getFirmwareUpdateUrl(char *url, size_t url_size) +{ + nvs_handle_t nvs_handle = plantstore_openNvsReadOnly(); + esp_err_t url_err = nvs_get_str(nvs_handle, FIRMWARE_UPDATE_URL_KEY, url, &url_size); + nvs_close(nvs_handle); + + return url_err == ESP_OK; +} + bool plantstore_isConfigured() { // Doing this is fine, because the parameters can be NULL and then the length of the stored values is checked only diff --git a/ESPlant-Firmware/main/plantstore.h b/ESPlant-Firmware/main/plantstore.h index 1e607c94..0f70b328 100644 --- a/ESPlant-Firmware/main/plantstore.h +++ b/ESPlant-Firmware/main/plantstore.h @@ -18,6 +18,7 @@ #define BLUMY_TOKEN_KEY "blumy_token" #define SENSOR_TIMEOUT_SLEEP_KEY "timeout_sleep" #define SENSOR_TIMEOUT_CONFIG_KEY "timeout_config" +#define FIRMWARE_UPDATE_URL_KEY "update_url" bool plantstore_getWifiCredentials(char *ssid, char *password, size_t ssid_size, size_t password_size); void plantstore_setWifiCredentials(char *ssid, char *password); @@ -31,6 +32,8 @@ bool plantstore_getSensorTimeoutSleepMs(uint64_t *timeoutMs); void plantstore_setSensorTimeoutSleepMs(uint64_t timeoutMs); bool plantstore_getConfigurationModeTimeoutMs(int32_t *timeoutMs); void plantstore_setConfigurationModeTimeoutMs(int32_t timeoutMs); +void plantstore_setFirmwareUpdateUrl(char *url); +bool plantstore_getFirmwareUpdateUrl(char *url, size_t url_size); /** * @brief Check if the plantstore is configured * The plantstore is marked as configured, if the wifi credentials are set and at least one of the cloud configurations is set. diff --git a/ESPlant-Firmware/sdkconfig b/ESPlant-Firmware/sdkconfig index 3b748bec..c91b414d 100644 --- a/ESPlant-Firmware/sdkconfig +++ b/ESPlant-Firmware/sdkconfig @@ -1,6 +1,6 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.2.1 Project Configuration # CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y @@ -56,10 +56,6 @@ CONFIG_SOC_CLK_TREE_SUPPORTED=y CONFIG_SOC_ASSIST_DEBUG_SUPPORTED=y CONFIG_SOC_WDT_SUPPORTED=y CONFIG_SOC_SPI_FLASH_SUPPORTED=y -CONFIG_SOC_RNG_SUPPORTED=y -CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y -CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y -CONFIG_SOC_MODEM_CLOCK_SUPPORTED=y CONFIG_SOC_XTAL_SUPPORT_40M=y CONFIG_SOC_AES_SUPPORT_DMA=y CONFIG_SOC_AES_GDMA=y @@ -108,7 +104,6 @@ CONFIG_SOC_AHB_GDMA_VERSION=1 CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=3 CONFIG_SOC_GDMA_SUPPORT_ETM=y -CONFIG_SOC_GDMA_SUPPORT_SLEEP_RETENTION=y CONFIG_SOC_ETM_GROUPS=1 CONFIG_SOC_ETM_CHANNELS_PER_GROUP=50 CONFIG_SOC_GPIO_PORT=1 @@ -120,7 +115,6 @@ CONFIG_SOC_GPIO_ETM_EVENTS_PER_GROUP=8 CONFIG_SOC_GPIO_ETM_TASKS_PER_GROUP=8 CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y CONFIG_SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP=y -CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y CONFIG_SOC_GPIO_IN_RANGE_MAX=30 CONFIG_SOC_GPIO_OUT_RANGE_MAX=30 CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK=0 @@ -128,12 +122,10 @@ CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x000000007FFFFF00 CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y CONFIG_SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP=y CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX=y -CONFIG_SOC_CLOCKOUT_HAS_SOURCE_GATE=y CONFIG_SOC_RTCIO_PIN_COUNT=8 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y -CONFIG_SOC_RTCIO_VALID_RTCIO_MASK=0xFF CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 CONFIG_SOC_DEDIC_PERIPH_ALWAYS_ENABLE=y @@ -141,7 +133,6 @@ CONFIG_SOC_I2C_NUM=1 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=8 CONFIG_SOC_I2C_SUPPORT_SLAVE=y -CONFIG_SOC_I2C_SUPPORT_HW_FSM_RST=y CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y CONFIG_SOC_I2C_SUPPORT_XTAL=y CONFIG_SOC_I2C_SUPPORT_RTC=y @@ -238,10 +229,6 @@ CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y CONFIG_SOC_SPI_SUPPORT_CLK_PLL_F80M=y CONFIG_SOC_SPI_SUPPORT_CLK_RC_FAST=y -CONFIG_SOC_SPI_SCT_SUPPORTED=y -CONFIG_SOC_SPI_SCT_REG_NUM=14 -CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y -CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y @@ -290,7 +277,7 @@ CONFIG_SOC_SECURE_BOOT_V2_ECC=y CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y -CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y CONFIG_SOC_CRYPTO_DPA_PROTECTION_SUPPORTED=y @@ -304,7 +291,6 @@ CONFIG_SOC_UART_SUPPORT_PLL_F80M_CLK=y CONFIG_SOC_UART_SUPPORT_RTC_CLK=y CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y -CONFIG_SOC_UART_HAS_LP_UART=y CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y CONFIG_SOC_COEX_HW_PTI=y CONFIG_SOC_EXTERNAL_COEX_ADVANCE=y @@ -340,10 +326,7 @@ CONFIG_SOC_RCC_IS_INDEPENDENT=y CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL=y CONFIG_SOC_TEMPERATURE_SENSOR_INTR_SUPPORT=y -CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_ETM=y -CONFIG_SOC_RNG_CLOCK_IS_INDEPENDENT=y CONFIG_SOC_WIFI_HW_TSF=y -CONFIG_SOC_WIFI_FTM_SUPPORT=y CONFIG_SOC_WIFI_GCMP_SUPPORT=y CONFIG_SOC_WIFI_WAPI_SUPPORT=y CONFIG_SOC_WIFI_CSI_SUPPORT=y @@ -459,19 +442,15 @@ CONFIG_ESP_ROM_HAS_RVFPLIB=y CONFIG_ESP_ROM_HAS_HAL_WDT=y CONFIG_ESP_ROM_HAS_HAL_SYSTIMER=y CONFIG_ESP_ROM_HAS_HEAP_TLSF=y -CONFIG_ESP_ROM_TLSF_CHECK_PATCH=y CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y CONFIG_ESP_ROM_HAS_SPI_FLASH=y CONFIG_ESP_ROM_HAS_REGI2C_BUG=y -CONFIG_ESP_ROM_HAS_NEWLIB=y CONFIG_ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT=y CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE=y CONFIG_ESP_ROM_WDT_INIT_PATCH=y CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y CONFIG_ESP_ROM_HAS_SW_FLOAT=y -CONFIG_ESP_ROM_USB_OTG_NUM=-1 -CONFIG_ESP_ROM_HAS_VERSION=y # # Boot ROM Behavior @@ -586,13 +565,7 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # -# TWAI Configuration -# -# CONFIG_TWAI_ISR_IN_IRAM is not set -# end of TWAI Configuration - -# -# Legacy ADC Driver Configuration +# Legacy ADC Configuration # # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set @@ -601,173 +574,160 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set # end of Legacy ADC Calibration Configuration -# end of Legacy ADC Driver Configuration - -# -# Legacy MCPWM Driver Configurations -# -# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# end of Legacy MCPWM Driver Configurations +# end of Legacy ADC Configuration # -# Legacy Timer Group Driver Configurations +# SPI Configuration # -# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# end of Legacy Timer Group Driver Configurations +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI Configuration # -# Legacy RMT Driver Configurations +# TWAI Configuration # -# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# end of Legacy RMT Driver Configurations -# end of Driver Configurations +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI Configuration # -# eFuse Bit Manager +# Temperature sensor Configuration # -# CONFIG_EFUSE_CUSTOM_TABLE is not set -# CONFIG_EFUSE_VIRTUAL is not set -CONFIG_EFUSE_MAX_BLK_LEN=256 -# end of eFuse Bit Manager +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE is not set +# end of Temperature sensor Configuration # -# ESP-TLS +# UART Configuration # -CONFIG_ESP_TLS_USING_MBEDTLS=y -CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y -# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set -# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set -# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set -# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set -# CONFIG_ESP_TLS_PSK_VERIFICATION is not set -# CONFIG_ESP_TLS_INSECURE is not set -# end of ESP-TLS +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART Configuration # -# ADC and ADC Calibration +# GPIO Configuration # -# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set -# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set -# CONFIG_ADC_ENABLE_DEBUG_LOG is not set -# end of ADC and ADC Calibration +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of GPIO Configuration # -# Wireless Coexistence +# Sigma Delta Modulator Configuration # -CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y -# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set -# end of Wireless Coexistence +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of Sigma Delta Modulator Configuration # -# Common ESP-related +# GPTimer Configuration # -CONFIG_ESP_ERR_TO_NAME_LOOKUP=y -# end of Common ESP-related +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of GPTimer Configuration # -# ESP-Driver:GPIO Configurations +# PCNT Configuration # -# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set -# end of ESP-Driver:GPIO Configurations +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of PCNT Configuration # -# ESP-Driver:GPTimer Configurations +# RMT Configuration # -CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y -# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set -# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:GPTimer Configurations +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of RMT Configuration # -# ESP-Driver:I2C Configurations +# MCPWM Configuration # -# CONFIG_I2C_ISR_IRAM_SAFE is not set -# CONFIG_I2C_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:I2C Configurations +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of MCPWM Configuration # -# ESP-Driver:I2S Configurations +# I2S Configuration # # CONFIG_I2S_ISR_IRAM_SAFE is not set # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set # CONFIG_I2S_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:I2S Configurations - -# -# ESP-Driver:LEDC Configurations -# -# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set -# end of ESP-Driver:LEDC Configurations +# end of I2S Configuration # -# ESP-Driver:MCPWM Configurations +# USB Serial/JTAG Configuration # -# CONFIG_MCPWM_ISR_IRAM_SAFE is not set -# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set -# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:MCPWM Configurations +# end of USB Serial/JTAG Configuration # -# ESP-Driver:Parallel IO Configurations +# Parallel IO Configuration # # CONFIG_PARLIO_ENABLE_DEBUG_LOG is not set # CONFIG_PARLIO_ISR_IRAM_SAFE is not set -# end of ESP-Driver:Parallel IO Configurations +# end of Parallel IO Configuration # -# ESP-Driver:PCNT Configurations +# LEDC Configuration # -# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set -# CONFIG_PCNT_ISR_IRAM_SAFE is not set -# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:PCNT Configurations +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of LEDC Configuration # -# ESP-Driver:RMT Configurations +# I2C Configuration # -# CONFIG_RMT_ISR_IRAM_SAFE is not set -# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set -# CONFIG_RMT_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:RMT Configurations +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# end of I2C Configuration +# end of Driver Configurations # -# ESP-Driver:Sigma Delta Modulator Configurations +# eFuse Bit Manager # -# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set -# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:Sigma Delta Modulator Configurations +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager # -# ESP-Driver:SPI Configurations +# ESP-TLS # -# CONFIG_SPI_MASTER_IN_IRAM is not set -CONFIG_SPI_MASTER_ISR_IN_IRAM=y -# CONFIG_SPI_SLAVE_IN_IRAM is not set -CONFIG_SPI_SLAVE_ISR_IN_IRAM=y -# end of ESP-Driver:SPI Configurations +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS # -# ESP-Driver:Temperature Sensor Configurations +# ADC and ADC Calibration # -# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set -# CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE is not set -# end of ESP-Driver:Temperature Sensor Configurations +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# end of ADC and ADC Calibration # -# ESP-Driver:UART Configurations +# Wireless Coexistence # -# CONFIG_UART_ISR_IN_IRAM is not set -# end of ESP-Driver:UART Configurations +CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# end of Wireless Coexistence # -# ESP-Driver:USB Serial/JTAG Configuration +# Common ESP-related # -CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y -# end of ESP-Driver:USB Serial/JTAG Configuration +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related # # Ethernet @@ -787,10 +747,7 @@ CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y # # GDB Stub # -CONFIG_ESP_GDBSTUB_ENABLED=y # CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set -CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y -CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub # @@ -799,7 +756,6 @@ CONFIG_ESP_GDBSTUB_MAX_TASKS=32 CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y # CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set # CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set -# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set # end of ESP HTTP client # @@ -897,12 +853,12 @@ CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y # end of ETM Configuration # -# GDMA Configurations +# GDMA Configuration # CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y # CONFIG_GDMA_ISR_IRAM_SAFE is not set # CONFIG_GDMA_ENABLE_DEBUG_LOG is not set -# end of GDMA Configurations +# end of GDMA Configuration # # Main XTAL Config @@ -920,8 +876,6 @@ CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_LOW=y # CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH is not set CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL=1 # end of Crypto DPA Protection - -CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y # end of Hardware Settings # @@ -935,6 +889,7 @@ CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y # # LCD Peripheral Configuration # +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 # CONFIG_LCD_ENABLE_DEBUG_LOG is not set # end of LCD Peripheral Configuration # end of LCD and Touch Panel @@ -963,11 +918,11 @@ CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y # CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_ENABLE_USB is not set CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 -# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # end of PHY # @@ -1027,7 +982,6 @@ CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y CONFIG_ESP_CONSOLE_UART=y CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 CONFIG_ESP_INT_WDT=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 @@ -1050,7 +1004,6 @@ CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y CONFIG_ESP_SYSTEM_HW_STACK_GUARD=y CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y -CONFIG_ESP_SYSTEM_HW_PC_RECORD=y # end of ESP System Settings # @@ -1060,7 +1013,7 @@ CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 # end of IPC (Inter-Processor Call) # -# ESP Timer (High Resolution Timer) +# High resolution timer (esp_timer) # # CONFIG_ESP_TIMER_PROFILING is not set CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y @@ -1070,10 +1023,11 @@ CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 # CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY=0x1 CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y # CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set CONFIG_ESP_TIMER_IMPL_SYSTIMER=y -# end of ESP Timer (High Resolution Timer) +# end of High resolution timer (esp_timer) # # Wi-Fi @@ -1105,7 +1059,6 @@ CONFIG_ESP_WIFI_ENABLE_SAE_PK=y CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y # CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set -# CONFIG_ESP_WIFI_FTM_ENABLE is not set CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y # CONFIG_ESP_WIFI_GCMP_SUPPORT is not set # CONFIG_ESP_WIFI_GMAC_SUPPORT is not set @@ -1184,8 +1137,6 @@ CONFIG_FATFS_PER_FILE_CACHE=y # CONFIG_FATFS_USE_FASTSEEK is not set CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set -# CONFIG_FATFS_USE_LABEL is not set -CONFIG_FATFS_LINK_LOCK=y # end of FAT Filesystem support # @@ -1209,18 +1160,13 @@ CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 # CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" -# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set -CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y -CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set -# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set -# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set # end of Kernel # @@ -1248,7 +1194,6 @@ CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_DEBUG_OCDAWARE=y CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y -CONFIG_FREERTOS_NUMBER_OF_CORES=1 # end of FreeRTOS # @@ -1395,7 +1340,6 @@ CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 CONFIG_LWIP_TCP_WND_DEFAULT=5760 CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 -CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 CONFIG_LWIP_TCP_QUEUE_OOSEQ=y CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 @@ -1519,7 +1463,6 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set # CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set -# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 # end of Certificate Bundle @@ -1528,7 +1471,6 @@ CONFIG_MBEDTLS_CMAC_C=y CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_AES_USE_INTERRUPT=y CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 -CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y CONFIG_MBEDTLS_HARDWARE_MPI=y CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 @@ -1732,7 +1674,6 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # # Features here require specific hardware (READ DOCS FIRST!) # -CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -1873,17 +1814,6 @@ CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set # end of Wi-Fi Provisioning Manager -# -# CMake Utilities -# -# CONFIG_CU_RELINKER_ENABLE is not set -# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set -CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y -# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set -# CONFIG_CU_GCC_LTO_ENABLE is not set -# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set -# end of CMake Utilities - # # LittleFS # @@ -1910,6 +1840,17 @@ CONFIG_LITTLEFS_MALLOC_STRATEGY_DEFAULT=y # CONFIG_LITTLEFS_MALLOC_STRATEGY_INTERNAL is not set CONFIG_LITTLEFS_ASSERTS=y # end of LittleFS + +# +# CMake Utilities +# +# CONFIG_CU_RELINKER_ENABLE is not set +# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set +CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y +# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set +# CONFIG_CU_GCC_LTO_ENABLE is not set +# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set +# end of CMake Utilities # end of Component config # CONFIG_IDF_EXPERIMENTAL_FEATURES is not set @@ -1949,17 +1890,15 @@ CONFIG_STACK_CHECK_NONE=y # CONFIG_ESP32_APPTRACE_DEST_TRAX is not set CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_MCPWM_ISR_IN_IRAM is not set CONFIG_SW_COEXIST_ENABLE=y CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y # CONFIG_EXTERNAL_COEX_ENABLE is not set # CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set -# CONFIG_MCPWM_ISR_IN_IRAM is not set # CONFIG_EVENT_LOOP_PROFILING is not set CONFIG_POST_EVENTS_FROM_ISR=y CONFIG_POST_EVENTS_FROM_IRAM_ISR=y -CONFIG_GDBSTUB_SUPPORT_TASKS=y -CONFIG_GDBSTUB_MAX_TASKS=32 # CONFIG_OTA_ALLOW_HTTP is not set # CONFIG_ESP_SYSTEM_PD_FLASH is not set CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y