├── .clang-format ├── .clang-tidy ├── .github ├── CODE_OF_CONDUCT.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── config.yml ├── SUPPORT.md ├── stale.yml └── workflows │ ├── dev_release.yml │ ├── github-releases-to-discord.yml │ ├── pr_check.yml │ ├── sonar_check.yml │ ├── stable_release.yml │ ├── stale_issues.yml │ └── test_release.yml ├── .gitignore ├── .markdownlint.json ├── .prettierignore ├── .prettierrc ├── .sonarlint └── connectedMode.json ├── .vscode └── settings.json ├── CHANGELOG.md ├── CHANGELOG_LATEST.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── boards ├── c3_mini_4M.json ├── esp32dev.json ├── s2_4M_P.json ├── s3_16M_P.json ├── s3_32M_P.json ├── s_16M.json ├── s_16M_P.json └── s_4M.json ├── cspell.json ├── data └── pre_load.json ├── docs ├── Modbus-Entity-Registers.md ├── dump_entities.csv └── dump_telegrams.csv ├── factory_settings.ini ├── interface ├── .env.development ├── .prettierignore ├── .typesafe-i18n.json ├── eslint.config.js ├── index.html ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── progmem-generator.js ├── public │ ├── app │ │ ├── icon.png │ │ └── manifest.json │ ├── css │ │ └── roboto.css │ ├── favicon.ico │ └── fonts │ │ └── re.woff2 ├── src │ ├── App.tsx │ ├── AppRouting.tsx │ ├── AuthenticatedRouting.tsx │ ├── CustomTheme.tsx │ ├── SignIn.tsx │ ├── api │ │ ├── ap.ts │ │ ├── app.ts │ │ ├── endpoints.ts │ │ ├── mqtt.ts │ │ ├── network.ts │ │ ├── ntp.ts │ │ ├── security.ts │ │ ├── system.ts │ │ └── unpack.ts │ ├── app │ │ ├── main │ │ │ ├── CustomEntities.tsx │ │ │ ├── CustomEntitiesDialog.tsx │ │ │ ├── Customizations.tsx │ │ │ ├── CustomizationsDialog.tsx │ │ │ ├── Dashboard.tsx │ │ │ ├── DeviceIcon.tsx │ │ │ ├── Devices.tsx │ │ │ ├── DevicesDialog.tsx │ │ │ ├── EntityMaskToggle.tsx │ │ │ ├── Help.tsx │ │ │ ├── Modules.tsx │ │ │ ├── ModulesDialog.tsx │ │ │ ├── OptionIcon.tsx │ │ │ ├── Scheduler.tsx │ │ │ ├── SchedulerDialog.tsx │ │ │ ├── Sensors.tsx │ │ │ ├── SensorsAnalogDialog.tsx │ │ │ ├── SensorsTemperatureDialog.tsx │ │ │ ├── deviceValue.ts │ │ │ ├── types.ts │ │ │ └── validators.ts │ │ ├── settings │ │ │ ├── APSettings.tsx │ │ │ ├── ApplicationSettings.tsx │ │ │ ├── DownloadUpload.tsx │ │ │ ├── MqttSettings.tsx │ │ │ ├── NTPSettings.tsx │ │ │ ├── Settings.tsx │ │ │ ├── TZ.tsx │ │ │ ├── network │ │ │ │ ├── Network.tsx │ │ │ │ ├── NetworkSettings.tsx │ │ │ │ ├── WiFiConnectionContext.tsx │ │ │ │ ├── WiFiNetworkScanner.tsx │ │ │ │ └── WiFiNetworkSelector.tsx │ │ │ └── security │ │ │ │ ├── GenerateToken.tsx │ │ │ │ ├── ManageUsers.tsx │ │ │ │ ├── Security.tsx │ │ │ │ ├── SecuritySettings.tsx │ │ │ │ └── User.tsx │ │ └── status │ │ │ ├── APStatus.tsx │ │ │ ├── Activity.tsx │ │ │ ├── HardwareStatus.tsx │ │ │ ├── MqttStatus.tsx │ │ │ ├── NTPStatus.tsx │ │ │ ├── NetworkStatus.tsx │ │ │ ├── Status.tsx │ │ │ ├── SystemLog.tsx │ │ │ ├── SystemMonitor.tsx │ │ │ ├── Version.tsx │ │ │ └── bbqkees.svg │ ├── components │ │ ├── ButtonRow.tsx │ │ ├── ButtonTooltip.tsx │ │ ├── MessageBox.tsx │ │ ├── SectionContent.tsx │ │ ├── index.ts │ │ ├── inputs │ │ │ ├── BlockFormControlLabel.tsx │ │ │ ├── LanguageSelector.tsx │ │ │ ├── ValidatedPasswordField.tsx │ │ │ ├── ValidatedTextField.tsx │ │ │ └── index.ts │ │ ├── layout │ │ │ ├── Layout.tsx │ │ │ ├── LayoutAppBar.tsx │ │ │ ├── LayoutDrawer.tsx │ │ │ ├── LayoutMenu.tsx │ │ │ ├── LayoutMenuItem.tsx │ │ │ ├── ListMenuItem.tsx │ │ │ ├── context.ts │ │ │ └── index.ts │ │ ├── loading │ │ │ ├── FormLoader.tsx │ │ │ ├── LoadingSpinner.tsx │ │ │ └── index.ts │ │ ├── routing │ │ │ ├── BlockNavigation.tsx │ │ │ ├── RequireAdmin.tsx │ │ │ ├── RequireAuthenticated.tsx │ │ │ ├── RequireUnauthenticated.tsx │ │ │ ├── RouterTabs.tsx │ │ │ ├── authentication.ts │ │ │ └── index.ts │ │ └── upload │ │ │ ├── DragNdrop.tsx │ │ │ ├── LinearProgressWithLabel.tsx │ │ │ ├── SingleUpload.tsx │ │ │ ├── dragNdrop.css │ │ │ └── index.ts │ ├── contexts │ │ └── authentication │ │ │ ├── Authentication.tsx │ │ │ ├── context.ts │ │ │ └── index.ts │ ├── env.ts │ ├── i18n │ │ ├── CZ.svg │ │ ├── DE.svg │ │ ├── FR.svg │ │ ├── GB.svg │ │ ├── IT.svg │ │ ├── NL.svg │ │ ├── NO.svg │ │ ├── PL.svg │ │ ├── SK.svg │ │ ├── SV.svg │ │ ├── TR.svg │ │ ├── cz │ │ │ └── index.ts │ │ ├── de │ │ │ └── index.ts │ │ ├── en │ │ │ └── index.ts │ │ ├── formatters.ts │ │ ├── fr │ │ │ └── index.ts │ │ ├── it │ │ │ └── index.ts │ │ ├── nl │ │ │ └── index.ts │ │ ├── no │ │ │ └── index.ts │ │ ├── pl │ │ │ └── index.ts │ │ ├── sk │ │ │ └── index.ts │ │ ├── sv │ │ │ └── index.ts │ │ └── tr │ │ │ └── index.ts │ ├── index.tsx │ ├── types │ │ ├── ap.ts │ │ ├── features.ts │ │ ├── index.ts │ │ ├── me.ts │ │ ├── mqtt.ts │ │ ├── network.ts │ │ ├── ntp.ts │ │ ├── security.ts │ │ ├── signin.ts │ │ └── system.ts │ ├── utils │ │ ├── binding.ts │ │ ├── file.ts │ │ ├── index.ts │ │ ├── props.ts │ │ ├── route.ts │ │ ├── submit.ts │ │ ├── time.ts │ │ ├── useInterval.ts │ │ ├── usePersistState.ts │ │ └── useRest.ts │ ├── validators │ │ ├── ap.ts │ │ ├── authentication.ts │ │ ├── index.ts │ │ ├── mqtt.ts │ │ ├── network.ts │ │ ├── ntp.ts │ │ ├── security.ts │ │ └── shared.ts │ └── vite-env.d.ts ├── tsconfig.json └── vite.config.ts ├── lib ├── OneWire │ ├── OneWire.cpp │ └── OneWire.h ├── PButton │ ├── PButon.cpp │ └── PButton.h ├── eModbus │ ├── README.md │ ├── license.md │ └── src │ │ ├── CoilData.cpp │ │ ├── CoilData.h │ │ ├── Logging.cpp │ │ ├── Logging.h │ │ ├── ModbusBridgeETH.h │ │ ├── ModbusBridgeEthernet.h │ │ ├── ModbusBridgeRTU.h │ │ ├── ModbusBridgeTemp.h │ │ ├── ModbusBridgeWiFi.h │ │ ├── ModbusClient.cpp │ │ ├── ModbusClient.h │ │ ├── ModbusClientRTU.cpp │ │ ├── ModbusClientRTU.h │ │ ├── ModbusClientTCP.cpp │ │ ├── ModbusClientTCP.h │ │ ├── ModbusClientTCPasync.cpp │ │ ├── ModbusClientTCPasync.h │ │ ├── ModbusError.h │ │ ├── ModbusMessage.cpp │ │ ├── ModbusMessage.h │ │ ├── ModbusServer.cpp │ │ ├── ModbusServer.h │ │ ├── ModbusServerETH.h │ │ ├── ModbusServerEthernet.h │ │ ├── ModbusServerRTU.cpp │ │ ├── ModbusServerRTU.h │ │ ├── ModbusServerTCPasync.cpp │ │ ├── ModbusServerTCPasync.h │ │ ├── ModbusServerTCPtemp.h │ │ ├── ModbusServerWiFi.h │ │ ├── ModbusTypeDefs.cpp │ │ ├── ModbusTypeDefs.h │ │ ├── RTUutils.cpp │ │ ├── RTUutils.h │ │ └── options.h ├── espMqttClient │ ├── LICENSE │ ├── README.md │ └── src │ │ ├── Config.h │ │ ├── Helpers.h │ │ ├── Logging.h │ │ ├── MemoryPool │ │ ├── LICENSE │ │ ├── README.md │ │ ├── keywords.txt │ │ ├── library.json │ │ ├── library.properties │ │ └── src │ │ │ ├── Fixed.h │ │ │ ├── MemoryPool.h │ │ │ └── Variable.h │ │ ├── MqttClient.cpp │ │ ├── MqttClient.h │ │ ├── MqttClientSetup.h │ │ ├── Outbox.h │ │ ├── Packets │ │ ├── Constants.h │ │ ├── Packet.cpp │ │ ├── Packet.h │ │ ├── Parser.cpp │ │ ├── Parser.h │ │ ├── RemainingLength.cpp │ │ ├── RemainingLength.h │ │ ├── StringUtil.cpp │ │ └── StringUtil.h │ │ ├── Transport │ │ ├── ClientAsync.cpp │ │ ├── ClientAsync.h │ │ ├── ClientPosix.cpp │ │ ├── ClientPosix.h │ │ ├── ClientPosixIPAddress.cpp │ │ ├── ClientPosixIPAddress.h │ │ ├── ClientSecureSync.cpp │ │ ├── ClientSecureSync.h │ │ ├── ClientSync.cpp │ │ ├── ClientSync.h │ │ └── Transport.h │ │ ├── TypeDefs.cpp │ │ ├── TypeDefs.h │ │ ├── espMqttClient.cpp │ │ ├── espMqttClient.h │ │ ├── espMqttClientAsync.cpp │ │ └── espMqttClientAsync.h ├── semver │ ├── LICENSE │ ├── README.md │ ├── Semver200_comparator.cpp │ ├── Semver200_parser.cpp │ ├── semver200.h │ ├── version.h │ └── version.inl ├── uuid-common │ ├── COPYING │ ├── README.rst │ ├── library.json │ └── src │ │ ├── common.cpp │ │ ├── get_uptime_ms.cpp │ │ ├── loop.cpp │ │ ├── printable_to_string.cpp │ │ └── uuid │ │ └── common.h ├── uuid-console │ ├── COPYING │ ├── README.rst │ ├── library.json │ └── src │ │ ├── command_line.cpp │ │ ├── commands.cpp │ │ ├── commands_iterable.cpp │ │ ├── console.cpp │ │ ├── shell.cpp │ │ ├── shell_log.cpp │ │ ├── shell_loop_all.cpp │ │ ├── shell_print.cpp │ │ ├── shell_prompt.cpp │ │ ├── shell_stream.cpp │ │ └── uuid │ │ └── console.h ├── uuid-log │ ├── COPYING │ ├── README.rst │ ├── library.json │ └── src │ │ ├── format_level_char.cpp │ │ ├── format_level_lowercase.cpp │ │ ├── format_level_uppercase.cpp │ │ ├── format_timestamp_ms.cpp │ │ ├── handler.cpp │ │ ├── levels.cpp │ │ ├── levels_lowercase.cpp │ │ ├── levels_uppercase.cpp │ │ ├── log.cpp │ │ ├── parse_level_lowercase.cpp │ │ ├── parse_level_uppercase.cpp │ │ ├── print_handler.cpp │ │ └── uuid │ │ └── log.h ├── uuid-syslog │ ├── COPYING │ ├── README.rst │ ├── library.json │ └── src │ │ ├── syslog.cpp │ │ └── uuid │ │ └── syslog.h └── uuid-telnet │ ├── COPYING │ ├── README.rst │ ├── library.json │ └── src │ ├── stream.cpp │ ├── telnet.cpp │ └── uuid │ └── telnet.h ├── lib_standalone ├── Arduino.cpp ├── Arduino.h ├── ArduinoJson.h ├── AsyncJson.h ├── AsyncTCP.h ├── ESP32React.h ├── ESPAsyncWebServer.h ├── FS.h ├── FSPersistence.h ├── HTTPClient.h ├── HttpEndpoint.h ├── LittleFS.cpp ├── LittleFS.h ├── ModuleLibrary.cpp ├── ModuleLibrary.h ├── Network.h ├── Preferences.h ├── Print.h ├── Printable.h ├── SecurityManager.h ├── SecuritySettingsService.cpp ├── SecuritySettingsService.h ├── StatefulService.cpp ├── StatefulService.h ├── Stream.h ├── WString.cpp ├── WString.h ├── avr │ └── pgmspace.h ├── emsuart_standalone.cpp └── emsuart_standalone.h ├── media ├── EMS-ESP_logo_dark.png ├── console0.png ├── console1.png ├── console3.png ├── favicon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── site.webmanifest ├── gateway-integration.jpg ├── ha_lovelace.png ├── main-screen.png ├── web_customizations.png ├── web_devices.png ├── web_edit.png ├── web_log.png ├── web_login.png ├── web_mqtt.png ├── web_sensor.png ├── web_settings.png └── web_status.png ├── mock-api ├── README.md ├── mockServer.js ├── package.json ├── pnpm-lock.yaml └── restServer.ts ├── partitions ├── esp32_asym_partition_4M.csv ├── esp32_partition_16M.csv ├── esp32_partition_16M.md ├── esp32_partition_32M.csv ├── esp32_partition_4M.csv └── esp32_partition_debug.csv ├── pio_local.ini_example ├── platformio.ini ├── project-words.txt ├── scripts ├── app-tls-size.py ├── build_interface.py ├── clang-format.py ├── clang-tidy.py ├── cspell.sh ├── echo_progress.py ├── generate-modbus-register-doc.py ├── generate_csv_and_headers.sh ├── helpers.py ├── memory_test.py ├── otatool.py ├── refresh_module_library_native.py ├── rename_fw.py ├── requirements.txt ├── run_memory_test.sh ├── run_native.py ├── run_sonar.sh ├── show_mem.sh ├── strip_csv.py ├── update_all.sh ├── update_modbus_registers.py ├── upload.py └── upload_cli.py ├── sonar-project.properties ├── src ├── ESP32React │ ├── APSettingsService.cpp │ ├── APSettingsService.h │ ├── APStatus.cpp │ ├── APStatus.h │ ├── ArduinoJsonJWT.cpp │ ├── ArduinoJsonJWT.h │ ├── AuthenticationService.cpp │ ├── AuthenticationService.h │ ├── ESP32React.cpp │ ├── ESP32React.h │ ├── FSPersistence.h │ ├── HttpEndpoint.h │ ├── IPUtils.h │ ├── JsonUtils.h │ ├── MqttSettingsService.cpp │ ├── MqttSettingsService.h │ ├── MqttStatus.cpp │ ├── MqttStatus.h │ ├── NTPSettingsService.cpp │ ├── NTPSettingsService.h │ ├── NTPStatus.cpp │ ├── NTPStatus.h │ ├── NetworkSettingsService.cpp │ ├── NetworkSettingsService.h │ ├── NetworkStatus.cpp │ ├── NetworkStatus.h │ ├── SecurityManager.h │ ├── SecuritySettingsService.cpp │ ├── SecuritySettingsService.h │ ├── StatefulService.cpp │ ├── StatefulService.h │ ├── UploadFileService.cpp │ ├── UploadFileService.h │ ├── WiFiScanner.cpp │ └── WiFiScanner.h ├── core │ ├── analogsensor.cpp │ ├── analogsensor.h │ ├── command.cpp │ ├── command.h │ ├── common.h │ ├── console.cpp │ ├── console.h │ ├── console_stream.h │ ├── default_settings.h │ ├── device_library.h │ ├── emsdevice.cpp │ ├── emsdevice.h │ ├── emsdevicevalue.cpp │ ├── emsdevicevalue.h │ ├── emsesp.cpp │ ├── emsesp.h │ ├── emsfactory.h │ ├── helpers.cpp │ ├── helpers.h │ ├── locale_common.h │ ├── locale_translations.h │ ├── main.cpp │ ├── modbus.cpp │ ├── modbus.h │ ├── modbus_entity_parameters.hpp │ ├── mqtt.cpp │ ├── mqtt.h │ ├── roomcontrol.cpp │ ├── roomcontrol.h │ ├── shower.cpp │ ├── shower.h │ ├── shuntingYard.hpp │ ├── system.cpp │ ├── system.h │ ├── telegram.cpp │ ├── telegram.h │ ├── temperaturesensor.cpp │ └── temperaturesensor.h ├── devices │ ├── alert.cpp │ ├── alert.h │ ├── boiler.cpp │ ├── boiler.h │ ├── connect.cpp │ ├── connect.h │ ├── controller.cpp │ ├── controller.h │ ├── extension.cpp │ ├── extension.h │ ├── gateway.cpp │ ├── gateway.h │ ├── generic.cpp │ ├── generic.h │ ├── heatpump.cpp │ ├── heatpump.h │ ├── heatsource.cpp │ ├── heatsource.h │ ├── mixer.cpp │ ├── mixer.h │ ├── pool.cpp │ ├── pool.h │ ├── solar.cpp │ ├── solar.h │ ├── switch.cpp │ ├── switch.h │ ├── thermostat.cpp │ ├── thermostat.h │ ├── ventilation.cpp │ ├── ventilation.h │ ├── water.cpp │ └── water.h ├── emsesp_version.h ├── test │ ├── test.cpp │ └── test.h ├── uart │ ├── emsuart_esp32.cpp │ └── emsuart_esp32.h └── web │ ├── WebAPIService.cpp │ ├── WebAPIService.h │ ├── WebActivityService.cpp │ ├── WebActivityService.h │ ├── WebCustomEntityService.cpp │ ├── WebCustomEntityService.h │ ├── WebCustomizationService.cpp │ ├── WebCustomizationService.h │ ├── WebDataService.cpp │ ├── WebDataService.h │ ├── WebLogService.cpp │ ├── WebLogService.h │ ├── WebModulesService.cpp │ ├── WebModulesService.h │ ├── WebSchedulerService.cpp │ ├── WebSchedulerService.h │ ├── WebSettingsService.cpp │ ├── WebSettingsService.h │ ├── WebStatusService.cpp │ └── WebStatusService.h └── test ├── test_api ├── api_test.http ├── api_test.sh ├── test_api.cpp ├── test_api.h └── test_shuntingYard.hpp ├── test_data └── custom_support.json ├── test_modbus └── modbus_test.h └── unity_config.h /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: LLVM 3 | UseTab: Never 4 | IndentWidth: 4 5 | ColumnLimit: 160 6 | TabWidth: 4 7 | #BreakBeforeBraces: Custom 8 | BraceWrapping: 9 | AfterControlStatement: false 10 | AfterFunction: false 11 | AfterClass: true 12 | AfterEnum: true 13 | BeforeElse: false 14 | ReflowComments: false 15 | AlignAfterOpenBracket: Align # If true, horizontally aligns arguments after an open bracket. 16 | AlignConsecutiveAssignments: true # This will align the assignment operators of consecutive lines 17 | AlignConsecutiveDeclarations: true # This will align the declaration names of consecutive lines 18 | AlignTrailingComments: true 19 | AllowAllParametersOfDeclarationOnNextLine: false 20 | AllowShortBlocksOnASingleLine: false 21 | AllowShortFunctionsOnASingleLine: false 22 | AllowShortIfStatementsOnASingleLine: false 23 | AllowShortLoopsOnASingleLine: false 24 | #AlwaysBreakAfterReturnType: TopLevel 25 | AlwaysBreakTemplateDeclarations: true # If true, always break after the template<...> of a template declaration 26 | BinPackArguments: false 27 | BinPackParameters: false 28 | BreakBeforeBinaryOperators: NonAssignment 29 | BreakConstructorInitializersBeforeComma: true # Always break constructor initializers before commas and align the commas with the colon. 30 | ExperimentalAutoDetectBinPacking: false 31 | KeepEmptyLinesAtTheStartOfBlocks: false 32 | MaxEmptyLinesToKeep: 4 33 | PenaltyBreakBeforeFirstCallParameter: 200 34 | PenaltyExcessCharacter: 10 35 | PointerAlignment: Middle 36 | SpaceAfterCStyleCast: false 37 | SpaceBeforeAssignmentOperators: true 38 | SpacesInCStyleCastParentheses: false 39 | SpacesInParentheses: false 40 | DerivePointerAlignment: false 41 | SortIncludes: false -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://www.paypal.me/prderbyshire/2 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem Report/Change Request 3 | about: Create a Report to help us improve 4 | --- 5 | 6 | 13 | 14 | ### DESCRIPTION 15 | 16 | _A clear and concise description of what the problem is or the change requested._ 17 | 18 | ### REQUESTED INFORMATION 19 | 20 | _Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!_ 21 | 22 | - [ ] Searched the issue in [issues](https://github.com/emsesp/EMS-ESP32/issues) 23 | - [ ] Searched the issue in [discussions](https://github.com/emsesp/EMS-ESP32/discussions) 24 | - [ ] Searched the issue in the [docs](https://docs.emsesp.org/Troubleshooting/) 25 | - [ ] Searched the issue in the [chat](https://discord.gg/3J3GgnzpyT) 26 | - [ ] Provide the System information in the area below, taken from `http:///api/system` 27 | 28 | ```json 29 | Paste System information here.... 30 | 31 | 32 | ``` 33 | 34 | ### TO REPRODUCE 35 | 36 | _Steps to reproduce the behavior:_ 37 | 38 | ### EXPECTED BEHAVIOUR 39 | 40 | _A clear and concise description of what you expected to happen._ 41 | 42 | ### SCREENSHOTS 43 | 44 | _If applicable, add screenshots to help explain your issue._ 45 | 46 | ### ADDITIONAL CONTEXT 47 | 48 | _Add any other context about the issue here._ 49 | 50 | **(Please remember to close the issue when it has been addressed)** 51 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: EMS-ESP Docs 4 | url: https://docs.emsesp.org 5 | about: All the information related to EMS-ESP. 6 | - name: EMS-ESP Discussions and Support 7 | url: https://github.com/emsesp/EMS-ESP32/discussions 8 | about: EMS-ESP usage Questions, Feature Requests and Projects. 9 | - name: EMS-ESP Users Chat 10 | url: https://discord.gg/3J3GgnzpyT 11 | about: Chat for feedback, questions and troubleshooting. 12 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an Issue or Pull Request becomes stale 2 | daysUntilStale: 40 3 | 4 | # Number of days of inactivity before a stale Issue or Pull Request is closed. 5 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 6 | daysUntilClose: 5 7 | 8 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 9 | exemptLabels: 10 | - pinned 11 | - security 12 | - enhancement 13 | - bug 14 | 15 | # Set to true to ignore issues in a project (defaults to false) 16 | exemptProjects: false 17 | 18 | # Set to true to ignore issues in a milestone (defaults to false) 19 | exemptMilestones: false 20 | 21 | # Label to use when marking as stale 22 | staleLabel: stale 23 | 24 | # Comment to post when marking as stale. Set to `false` to disable 25 | markComment: > 26 | This issue has been automatically marked as stale because it has not had 27 | recent activity. It will be closed if no further activity occurs. Thank you 28 | for your contributions. 29 | # Comment to post when removing the stale label. 30 | # unmarkComment: > 31 | # Your comment here. 32 | 33 | # Comment to post when closing a stale Issue or Pull Request. 34 | closeComment: > 35 | This issue will be auto-closed because there hasn't been any activity for a few months. Feel free to open a new one if you still experience this problem. 36 | # Limit the number of actions per hour, from 1-30. Default is 30 37 | limitPerRun: 30 38 | 39 | # Limit to only `issues` or `pulls` 40 | #only: issues -------------------------------------------------------------------------------- /.github/workflows/github-releases-to-discord.yml: -------------------------------------------------------------------------------- 1 | name: 'Publish releases to discord' 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | github-releases-to-discord: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | 14 | - name: GitHub Releases To Discord 15 | uses: SethCohen/github-releases-to-discord@v1.13.1 16 | with: 17 | webhook_url: ${{ secrets.WEBHOOK_URL }} 18 | color: '2105893' 19 | username: 'Release Changelog' 20 | avatar_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png' 21 | content: '||@everyone||' 22 | footer_title: 'Changelog' 23 | footer_icon_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png' 24 | footer_timestamp: true 25 | -------------------------------------------------------------------------------- /.github/workflows/pr_check.yml: -------------------------------------------------------------------------------- 1 | name: 'Pre-check on PR' 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: dev 7 | paths: 8 | - '**.c' 9 | - '**.cpp' 10 | - '**.h' 11 | - '**.hpp' 12 | - '**.json' 13 | - '**.py' 14 | - '**.md' 15 | - '.github/workflows/pr_check.yml' 16 | 17 | jobs: 18 | pre-release: 19 | name: 'Automatic pre-release build' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout repository 23 | uses: actions/checkout@v4 24 | 25 | - name: Install python 3.11 26 | uses: actions/setup-python@v5 27 | with: 28 | python-version: '3.11' 29 | 30 | - name: Install PlatformIO 31 | run: | 32 | pip install wheel 33 | pip install -U platformio 34 | 35 | - name: Build native 36 | run: | 37 | platformio run -e native 38 | -------------------------------------------------------------------------------- /.github/workflows/sonar_check.yml: -------------------------------------------------------------------------------- 1 | # see https://github.com/marketplace/actions/sonarcloud-scan-for-c-and-c#usage 2 | name: Sonar Check 3 | 4 | on: 5 | push: 6 | branches: 7 | - dev 8 | # pull_request: 9 | # types: [opened, synchronize, reopened] 10 | 11 | jobs: 12 | build: 13 | name: Build and analyze 14 | if: github.repository == 'emsesp/EMS-ESP32' 15 | runs-on: ubuntu-latest 16 | env: 17 | BUILD_WRAPPER_OUT_DIR: bw-output 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Install sonar-scanner and build-wrapper 25 | uses: SonarSource/sonarcloud-github-c-cpp@v2 26 | 27 | - name: Run build-wrapper 28 | run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all 29 | 30 | - name: Run sonar-scanner 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 34 | run: sonar-scanner --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" 35 | -------------------------------------------------------------------------------- /.github/workflows/stable_release.yml: -------------------------------------------------------------------------------- 1 | name: 'Build stable release' 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | tags: 10 | - 'v*' 11 | 12 | jobs: 13 | tagged-release: 14 | name: 'Build Stable Release' 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Install python 3.13 19 | uses: actions/setup-python@v5 20 | with: 21 | python-version: '3.13' 22 | 23 | - name: Install Node.js 22 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: 22 27 | 28 | - name: Checkout repository 29 | uses: actions/checkout@v4 30 | 31 | - name: Enable Corepack 32 | run: corepack enable pnpm 33 | 34 | - name: Install PlatformIO 35 | run: | 36 | python -m pip install --upgrade pip 37 | pip install -U platformio 38 | 39 | - name: Build the WebUI 40 | run: | 41 | cd interface 42 | pnpm install 43 | pnpm typesafe-i18n --no-watch 44 | sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts 45 | pnpm build 46 | pnpm webUI 47 | 48 | - name: Build all PIO target environments 49 | run: | 50 | platformio run 51 | env: 52 | NO_BUILD_WEBUI: true 53 | 54 | - name: Create GitHub Release 55 | uses: emsesp/action-automatic-releases@v1.0.0 56 | with: 57 | repo_token: '${{ secrets.GITHUB_TOKEN }}' 58 | prerelease: false 59 | files: | 60 | CHANGELOG.md 61 | ./build/firmware/*.* 62 | -------------------------------------------------------------------------------- /.github/workflows/stale_issues.yml: -------------------------------------------------------------------------------- 1 | name: "Mark or close stale issues and PRs" 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v9 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | days-before-stale: 30 15 | days-before-close: 5 16 | stale-issue-message: "This issue is stale because it has been open 30 days with no activity. Remove stale label or comment otherwise this will be closed in 5 days." 17 | stale-pr-message: "This PR has been automatically marked as stale because there has been no activity in last 30 days. It will be closed if no further activity occurs. Thank you for your contributions." 18 | close-issue-message: "This issue was closed because it has been stalled for 5 days with no activity." 19 | close-pr-message: "This PR was automatically closed because of being stale." 20 | stale-pr-label: "stale" 21 | stale-issue-label: "stale" 22 | exempt-issue-labels: "bug,enhancement,pinned,security" 23 | exempt-pr-labels: "bug,enhancement,pinned,security" 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode/c_cpp_properties.json 3 | .vscode/extensions.json 4 | .vscode/launch.json 5 | .vscode/settings.json 6 | 7 | # c++ compiling 8 | .clang_complete 9 | .gcc-flags.json 10 | cppcheck.out.xml 11 | 12 | # platformio 13 | .pio 14 | pio_local.ini 15 | 16 | # OS specific 17 | .DS_Store 18 | *Thumbs.db 19 | 20 | # web specific 21 | build/ 22 | dist/ 23 | /data/www 24 | /interface/build 25 | node_modules 26 | /interface/.eslintcache 27 | stats.html 28 | *.sln 29 | *.sw? 30 | .pnp.* 31 | analyse.html 32 | interface/vite.config.ts.timestamp* 33 | *.local 34 | src/ESP32React/WWWData.h 35 | 36 | # i18n generated files 37 | interface/src/i18n/i18n-react.tsx 38 | interface/src/i18n/i18n-types.ts 39 | interface/src/i18n/i18n-util.ts 40 | interface/src/i18n/i18n-util.sync.ts 41 | interface/src/i18n/i18n-util.async.ts 42 | 43 | # scripts 44 | test.sh 45 | scripts/run.sh 46 | scripts/__pycache__ 47 | scripts/stackdmp.txt 48 | 49 | # sonar 50 | .scannerwork/ 51 | sonar/ 52 | bw-output/ 53 | 54 | # standalone executable for testing 55 | emsesp 56 | interface/tsconfig.tsbuildinfo 57 | 58 | # python virtual environment 59 | venv/ 60 | 61 | # cspell 62 | words-found-verbose.txt 63 | 64 | # sonarlint 65 | compile_commands.json 66 | 67 | # pioarduino + hybrid 68 | managed_components 69 | dependencies.lock 70 | CMakeLists.txt 71 | .dummy/* 72 | logs/* 73 | sdkconfig.* 74 | sdkconfig_tasmota_esp32 75 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD033": false, 3 | "MD013": false, 4 | "MD045": false, 5 | "MD041": false 6 | } -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | */node_modules/ 2 | build/ 3 | dist/* 4 | interface/src/i18n/* 5 | 6 | .typesafe-i18n.json -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@trivago/prettier-plugin-sort-imports"], 3 | "trailingComma": "none", 4 | "tabWidth": 2, 5 | "semi": true, 6 | "singleQuote": true, 7 | "printWidth": 85, 8 | "bracketSpacing": true, 9 | "importOrder": ["^react", "^@mui/(.*)$", "^api*/(.*)$", "", "^[./]"], 10 | "importOrderSeparation": true, 11 | "importOrderSortSpecifiers": true, 12 | "importOrderGroupNamespaceSpecifiers": true 13 | } -------------------------------------------------------------------------------- /.sonarlint/connectedMode.json: -------------------------------------------------------------------------------- 1 | { 2 | "sonarCloudOrganization": "emsesp", 3 | "projectKey": "emsesp_EMS-ESP32" 4 | } -------------------------------------------------------------------------------- /CHANGELOG_LATEST.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | For more details go to [docs.emsesp.org](https://docs.emsesp.org/). 4 | 5 | ## [3.7.3] 6 | 7 | ## Added 8 | 9 | - analogsensor types: NTC and RGB-Led 10 | - Flag for HMC310 [#2465](https://github.com/emsesp/EMS-ESP32/issues/2465) 11 | - boiler auxheatersource [#2489](https://github.com/emsesp/EMS-ESP32/discussions/2489) 12 | - thermostat last error for RC100/300 [#2501](https://github.com/emsesp/EMS-ESP32/issues/2501) 13 | - boiler 0xC6 telegram [#1963](https://github.com/emsesp/EMS-ESP32/issues/1963) 14 | - CS6800i changes [#2448](https://github.com/emsesp/EMS-ESP32/issues/2448), [#2449](https://github.com/emsesp/EMS-ESP32/issues/2449) 15 | - charging pump [#2544](https://github.com/emsesp/EMS-ESP32/issues/2544) 16 | 17 | ## Fixed 18 | 19 | - dhw/switchtime [#2490](https://github.com/emsesp/EMS-ESP32/issues/2490) 20 | - switch to secure mqtt [#2492](https://github.com/emsesp/EMS-ESP32/issues/2492) 21 | - update link buttons [#2497](https://github.com/emsesp/EMS-ESP32/issues/2497) 22 | - refresh scheduler states [#2502](https://github.com/emsesp/EMS-ESP32/discussions/2502) 23 | - also rebuild HA config on mqtt connect for scheduler, custom and shower 24 | - FB100 controls the hc, not the master [#2510](https://github.com/emsesp/EMS-ESP32/issues/2510) 25 | - IPM DHW module, [#2524](https://github.com/emsesp/EMS-ESP32/issues/2524) 26 | - charge optimization [#2543](https://github.com/emsesp/EMS-ESP32/issues/2543) 27 | - shower active state retained, shows correctly in HA 28 | 29 | ## Changed 30 | 31 | - show console log with ISO date/time [#2533](https://github.com/emsesp/EMS-ESP32/discussions/2533) 32 | -------------------------------------------------------------------------------- /boards/c3_mini_4M.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "esp32c3_out.ld" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": [ 8 | "-DTASMOTA_SDK", 9 | "-DARDUINO_LOLIN_C3_MINI", 10 | "-DARDUINO_USB_MODE=1", 11 | "-DARDUINO_USB_CDC_ON_BOOT=1" 12 | ], 13 | "f_cpu": "160000000L", 14 | "f_flash": "80000000L", 15 | "flash_mode": "qio", 16 | "hwids": [ 17 | [ 18 | "0X303A", 19 | "0x1001" 20 | ] 21 | ], 22 | "mcu": "esp32c3", 23 | "variant": "lolin_c3_mini" 24 | }, 25 | "connectivity": [ 26 | "wifi" 27 | ], 28 | "debug": { 29 | "openocd_target": "esp32c3.cfg" 30 | }, 31 | "frameworks": [ 32 | "arduino", 33 | "espidf" 34 | ], 35 | "name": "WEMOS LOLIN C3 Mini", 36 | "upload": { 37 | "flash_size": "4MB", 38 | "maximum_ram_size": 327680, 39 | "maximum_size": 4194304, 40 | "require_upload_port": true, 41 | "speed": 460800 42 | }, 43 | "url": "https://www.wemos.cc/en/latest/c3/c3_mini.html", 44 | "vendor": "WEMOS" 45 | } -------------------------------------------------------------------------------- /boards/esp32dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "core": "esp32", 4 | "f_cpu": "240000000L", 5 | "f_flash": "40000000L", 6 | "flash_mode": "dio", 7 | "mcu": "esp32", 8 | "variant": "esp32" 9 | }, 10 | "connectivity": [ 11 | "wifi", 12 | "ethernet" 13 | ], 14 | "debug": { 15 | "openocd_board": "esp32.cfg" 16 | }, 17 | "frameworks": [ 18 | "arduino", 19 | "espidf" 20 | ], 21 | "name": "Espressif ESP32 Dev Module", 22 | "upload": { 23 | "flash_size": "16MB", 24 | "maximum_ram_size": 327680, 25 | "maximum_size": 16777216, 26 | "require_upload_port": true, 27 | "speed": 460800 28 | }, 29 | "download": { 30 | "speed": 230400 31 | }, 32 | "url": "https://en.wikipedia.org/wiki/ESP32", 33 | "vendor": "Espressif" 34 | } -------------------------------------------------------------------------------- /boards/s2_4M_P.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "esp32s2_out.ld" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": [ 8 | "-DBOARD_HAS_PSRAM", 9 | "-DTASMOTA_SDK", 10 | "-DARDUINO_USB_CDC_ON_BOOT=1", 11 | "-DARDUINO_USB_MODE=0" 12 | ], 13 | "f_cpu": "240000000L", 14 | "f_flash": "80000000L", 15 | "flash_mode": "dio", 16 | "hwids": [ 17 | [ 18 | "0X303A", 19 | "0x80C2" 20 | ] 21 | ], 22 | "mcu": "esp32s2", 23 | "variant": "lolin_s2_mini" 24 | }, 25 | "connectivity": [ 26 | "wifi" 27 | ], 28 | "debug": { 29 | "openocd_target": "esp32s2.cfg" 30 | }, 31 | "frameworks": [ 32 | "arduino", 33 | "espidf" 34 | ], 35 | "name": "WEMOS LOLIN S2 Mini", 36 | "upload": { 37 | "flash_size": "4MB", 38 | "maximum_ram_size": 327680, 39 | "maximum_size": 4194304, 40 | "use_1200bps_touch": true, 41 | "wait_for_upload_port": true, 42 | "require_upload_port": true, 43 | "speed": 921600 44 | }, 45 | "url": "https://www.wemos.cc/en/latest/s2/s2_mini.html", 46 | "vendor": "WEMOS" 47 | } -------------------------------------------------------------------------------- /boards/s3_16M_P.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino": { 4 | "ldscript": "esp32s3_out.ld", 5 | "memory_type": "qio_opi" 6 | }, 7 | "core": "esp32", 8 | "extra_flags": [ 9 | "-DBOARD_HAS_PSRAM", 10 | "-DARDUINO_USB_MODE=1", 11 | "-DARDUINO_USB_CDC_ON_BOOT=1", 12 | "-DARDUINO_RUNNING_CORE=1", 13 | "-DARDUINO_EVENT_RUNNING_CORE=1" 14 | ], 15 | "f_cpu": "240000000L", 16 | "f_flash": "80000000L", 17 | "flash_mode": "qio", 18 | "mcu": "esp32s3", 19 | "variant": "esp32s3" 20 | }, 21 | "connectivity": [ 22 | "wifi" 23 | ], 24 | "debug": { 25 | "openocd_target": "esp32s3.cfg" 26 | }, 27 | "frameworks": [ 28 | "arduino", 29 | "espidf" 30 | ], 31 | "name": "Espressif ESP32-S3 16M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS", 32 | "upload": { 33 | "flash_size": "16MB", 34 | "maximum_ram_size": 327680, 35 | "maximum_size": 16777216, 36 | "require_upload_port": true, 37 | "speed": 460800 38 | }, 39 | "download": { 40 | "speed": 230400 41 | }, 42 | "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", 43 | "vendor": "Espressif" 44 | } -------------------------------------------------------------------------------- /boards/s3_32M_P.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "memory_type": "opi_opi" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": "-DBOARD_HAS_PSRAM", 8 | "f_cpu": "240000000L", 9 | "f_flash": "80000000L", 10 | "flash_mode": "opi", 11 | "mcu": "esp32s3", 12 | "variant": "esp32s3" 13 | }, 14 | "connectivity": [ 15 | "wifi" 16 | ], 17 | "debug": { 18 | "openocd_target": "esp32s3.cfg" 19 | }, 20 | "frameworks": [ 21 | "arduino", 22 | "espidf" 23 | ], 24 | "name": "Espressif ESP32-S3 32M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS", 25 | "upload": { 26 | "flash_size": "32MB", 27 | "maximum_ram_size": 327680, 28 | "maximum_size": 16777216, 29 | "require_upload_port": true, 30 | "speed": 460800 31 | }, 32 | "download": { 33 | "speed": 230400 34 | }, 35 | "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", 36 | "vendor": "Espressif" 37 | } -------------------------------------------------------------------------------- /boards/s_16M.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "core": "esp32", 4 | "extra_flags": "-DTASMOTA_SDK", 5 | "f_cpu": "240000000L", 6 | "f_flash": "40000000L", 7 | "flash_mode": "dio", 8 | "mcu": "esp32", 9 | "variant": "esp32" 10 | }, 11 | "connectivity": [ 12 | "wifi", 13 | "ethernet" 14 | ], 15 | "debug": { 16 | "openocd_target": "esp32.cfg" 17 | }, 18 | "frameworks": [ 19 | "arduino", 20 | "espidf" 21 | ], 22 | "name": "Espressif ESP32 16M Flash, 4608KB Code/OTA, 2MB FS", 23 | "upload": { 24 | "flash_size": "16MB", 25 | "maximum_ram_size": 327680, 26 | "maximum_size": 16777216, 27 | "require_upload_port": true, 28 | "speed": 460800 29 | }, 30 | "download": { 31 | "speed": 230400 32 | }, 33 | "url": "https://en.wikipedia.org/wiki/ESP32", 34 | "vendor": "Espressif" 35 | } -------------------------------------------------------------------------------- /boards/s_16M_P.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "core": "esp32", 4 | "extra_flags": "-DBOARD_HAS_PSRAM", 5 | "f_cpu": "240000000L", 6 | "f_flash": "80000000L", 7 | "flash_mode": "dio", 8 | "mcu": "esp32", 9 | "variant": "esp32" 10 | }, 11 | "connectivity": [ 12 | "wifi", 13 | "ethernet" 14 | ], 15 | "debug": { 16 | "openocd_target": "esp32.cfg" 17 | }, 18 | "frameworks": [ 19 | "arduino", 20 | "espidf" 21 | ], 22 | "name": "Espressif ESP32 16M Flash DIO PSRAM, 4608KB Code/OTA, 2MB FS", 23 | "upload": { 24 | "flash_size": "16MB", 25 | "maximum_ram_size": 327680, 26 | "maximum_size": 16777216, 27 | "require_upload_port": true, 28 | "speed": 460800 29 | }, 30 | "download": { 31 | "speed": 230400 32 | }, 33 | "url": "https://en.wikipedia.org/wiki/ESP32", 34 | "vendor": "Espressif" 35 | } -------------------------------------------------------------------------------- /boards/s_4M.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "core": "esp32", 4 | "extra_flags": "-DTASMOTA_SDK", 5 | "f_cpu": "240000000L", 6 | "f_flash": "40000000L", 7 | "flash_mode": "dio", 8 | "mcu": "esp32", 9 | "variant": "esp32" 10 | }, 11 | "connectivity": [ 12 | "wifi" 13 | ], 14 | "debug": { 15 | "openocd_target": "esp32.cfg" 16 | }, 17 | "frameworks": [ 18 | "arduino", 19 | "espidf" 20 | ], 21 | "name": "Tasmota ESP32 4M Flash, 4608KB Code/OTA, 2MB FS", 22 | "upload": { 23 | "flash_size": "4MB", 24 | "maximum_ram_size": 327680, 25 | "maximum_size": 4194304, 26 | "require_upload_port": true, 27 | "speed": 460800 28 | }, 29 | "download": { 30 | "speed": 230400 31 | }, 32 | "url": "https://en.wikipedia.org/wiki/ESP32", 33 | "vendor": "Espressif" 34 | } -------------------------------------------------------------------------------- /cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", 3 | "version": "0.2", 4 | "dictionaryDefinitions": [ 5 | { 6 | "name": "project-words", 7 | "path": "./project-words.txt", 8 | "addWords": true 9 | } 10 | ], 11 | "dictionaries": ["project-words"], 12 | "ignorePaths": [ 13 | "node_modules", 14 | "compile_commands.json", 15 | "WWWData.h", "**/venv/**", 16 | "lib/eModbus", 17 | "lib/ESPAsyncWebServer", 18 | "lib/espMqttClient", 19 | "analyse.html", 20 | "dist", 21 | "**/*.csv", 22 | "**/*.md", 23 | "**/*.py", 24 | "locale_translations.h", 25 | "TZ.tsx", 26 | "**/*.txt", 27 | "build/**", 28 | "**/i18n/**", 29 | "/project-words.txt", 30 | "Makefile", 31 | "**/*.ini", 32 | "**/*.json", 33 | "src/core/modbus_entity_parameters.hpp", 34 | "sdkconfig.*", 35 | "managed_components/**", 36 | "pnpm-*.yaml" 37 | ] 38 | } -------------------------------------------------------------------------------- /factory_settings.ini: -------------------------------------------------------------------------------- 1 | [factory_settings] 2 | build_flags = 3 | ; WiFi settings 4 | -D FACTORY_WIFI_SSID=\"\" 5 | -D FACTORY_WIFI_PASSWORD=\"\" 6 | -D FACTORY_WIFI_HOSTNAME=\"ems-esp\" 7 | 8 | ; Access point settings 9 | -D FACTORY_AP_PROVISION_MODE=AP_MODE_DISCONNECTED 10 | -D FACTORY_AP_SSID=\"ems-esp\" 11 | -D FACTORY_AP_PASSWORD=\"ems-esp-neo\" 12 | -D FACTORY_AP_LOCAL_IP=\"192.168.4.1\" 13 | -D FACTORY_AP_GATEWAY_IP=\"192.168.4.1\" 14 | -D FACTORY_AP_SUBNET_MASK=\"255.255.255.0\" 15 | 16 | ; User credentials for admin and guest user 17 | -D FACTORY_ADMIN_USERNAME=\"admin\" 18 | -D FACTORY_ADMIN_PASSWORD=\"admin\" 19 | -D FACTORY_GUEST_USERNAME=\"guest\" 20 | -D FACTORY_GUEST_PASSWORD=\"guest\" 21 | 22 | ; NTP settings 23 | -D FACTORY_NTP_ENABLED=false 24 | -D FACTORY_NTP_TIME_ZONE_LABEL=\"Europe/Amsterdam\" 25 | -D FACTORY_NTP_TIME_ZONE_FORMAT=\"CET-1CEST,M3.5.0,M10.5.0/3\" 26 | -D FACTORY_NTP_SERVER=\"time.google.com\" 27 | 28 | ; MQTT settings 29 | -D FACTORY_MQTT_ENABLED=false 30 | -D FACTORY_MQTT_HOST=\"\" 31 | -D FACTORY_MQTT_PORT=1883 32 | -D FACTORY_MQTT_USERNAME=\"\" 33 | -D FACTORY_MQTT_PASSWORD=\"\" 34 | -D FACTORY_MQTT_KEEP_ALIVE=60 35 | -D FACTORY_MQTT_CLEAN_SESSION=false 36 | -D FACTORY_MQTT_MAX_TOPIC_LENGTH=128 37 | 38 | ; JWT Secret 39 | -D FACTORY_JWT_SECRET=\"ems-esp-neo\" 40 | -------------------------------------------------------------------------------- /interface/.env.development: -------------------------------------------------------------------------------- 1 | VITE_ALOVA_TIPS=0 2 | REACT_APP_ALOVA_TIPS=0 -------------------------------------------------------------------------------- /interface/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ 4 | src/i18n/* 5 | 6 | .prettierrc 7 | .typesafe-i18n.json 8 | -------------------------------------------------------------------------------- /interface/.typesafe-i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "adapter": "react", 3 | "baseLocale": "pl", 4 | "$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json" 5 | } -------------------------------------------------------------------------------- /interface/eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import eslint from '@eslint/js'; 3 | import prettierConfig from 'eslint-config-prettier'; 4 | import tseslint from 'typescript-eslint'; 5 | 6 | export default tseslint.config( 7 | eslint.configs.recommended, 8 | ...tseslint.configs.recommendedTypeChecked, 9 | prettierConfig, 10 | { 11 | languageOptions: { 12 | parserOptions: { 13 | project: true, 14 | tsconfigRootDir: import.meta.dirname 15 | } 16 | } 17 | }, 18 | { 19 | ignores: [ 20 | 'dist/*', 21 | '*.mjs', 22 | 'build/*', 23 | '*.js', 24 | '**/*.cjs', 25 | '**/unpack.ts', 26 | 'i18n*.*' 27 | ] 28 | }, 29 | { 30 | rules: { 31 | '@typescript-eslint/no-unsafe-enum-comparison': 'off', 32 | '@typescript-eslint/no-unused-expressions': 'off', 33 | '@typescript-eslint/no-unsafe-assignment': 'off', 34 | '@typescript-eslint/no-unsafe-member-access': 'off', 35 | '@typescript-eslint/no-unsafe-call': 'off', 36 | '@typescript-eslint/no-misused-promises': [ 37 | 'error', 38 | { 39 | checksVoidReturn: false 40 | } 41 | ] 42 | } 43 | } 44 | ); 45 | -------------------------------------------------------------------------------- /interface/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | EMS-ESP 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /interface/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | onlyBuiltDependencies: 2 | - cwebp-bin 3 | - esbuild 4 | - gifsicle 5 | - jpegtran-bin 6 | - mozjpeg 7 | - optipng-bin 8 | - pngquant-bin 9 | -------------------------------------------------------------------------------- /interface/public/app/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emsesp/EMS-ESP32/d04c882590d547510a98725f455eb488dc611585/interface/public/app/icon.png -------------------------------------------------------------------------------- /interface/public/app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EMS-ESP", 3 | "icons": [ 4 | { 5 | "src": "/app/icon.png", 6 | "sizes": "48x48 72x72 96x96 128x128 256x256" 7 | } 8 | ], 9 | "start_url": "/", 10 | "display": "fullscreen", 11 | "orientation": "any" 12 | } 13 | -------------------------------------------------------------------------------- /interface/public/css/roboto.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Uses font-weight 400 (normal) only, no bold, and Latin with a few extra unicode chars. 3 | * This is to keep flash memory to a minimum 4 | * View fonts on https://fonts.google.com/ 5 | * Download woff2 using e.g. https://fonts.googleapis.com/css2?family=Lato or https://fonts.googleapis.com/css2?family=Roboto 6 | */ 7 | @font-face { 8 | font-family: 'Roboto'; 9 | font-style: normal; 10 | font-weight: 400; 11 | /* src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2'); */ 12 | src: 13 | local('Roboto'), 14 | local('Roboto-Regular'), 15 | url(../fonts/re.woff2) format('woff2'); 16 | unicode-range: 17 | U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131, U+0141-0144, 18 | U+0152-0153, U+015A-015B, U+015E-015F, U+0179-017C, U+02BB-02BC, U+02C6, U+02DA, 19 | U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, 20 | U+FEFF, U+FFFD; 21 | } 22 | -------------------------------------------------------------------------------- /interface/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emsesp/EMS-ESP32/d04c882590d547510a98725f455eb488dc611585/interface/public/favicon.ico -------------------------------------------------------------------------------- /interface/public/fonts/re.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emsesp/EMS-ESP32/d04c882590d547510a98725f455eb488dc611585/interface/public/fonts/re.woff2 -------------------------------------------------------------------------------- /interface/src/CustomTheme.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | 3 | import { CssBaseline, ThemeProvider, responsiveFontSizes } from '@mui/material'; 4 | import { createTheme } from '@mui/material/styles'; 5 | 6 | import type { RequiredChildrenProps } from 'utils'; 7 | 8 | export const dialogStyle = { 9 | '& .MuiDialog-paper': { 10 | borderRadius: '8px', 11 | borderColor: '#565656', 12 | borderStyle: 'solid', 13 | borderWidth: '1px' 14 | } 15 | }; 16 | 17 | const theme = responsiveFontSizes( 18 | createTheme({ 19 | typography: { 20 | fontSize: 13 21 | }, 22 | palette: { 23 | mode: 'dark', 24 | secondary: { 25 | main: '#2196f3' // blue[500] 26 | }, 27 | info: { 28 | main: '#607d8b' // blueGrey[500] 29 | }, 30 | text: { 31 | disabled: '#eee' // white 32 | } 33 | } 34 | }) 35 | ); 36 | 37 | const CustomTheme: FC = ({ children }) => ( 38 | 39 | 40 | {children} 41 | 42 | ); 43 | 44 | export default CustomTheme; 45 | -------------------------------------------------------------------------------- /interface/src/api/ap.ts: -------------------------------------------------------------------------------- 1 | import type { APSettingsType, APStatusType } from 'types'; 2 | 3 | import { alovaInstance } from './endpoints'; 4 | 5 | export const readAPStatus = () => alovaInstance.Get('/rest/apStatus'); 6 | export const readAPSettings = () => 7 | alovaInstance.Get('/rest/apSettings'); 8 | export const updateAPSettings = (data: APSettingsType) => 9 | alovaInstance.Post('/rest/apSettings', data); 10 | -------------------------------------------------------------------------------- /interface/src/api/mqtt.ts: -------------------------------------------------------------------------------- 1 | import type { MqttSettingsType, MqttStatusType } from 'types'; 2 | 3 | import { alovaInstance } from './endpoints'; 4 | 5 | export const readMqttStatus = () => 6 | alovaInstance.Get('/rest/mqttStatus'); 7 | export const readMqttSettings = () => 8 | alovaInstance.Get('/rest/mqttSettings'); 9 | export const updateMqttSettings = (data: MqttSettingsType) => 10 | alovaInstance.Post('/rest/mqttSettings', data); 11 | -------------------------------------------------------------------------------- /interface/src/api/network.ts: -------------------------------------------------------------------------------- 1 | import type { NetworkSettingsType, NetworkStatusType, WiFiNetworkList } from 'types'; 2 | 3 | import { alovaInstance } from './endpoints'; 4 | 5 | export const readNetworkStatus = () => 6 | alovaInstance.Get('/rest/networkStatus'); 7 | export const scanNetworks = () => alovaInstance.Get('/rest/scanNetworks'); 8 | export const listNetworks = () => 9 | alovaInstance.Get('/rest/listNetworks', { 10 | timeout: 20000 // 20 seconds 11 | }); 12 | export const readNetworkSettings = () => 13 | alovaInstance.Get('/rest/networkSettings'); 14 | export const updateNetworkSettings = (wifiSettings: NetworkSettingsType) => 15 | alovaInstance.Post('/rest/networkSettings', wifiSettings); 16 | -------------------------------------------------------------------------------- /interface/src/api/ntp.ts: -------------------------------------------------------------------------------- 1 | import type { NTPSettingsType, NTPStatusType, Time } from 'types'; 2 | 3 | import { alovaInstance } from './endpoints'; 4 | 5 | export const readNTPStatus = () => 6 | alovaInstance.Get('/rest/ntpStatus'); 7 | 8 | export const readNTPSettings = () => 9 | alovaInstance.Get('/rest/ntpSettings', {}); 10 | export const updateNTPSettings = (data: NTPSettingsType) => 11 | alovaInstance.Post('/rest/ntpSettings', data); 12 | 13 | export const updateTime = (data: Time) => 14 | alovaInstance.Post