From 73bd096f3739bb094b79aca4a7e2e5f8e4128f40 Mon Sep 17 00:00:00 2001 From: Sebastien L Date: Tue, 18 Mar 2025 17:38:34 -0400 Subject: [PATCH] Start of 5.X work --- .clang-format | 14 + .cproject | 32 - .devcontainer/devcontainer.json | 21 - .gitignore | 7 + .project | 20 - CMakeLists.txt | 184 +- Dockerfile | 222 +- Makefile | 22 - Makefile_std.mk | 3 - buildFirmware.sh | 47 - build_flash_cmd.sh | 113 - components/display/CMakeLists.txt | 2 +- components/display/ILI9341.c | 6 +- components/display/SH1106.c | 4 +- components/display/SSD1306.c | 4 +- components/display/SSD1322.c | 4 +- components/display/SSD132x.c | 6 +- components/display/SSD1351.c | 4 +- components/display/SSD1675.c | 47 +- components/display/ST77xx.c | 6 +- components/display/core/gds.c | 6 +- components/display/core/gds.h | 6 +- components/display/core/gds_font.c | 5 +- components/display/display.c | 47 +- components/driver_bt/bt_app_core.c | 113 +- components/driver_bt/bt_app_core.h | 37 +- components/driver_bt/bt_app_sink.c | 12 +- components/driver_bt/bt_app_source.c | 141 +- components/led_strip/CMakeLists.txt | 2 +- components/led_strip/led_vu.c | 19 +- components/metrics/CMakeLists.txt | 2 +- components/metrics/Metrics.cpp | 3 +- components/platform_config/CMakeLists.txt | 6 +- components/platform_config/Config.cpp | 266 + components/platform_config/Config.h | 49 + components/platform_config/Configurator.cpp | 480 - components/platform_config/Configurator.h | 107 - components/platform_config/Locking.cpp | 45 + components/platform_config/Locking.h | 71 + components/platform_config/PBW.cpp | 272 + components/platform_config/PBW.h | 331 + components/platform_config/WifiList.cpp | 845 + components/platform_config/WifiList.h | 185 + .../platform_config/test/CMakeLists.txt | 20 + .../platform_config/test/DAC_test_extra.proto | 29 + .../test/DAC_test_extra2.proto | 30 + .../test/test_platform_config.cpp | 956 + components/platform_console/CMakeLists.txt | 2 +- .../app_squeezelite/CMakeLists.txt | 2 +- .../app_squeezelite/cmd_squeezelite.c | 203 +- components/platform_console/cmd_config.c | 1836 +- components/platform_console/cmd_i2ctools.c | 95 +- components/platform_console/cmd_system.c | 946 +- components/platform_console/cmd_system.h | 4 +- components/platform_console/cmd_wifi.c | 2 +- .../platform_console/platform_console.c | 686 +- .../platform_console/platform_console.h | 1 + .../platform_console/test/test_system.c | 2 +- components/raop/CMakeLists.txt | 2 +- components/raop/raop_sink.c | 2 +- components/services/CMakeLists.txt | 3 +- components/services/accessors.c | 56 +- components/services/accessors.h | 25 +- components/services/audio_controls.c | 980 +- components/services/audio_controls.h | 31 +- components/services/battery.c | 8 +- components/services/buttons.c | 656 +- components/services/globdefs.h | 3 - components/services/gpio_exp.c | 18 +- components/services/gpio_exp.h | 4 + components/services/led.c | 63 +- components/services/led.h | 4 +- components/services/messaging.c | 527 +- components/services/monitor.c | 16 +- components/services/monitor.h | 10 +- components/services/services.c | 451 +- components/services/services.h | 4 +- components/services/system_time.c | 44 + components/services/system_time.h | 2 + components/spotify/Shim.cpp | 15 +- .../nanopb/generator/nanopb_generator.py | 6 +- .../cspot/bell/external/nanopb/pb_decode.c | 52 +- components/spotify/cspot_sink.c | 3 +- components/squeezelite-ota/component.mk | 10 - components/squeezelite-ota/github.pem | 41 - components/squeezelite-ota/squeezelite-ota.c | 23 +- components/squeezelite-ota/squeezelite-ota.h | 5 +- components/squeezelite/CMakeLists.txt | 4 +- components/squeezelite/ac101/ac101.c | 12 +- components/squeezelite/adac.h | 9 +- components/squeezelite/adac_core.c | 21 +- components/squeezelite/controls.c | 15 +- components/squeezelite/cs4265/cs4265.c | 826 +- components/squeezelite/decode_external.c | 753 +- components/squeezelite/embedded.c | 9 +- components/squeezelite/equalizer.c | 21 +- components/squeezelite/esp32_main.c | 147 +- .../squeezelite/external/dac_external.c | 273 +- components/squeezelite/output_bt.c | 10 +- components/squeezelite/output_embedded.c | 30 +- components/squeezelite/output_i2s.c | 269 +- components/squeezelite/tas57xx/dac_5713.c | 8 +- components/squeezelite/tas57xx/dac_57xx.c | 10 +- components/squeezelite/wm8978/wm8978.c | 8 +- components/targets/targets.c | 5 +- components/telnet/telnet.c | 386 +- components/tools/CMakeLists.txt | 9 +- components/tools/bootstate.cpp | 143 + components/tools/bootstate.h | 126 + components/tools/component.mk | 11 - components/tools/cpp_tools.cpp | 22 + components/tools/cpp_tools.h | 48 + components/tools/perf_trace.h | 30 +- components/tools/platform_esp32.h | 3 +- components/tools/test/CMakeLists.txt | 4 + components/tools/test/test_tools.cpp | 387 + components/tools/tools.c | 564 +- components/tools/tools.h | 355 +- components/tools/tools_http_utils.c | 148 + components/tools/tools_http_utils.h | 100 + components/tools/tools_spiffs_utils.cpp | 383 + components/tools/tools_spiffs_utils.h | 249 + components/tools/trace.c | 79 +- components/tools/trace.h | 50 +- components/wifi-manager/CMakeLists.txt | 6 +- components/wifi-manager/Kconfig.projbuild | 62 +- components/wifi-manager/LICENSE.md | 19 - components/wifi-manager/component.mk | 14 - components/wifi-manager/dns_server.c | 6 +- .../wifi-manager/http_server_handlers.c | 757 +- .../wifi-manager/http_server_handlers.h | 138 +- .../wifi-manager/network_driver_DM9051.c | 34 +- .../wifi-manager/network_driver_LAN8720.c | 33 +- .../wifi-manager/network_driver_W5500.c | 31 +- components/wifi-manager/network_ethernet.c | 96 +- components/wifi-manager/network_ethernet.h | 33 +- components/wifi-manager/network_manager.c | 690 +- components/wifi-manager/network_manager.h | 167 +- .../wifi-manager/network_manager_handlers.c | 1428 +- components/wifi-manager/network_services.h | 24 + components/wifi-manager/network_status.c | 188 - components/wifi-manager/network_status.cpp | 194 + components/wifi-manager/network_status.h | 62 +- components/wifi-manager/network_wifi.c | 960 - components/wifi-manager/network_wifi.cpp | 805 + components/wifi-manager/network_wifi.h | 39 +- .../wifi-manager/webapp/dist/css/index.css | 5 + .../wifi-manager/webapp/dist/css/index.css.gz | Bin 0 -> 8583 bytes .../dist/css/index.e8b465b654eff617dd1c.css | 5 - .../css/index.e8b465b654eff617dd1c.css.gz | Bin 8604 -> 0 bytes .../wifi-manager/webapp/dist/index.html | 2 +- .../wifi-manager/webapp/dist/index.html.gz | Bin 4976 -> 4949 bytes .../webapp/dist/js/index.bundle.js | 2 + .../webapp/dist/js/index.bundle.js.gz | Bin 0 -> 38846 bytes .../webapp/dist/js/index.bundle.js.map | 1 + .../webapp/dist/js/index.dd7cd3.bundle.js | 2 - .../webapp/dist/js/index.dd7cd3.bundle.js.gz | Bin 27809 -> 0 bytes .../webapp/dist/js/index.dd7cd3.bundle.js.map | 1 - .../webapp/dist/js/node_vendors.bundle.js | 2 + .../webapp/dist/js/node_vendors.bundle.js.gz | Bin 0 -> 166729 bytes .../webapp/dist/js/node_vendors.bundle.js.map | 1 + .../dist/js/node_vendors.dd7cd3.bundle.js | 2 - .../dist/js/node_vendors.dd7cd3.bundle.js.gz | Bin 143610 -> 0 bytes .../dist/js/node_vendors.dd7cd3.bundle.js.map | 1 - .../wifi-manager/webapp/dist/src/index.d.ts | 1 + .../webapp/dist/src/js/proto/AirPlay_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Artwork_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Battery_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Buttons_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Common_pb.d.ts | 1 + .../webapp/dist/src/js/proto/DAC_pb.d.ts | 1 + .../dist/src/js/proto/DacControlSet_pb.d.ts | 1 + .../dist/src/js/proto/DataRequest_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Devices_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Display_pb.d.ts | 1 + .../dist/src/js/proto/Equalizer_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Ethernet_pb.d.ts | 1 + .../webapp/dist/src/js/proto/GPIO_pb.d.ts | 1 + .../webapp/dist/src/js/proto/I2CBus_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Names_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Network_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Services_pb.d.ts | 1 + .../webapp/dist/src/js/proto/Spotify_pb.d.ts | 1 + .../dist/src/js/proto/Squeezelite_pb.d.ts | 1 + .../webapp/dist/src/js/proto/State_pb.d.ts | 1 + .../dist/src/js/proto/customoptions_pb.d.ts | 1 + components/wifi-manager/webapp/package.json | 5 +- components/wifi-manager/webapp/src/index.ts | 2 +- .../wifi-manager/webapp/src/js/custom.ts | 437 +- .../wifi-manager/webapp/src/js/messages.ts | 54 + .../webapp/src/js/proto/AirPlay_pb.js | 210 + .../webapp/src/js/proto/Artwork_pb.js | 208 + .../webapp/src/js/proto/Battery_pb.js | 296 + .../webapp/src/js/proto/Buttons_pb.js | 1832 + .../webapp/src/js/proto/Common_pb.js | 57 + .../webapp/src/js/proto/DAC_pb.js | 578 + .../webapp/src/js/proto/DacControlSet_pb.js | 1303 + .../webapp/src/js/proto/DataRequest_pb.js | 553 + .../webapp/src/js/proto/Devices_pb.js | 1875 + .../webapp/src/js/proto/Display_pb.js | 1514 + .../webapp/src/js/proto/Equalizer_pb.js | 236 + .../webapp/src/js/proto/Ethernet_pb.js | 1126 + .../webapp/src/js/proto/GPIO_pb.js | 1864 + .../webapp/src/js/proto/I2CBus_pb.js | 322 + .../webapp/src/js/proto/Names_pb.js | 330 + .../webapp/src/js/proto/Network_pb.js | 1987 + .../webapp/src/js/proto/Services_pb.js | 1742 + .../webapp/src/js/proto/Spotify_pb.js | 270 + .../webapp/src/js/proto/Squeezelite_pb.js | 2070 + .../webapp/src/js/proto/State_pb.js | 425 + .../webapp/src/js/proto/Status_pb.js | 1964 + .../webapp/src/js/proto/configuration_pb.js | 445 + .../webapp/src/js/proto/customoptions_pb.js | 986 + .../webapp/src/js/proto/nanopb_pb.js | 14 +- .../webapp/src/js/serviceHandler.ts | 49 + .../wifi-manager/webapp/src/js/utils.ts | 12 + .../wifi-manager/webapp/webpack.config.js | 9 +- .../webpack/GrpcToolsNodeProtocPlugin.js | 108 +- .../webpack/GrpcToolsNodeProtocPlugin.ts | 5 + .../webapp/webpack/protobuf-loader.js | 0 .../webapp/webpack/testProtocPlugin.js | 32 + .../wifi-manager/wifi_manager_http_server.c | 82 +- esp-idf-vscode-generated.gdb | 7 - flash_cmd.txt | 18 - main/Kconfig.projbuild | 149 +- main/component.mk | 12 - main/esp_app_main.c | 477 +- main/platform_esp32.h | 1 - makeBuildDocs.sh | 120 - partition_table/partitionTable.bin | Bin 3072 -> 3072 bytes partition_table/partitionTable.csv | 6 +- partitions-debug.csv | 8 - partitions.csv | 6 +- protobuf/CMakeLists.txt | 74 +- protobuf/generated/AirPlay.dot | 10 +- protobuf/generated/AirPlay.dot.png | Bin 1970 -> 1330 bytes protobuf/generated/AirPlay.dot.svg | 38 +- protobuf/generated/Artwork.dot | 10 +- protobuf/generated/Artwork.dot.png | Bin 1484 -> 1272 bytes protobuf/generated/Artwork.dot.svg | 6 +- protobuf/generated/Battery.dot | 10 +- protobuf/generated/Battery.dot.png | Bin 8457 -> 8204 bytes protobuf/generated/Battery.dot.svg | 6 +- protobuf/generated/Buttons.dot | 46 +- protobuf/generated/Buttons.dot.png | Bin 28578 -> 25308 bytes protobuf/generated/Buttons.dot.svg | 778 +- protobuf/generated/Common.dot | 8 +- protobuf/generated/Common.dot.png | Bin 528 -> 772 bytes protobuf/generated/Common.dot.svg | 8 +- protobuf/generated/DAC.dot | 80 +- protobuf/generated/DAC.dot.png | Bin 64528 -> 54622 bytes protobuf/generated/DAC.dot.svg | 1120 +- protobuf/generated/DacControlSet.dot | 42 +- protobuf/generated/DacControlSet.dot.png | Bin 22205 -> 22573 bytes protobuf/generated/DacControlSet.dot.svg | 540 +- protobuf/generated/DataRequest.dot | 274 + protobuf/generated/DataRequest.dot.png | Bin 0 -> 650151 bytes protobuf/generated/DataRequest.dot.svg | 4731 ++ protobuf/generated/Devices.dot | 250 +- protobuf/generated/Devices.dot.png | Bin 319988 -> 248008 bytes protobuf/generated/Devices.dot.svg | 4085 +- protobuf/generated/Display.dot | 41 +- protobuf/generated/Display.dot.png | Bin 28052 -> 25347 bytes protobuf/generated/Display.dot.svg | 628 +- protobuf/generated/Equalizer.dot | 29 + protobuf/generated/Equalizer.dot.png | Bin 0 -> 1372 bytes protobuf/generated/Equalizer.dot.svg | 36 + protobuf/generated/Ethernet.dot | 38 +- protobuf/generated/Ethernet.dot.png | Bin 21269 -> 16269 bytes protobuf/generated/Ethernet.dot.svg | 465 +- protobuf/generated/GPIO.dot | 62 +- protobuf/generated/GPIO.dot.png | Bin 34815 -> 38261 bytes protobuf/generated/GPIO.dot.svg | 742 +- protobuf/generated/I2CBus.dot | 17 +- protobuf/generated/I2CBus.dot.png | Bin 5653 -> 3342 bytes protobuf/generated/I2CBus.dot.svg | 143 +- protobuf/generated/MessageDefinition.dot | 29 + protobuf/generated/MessageDefinition.dot.png | Bin 0 -> 1485 bytes protobuf/generated/MessageDefinition.dot.svg | 35 + protobuf/generated/Names.dot | 29 + protobuf/generated/Names.dot.png | Bin 0 -> 2257 bytes protobuf/generated/Names.dot.svg | 51 + protobuf/generated/Network.dot | 47 + protobuf/generated/Network.dot.png | Bin 0 -> 43638 bytes protobuf/generated/Network.dot.svg | 457 + protobuf/generated/Services.dot | 94 +- protobuf/generated/Services.dot.png | Bin 58319 -> 90068 bytes protobuf/generated/Services.dot.svg | 1491 +- protobuf/generated/Spotify.dot | 10 +- protobuf/generated/Spotify.dot.png | Bin 2463 -> 1762 bytes protobuf/generated/Spotify.dot.svg | 52 +- protobuf/generated/Squeezelite.dot | 55 +- protobuf/generated/Squeezelite.dot.png | Bin 36639 -> 51698 bytes protobuf/generated/Squeezelite.dot.svg | 1022 +- protobuf/generated/State.dot | 42 + protobuf/generated/State.dot.png | Bin 0 -> 29269 bytes protobuf/generated/State.dot.svg | 327 + protobuf/generated/Status.dot | 70 +- protobuf/generated/Status.dot.png | Bin 40827 -> 97542 bytes protobuf/generated/Status.dot.svg | 1244 +- protobuf/generated/configuration.dot | 386 +- protobuf/generated/configuration.dot.png | Bin 498902 -> 531901 bytes protobuf/generated/configuration.dot.svg | 6534 +- protobuf/generated/configuration.dot.zip | Bin 0 -> 40375 bytes protobuf/generated/customoptions.dot | 4 +- protobuf/generated/customoptions.dot.png | Bin 2401 -> 5756 bytes protobuf/generated/customoptions.dot.svg | 104 +- protobuf/generated/timestamp.dot | 29 + protobuf/generated/timestamp.dot.png | Bin 0 -> 1899 bytes protobuf/generated/timestamp.dot.svg | 35 + protobuf/proto/AirPlay.proto | 10 +- protobuf/proto/Artwork.proto | 7 +- protobuf/proto/Battery.proto | 13 +- protobuf/proto/Buttons.proto | 115 +- protobuf/proto/CMakeLists.txt | 17 +- protobuf/proto/Common.proto | 22 +- protobuf/proto/DAC.proto | 51 +- protobuf/proto/DacControlSet.proto | 81 +- protobuf/proto/DataRequest.proto | 45 + protobuf/proto/Devices.proto | 77 +- protobuf/proto/Display.proto | 52 +- protobuf/proto/Equalizer.proto | 6 +- protobuf/proto/Ethernet.proto | 53 +- protobuf/proto/Expanders.proto | 37 + protobuf/proto/GPIO.proto | 74 +- protobuf/proto/Gpios.proto | 23 + protobuf/proto/I2CBus.proto | 29 +- protobuf/proto/Led.proto | 19 + protobuf/proto/MessageDefinition.proto | 9 + protobuf/proto/Metadata.proto | 23 + protobuf/proto/Names.proto | 5 +- protobuf/proto/Network.proto | 158 +- protobuf/proto/SPI.proto | 44 + protobuf/proto/Services.proto | 88 +- protobuf/proto/Sleep.proto | 31 + protobuf/proto/Spotify.proto | 7 +- protobuf/proto/Squeezelite.proto | 122 +- protobuf/proto/State.proto | 13 +- protobuf/proto/Status.proto | 78 +- protobuf/proto/Telnet.proto | 20 + protobuf/proto/configuration.proto | 22 +- protobuf/proto/customoptions.proto | 9 +- protobuf/targets/bureau-oled.json | 65 - protobuf/targets/esp32.json | 65 - sdkconfig | 146 +- sdkconfig.defaults | 2 +- spiffs/Config_defaults_pb.bin | 2 - spiffs/targets/bureau-oled.bin | 7 - spiffs/targets/esp32.bin | 7 - spiffs_src/CMakeLists.txt | 76 + spiffs_src/data/default_sets.json | 299 + .../data}/fonts/droid_sans_fb_11x13.bin | Bin {spiffs => spiffs_src/data}/fonts/line_1.bin | Bin {spiffs => spiffs_src/data}/fonts/line_2.bin | Bin spiffs_src/targets/bureau-oled/config.json | 58 + .../targets/esp32-a1s-ac101 copy/config.json | 45 + .../targets/esp32-a1s-ac101/config.json | 96 + .../targets/esp32-a1s-es8388a/config.json | 91 + spiffs_src/targets/squeezeamp/Config.json.WIP | 161 + spiffs_src/targets/squeezeio/config.json | 85 + squeezelite-esp32.code-workspace | 208 - test/CMakelists.txt | 105 +- test/main/CMakeLists.txt | 2 - test/main/unit_tests.c | 131 - test/partitions.csv | 12 +- test/sdkconfig.defaults | 1672 +- sdkconfig-backup => test/sdkconfig.test | 832 +- test/test.code-workspace | 125 + test/test_main/CMakeLists.txt | 4 + test/test_main/Kconfig.projbuild | 4 + test/test_main/test_common_init.c | 32 + test/test_main/test_common_init.h | 11 + test/test_main/test_runner.c | 77 + .../ToggleGitTracking.ps1 | 2 +- .../generate_debug_scripts.cmake | 27 +- .../linux-x86_64/LICENSE-asserts.md | 176 + .../linux-x86_64/LICENSE.md | 29 + .../linux-x86_64/README.md | 181 + .../linux-x86_64/bin/protoc-gen-js | Bin 0 -> 2123752 bytes .../linux-x86_64/google-protobuf.js | 566 + .../linux-x86_64/google/protobuf/any_pb.js | 281 + .../linux-x86_64/google/protobuf/api_pb.js | 1001 + .../google/protobuf/compiler/plugin_pb.js | 1274 + .../google/protobuf/descriptor_pb.js | 10124 +++ .../google/protobuf/duration_pb.js | 206 + .../linux-x86_64/google/protobuf/empty_pb.js | 147 + .../google/protobuf/field_mask_pb.js | 202 + .../google/protobuf/source_context_pb.js | 176 + .../linux-x86_64/google/protobuf/struct_pb.js | 955 + .../google/protobuf/timestamp_pb.js | 242 + .../linux-x86_64/google/protobuf/type_pb.js | 1712 + .../google/protobuf/wrappers_pb.js | 1416 + .../linux-x86_64/package.json | 34 + .../win64/LICENSE-asserts.md | 176 + tools/protobuf-javascript/win64/LICENSE.md | 29 + tools/protobuf-javascript/win64/README.md | 181 + .../win64/bin/protoc-gen-js.exe | Bin 0 -> 2860032 bytes .../win64/google-protobuf.js | 149 + .../win64/google/protobuf/any.js | 274 + .../win64/google/protobuf/any_pb.js | 281 + .../win64/google/protobuf/api.js | 993 + .../win64/google/protobuf/api_pb.js | 1001 + .../win64/google/protobuf/compiler/plugin.js | 1267 + .../google/protobuf/compiler/plugin_pb.js | 1274 + .../win64/google/protobuf/descriptor.js | 10117 +++ .../win64/google/protobuf/descriptor_pb.js | 10124 +++ .../win64/google/protobuf/duration.js | 199 + .../win64/google/protobuf/duration_pb.js | 206 + .../win64/google/protobuf/empty.js | 140 + .../win64/google/protobuf/empty_pb.js | 147 + .../win64/google/protobuf/field_mask.js | 195 + .../win64/google/protobuf/field_mask_pb.js | 202 + .../win64/google/protobuf/source_context.js | 169 + .../google/protobuf/source_context_pb.js | 176 + .../win64/google/protobuf/struct.js | 949 + .../win64/google/protobuf/struct_pb.js | 955 + .../win64/google/protobuf/timestamp.js | 235 + .../win64/google/protobuf/timestamp_pb.js | 242 + .../win64/google/protobuf/type.js | 1703 + .../win64/google/protobuf/type_pb.js | 1712 + .../win64/google/protobuf/wrappers.js | 1409 + .../win64/google/protobuf/wrappers_pb.js | 1416 + tools/protobuf-javascript/win64/package.json | 35 + tools/protoc_utils/ProtoElement.py | 35 +- tools/protoc_utils/ProtocParser.py | 78 +- .../__pycache__/ProtoElement.cpython-310.pyc | Bin 0 -> 8503 bytes .../__pycache__/ProtoElement.cpython-38.pyc | Bin 8662 -> 9502 bytes .../__pycache__/ProtocParser.cpython-310.pyc | Bin 0 -> 11330 bytes .../__pycache__/ProtocParser.cpython-38.pyc | Bin 11434 -> 12466 bytes tools/protoc_utils/check_python_packages.py | 48 + tools/protoc_utils/decode_log_string.py | 37 + tools/protoc_utils/generate_bin.py | 40 +- tools/protoc_utils/parse_bin.py | 9 +- .../protoc_utils}/protobuf_utils.cmake | 94 +- tools/protoc_utils/protoc-gen-defaults.py | 166 +- tools/protoc_utils/protoc-gen-dump.py | 4 +- tools/protoc_utils/protoc-gen-json.py | 6 +- tools/protoc_utils/protoc-gen-options.py | 15 +- .../sdkconfig_compare.js | 0 tools/spiffs | Bin 184320 -> 0 bytes tools/svd/esp32.svd | 45572 ++++++++++ tools/svd/esp32s3.svd | 69021 ++++++++++++++++ 442 files changed, 227862 insertions(+), 21075 deletions(-) create mode 100644 .clang-format delete mode 100644 .cproject delete mode 100644 .devcontainer/devcontainer.json delete mode 100644 .project delete mode 100644 Makefile delete mode 100644 Makefile_std.mk delete mode 100755 buildFirmware.sh delete mode 100644 build_flash_cmd.sh create mode 100644 components/platform_config/Config.cpp create mode 100644 components/platform_config/Config.h delete mode 100644 components/platform_config/Configurator.cpp delete mode 100644 components/platform_config/Configurator.h create mode 100644 components/platform_config/Locking.cpp create mode 100644 components/platform_config/Locking.h create mode 100644 components/platform_config/PBW.cpp create mode 100644 components/platform_config/PBW.h create mode 100644 components/platform_config/WifiList.cpp create mode 100644 components/platform_config/WifiList.h create mode 100644 components/platform_config/test/CMakeLists.txt create mode 100644 components/platform_config/test/DAC_test_extra.proto create mode 100644 components/platform_config/test/DAC_test_extra2.proto create mode 100644 components/platform_config/test/test_platform_config.cpp create mode 100644 components/services/system_time.c create mode 100644 components/services/system_time.h delete mode 100644 components/squeezelite-ota/component.mk delete mode 100644 components/squeezelite-ota/github.pem create mode 100644 components/tools/bootstate.cpp create mode 100644 components/tools/bootstate.h delete mode 100644 components/tools/component.mk create mode 100644 components/tools/cpp_tools.cpp create mode 100644 components/tools/cpp_tools.h create mode 100644 components/tools/test/CMakeLists.txt create mode 100644 components/tools/test/test_tools.cpp create mode 100644 components/tools/tools_http_utils.c create mode 100644 components/tools/tools_http_utils.h create mode 100644 components/tools/tools_spiffs_utils.cpp create mode 100644 components/tools/tools_spiffs_utils.h delete mode 100644 components/wifi-manager/LICENSE.md delete mode 100644 components/wifi-manager/component.mk delete mode 100644 components/wifi-manager/network_status.c create mode 100644 components/wifi-manager/network_status.cpp delete mode 100644 components/wifi-manager/network_wifi.c create mode 100644 components/wifi-manager/network_wifi.cpp create mode 100644 components/wifi-manager/webapp/dist/css/index.css create mode 100644 components/wifi-manager/webapp/dist/css/index.css.gz delete mode 100644 components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css delete mode 100644 components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css.gz create mode 100644 components/wifi-manager/webapp/dist/js/index.bundle.js create mode 100644 components/wifi-manager/webapp/dist/js/index.bundle.js.gz create mode 100644 components/wifi-manager/webapp/dist/js/index.bundle.js.map delete mode 100644 components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js delete mode 100644 components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.gz delete mode 100644 components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.map create mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.bundle.js create mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.bundle.js.gz create mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.bundle.js.map delete mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.dd7cd3.bundle.js delete mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.dd7cd3.bundle.js.gz delete mode 100644 components/wifi-manager/webapp/dist/js/node_vendors.dd7cd3.bundle.js.map create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/AirPlay_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Artwork_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Battery_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Buttons_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Common_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/DAC_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/DacControlSet_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/DataRequest_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Devices_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Display_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Equalizer_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Ethernet_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/GPIO_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/I2CBus_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Names_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Network_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Services_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Spotify_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/Squeezelite_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/State_pb.d.ts create mode 100644 components/wifi-manager/webapp/dist/src/js/proto/customoptions_pb.d.ts create mode 100644 components/wifi-manager/webapp/src/js/messages.ts create mode 100644 components/wifi-manager/webapp/src/js/proto/AirPlay_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Artwork_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Battery_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Buttons_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Common_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/DAC_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/DacControlSet_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/DataRequest_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Devices_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Display_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Equalizer_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Ethernet_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/GPIO_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/I2CBus_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Names_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Network_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Services_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Spotify_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Squeezelite_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/State_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/Status_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/configuration_pb.js create mode 100644 components/wifi-manager/webapp/src/js/proto/customoptions_pb.js create mode 100644 components/wifi-manager/webapp/src/js/serviceHandler.ts create mode 100644 components/wifi-manager/webapp/src/js/utils.ts create mode 100644 components/wifi-manager/webapp/webpack/protobuf-loader.js create mode 100644 components/wifi-manager/webapp/webpack/testProtocPlugin.js delete mode 100644 esp-idf-vscode-generated.gdb delete mode 100644 flash_cmd.txt delete mode 100644 main/component.mk delete mode 100755 makeBuildDocs.sh delete mode 100644 partitions-debug.csv create mode 100644 protobuf/generated/DataRequest.dot create mode 100644 protobuf/generated/DataRequest.dot.png create mode 100644 protobuf/generated/DataRequest.dot.svg create mode 100644 protobuf/generated/Equalizer.dot create mode 100644 protobuf/generated/Equalizer.dot.png create mode 100644 protobuf/generated/Equalizer.dot.svg create mode 100644 protobuf/generated/MessageDefinition.dot create mode 100644 protobuf/generated/MessageDefinition.dot.png create mode 100644 protobuf/generated/MessageDefinition.dot.svg create mode 100644 protobuf/generated/Names.dot create mode 100644 protobuf/generated/Names.dot.png create mode 100644 protobuf/generated/Names.dot.svg create mode 100644 protobuf/generated/Network.dot create mode 100644 protobuf/generated/Network.dot.png create mode 100644 protobuf/generated/Network.dot.svg create mode 100644 protobuf/generated/State.dot create mode 100644 protobuf/generated/State.dot.png create mode 100644 protobuf/generated/State.dot.svg create mode 100644 protobuf/generated/configuration.dot.zip create mode 100644 protobuf/generated/timestamp.dot create mode 100644 protobuf/generated/timestamp.dot.png create mode 100644 protobuf/generated/timestamp.dot.svg create mode 100644 protobuf/proto/DataRequest.proto create mode 100644 protobuf/proto/Expanders.proto create mode 100644 protobuf/proto/Gpios.proto create mode 100644 protobuf/proto/Led.proto create mode 100644 protobuf/proto/MessageDefinition.proto create mode 100644 protobuf/proto/Metadata.proto create mode 100644 protobuf/proto/SPI.proto create mode 100644 protobuf/proto/Sleep.proto create mode 100644 protobuf/proto/Telnet.proto delete mode 100644 protobuf/targets/bureau-oled.json delete mode 100644 protobuf/targets/esp32.json delete mode 100644 spiffs/Config_defaults_pb.bin delete mode 100644 spiffs/targets/bureau-oled.bin delete mode 100644 spiffs/targets/esp32.bin create mode 100644 spiffs_src/CMakeLists.txt create mode 100644 spiffs_src/data/default_sets.json rename {spiffs => spiffs_src/data}/fonts/droid_sans_fb_11x13.bin (100%) rename {spiffs => spiffs_src/data}/fonts/line_1.bin (100%) rename {spiffs => spiffs_src/data}/fonts/line_2.bin (100%) create mode 100644 spiffs_src/targets/bureau-oled/config.json create mode 100644 spiffs_src/targets/esp32-a1s-ac101 copy/config.json create mode 100644 spiffs_src/targets/esp32-a1s-ac101/config.json create mode 100644 spiffs_src/targets/esp32-a1s-es8388a/config.json create mode 100644 spiffs_src/targets/squeezeamp/Config.json.WIP create mode 100644 spiffs_src/targets/squeezeio/config.json delete mode 100644 squeezelite-esp32.code-workspace delete mode 100644 test/main/CMakeLists.txt delete mode 100644 test/main/unit_tests.c rename sdkconfig-backup => test/sdkconfig.test (68%) create mode 100644 test/test.code-workspace create mode 100644 test/test_main/CMakeLists.txt create mode 100644 test/test_main/Kconfig.projbuild create mode 100644 test/test_main/test_common_init.c create mode 100644 test/test_main/test_common_init.h create mode 100644 test/test_main/test_runner.c rename ToggleGitTracking.ps1 => tools/ToggleGitTracking.ps1 (98%) rename generate_debug_scripts.cmake => tools/generate_debug_scripts.cmake (77%) create mode 100644 tools/protobuf-javascript/linux-x86_64/LICENSE-asserts.md create mode 100644 tools/protobuf-javascript/linux-x86_64/LICENSE.md create mode 100644 tools/protobuf-javascript/linux-x86_64/README.md create mode 100644 tools/protobuf-javascript/linux-x86_64/bin/protoc-gen-js create mode 100644 tools/protobuf-javascript/linux-x86_64/google-protobuf.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/any_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/api_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/compiler/plugin_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/descriptor_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/duration_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/empty_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/field_mask_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/source_context_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/struct_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/timestamp_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/type_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/google/protobuf/wrappers_pb.js create mode 100644 tools/protobuf-javascript/linux-x86_64/package.json create mode 100644 tools/protobuf-javascript/win64/LICENSE-asserts.md create mode 100644 tools/protobuf-javascript/win64/LICENSE.md create mode 100644 tools/protobuf-javascript/win64/README.md create mode 100644 tools/protobuf-javascript/win64/bin/protoc-gen-js.exe create mode 100644 tools/protobuf-javascript/win64/google-protobuf.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/any.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/any_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/api.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/api_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/compiler/plugin.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/compiler/plugin_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/descriptor.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/descriptor_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/duration.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/duration_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/empty.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/empty_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/field_mask.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/field_mask_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/source_context.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/source_context_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/struct.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/struct_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/timestamp.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/timestamp_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/type.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/type_pb.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/wrappers.js create mode 100644 tools/protobuf-javascript/win64/google/protobuf/wrappers_pb.js create mode 100644 tools/protobuf-javascript/win64/package.json create mode 100644 tools/protoc_utils/__pycache__/ProtoElement.cpython-310.pyc create mode 100644 tools/protoc_utils/__pycache__/ProtocParser.cpython-310.pyc create mode 100644 tools/protoc_utils/check_python_packages.py create mode 100644 tools/protoc_utils/decode_log_string.py rename {protobuf => tools/protoc_utils}/protobuf_utils.cmake (63%) rename sdkconfig_compare.js => tools/sdkconfig_compare.js (100%) delete mode 100644 tools/spiffs create mode 100644 tools/svd/esp32.svd create mode 100644 tools/svd/esp32s3.svd diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..0fdb014e --- /dev/null +++ b/.clang-format @@ -0,0 +1,14 @@ +{ + "BasedOnStyle": "LLVM", + "UseTab": "Never", + "IndentWidth": 4, + "TabWidth": 4, + "ColumnLimit": 150, + "PointerAlignment": "Left", + "AlignAfterOpenBracket": "DontAlign", + "BreakBeforeBraces": "Attach", + "AllowShortIfStatementsOnASingleLine": true, + "AllowShortFunctionsOnASingleLine": "All", + "IndentCaseLabels": false, + "SpacesBeforeTrailingComments": 1 +} \ No newline at end of file diff --git a/.cproject b/.cproject deleted file mode 100644 index 317be43f..00000000 --- a/.cproject +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index aa2ccfb0..00000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "ESP-IDF Development", - "image": "espressif/idf:v4.4.6", - "workspaceFolder": "/project", - "workspaceMount": "source=${localWorkspaceFolder},target=/project,type=bind", - "customizations": { - "vscode": { - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - "extensions": [ - "ms-vscode.cpptools", - "usernamehw.errorlens", - "espressif.esp-idf-extension" // ESP-IDF extension - ] - } - }, - "runArgs": [ - "--privileged" // If needed for accessing certain hardware resources - ] -} diff --git a/.gitignore b/.gitignore index caa347ce..b4ae7dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,10 @@ components/wifi-manager/UML-State-Machine-in-C envfile.txt artifacts web-installer +esp-idf-vscode-generated.gdb +.vscode/.espidf.peripherals.state.json +.vscode/squeezelite-esp32.code-workspace +debug.log +components/driver_bt/bt_app_source - Copy.c.old +components/driver_bt/bt_app_source - Copy.c.old +components/driver_bt/bt_app_source - Copy.c.old diff --git a/.project b/.project deleted file mode 100644 index 20702302..00000000 --- a/.project +++ /dev/null @@ -1,20 +0,0 @@ - - - squeezelite-esp32-idfv4 - - - - - - org.eclipse.cdt.core.cBuilder - clean,full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - com.espressif.idf.core.idfNature - - \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 644b7260..4c56f023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,12 @@ endif() # State machine hierarchy enabled and logging enabled add_definitions(-DSTATE_MACHINE_LOGGER=1) -add_definitions(-DHIERARCHICAL_STATES=1) +#add_definitions(-DHIERARCHICAL_STATES=1) + +# Align the nanopb library options across the entire project +# otherwise this results in nasty structures misalignment +# when implementing callbacks +add_definitions(-DPB_ENABLE_MALLOC -DPB_FIELD_32BIT) # Uncomment line below to get memory usage trace details # add_definitions(-DENABLE_MEMTRACE=1) @@ -18,9 +23,11 @@ add_definitions(-DHIERARCHICAL_STATES=1) #add_definitions(-DNETWORK_ETHERNET_LOG_LEVEL=ESP_LOG_DEBUG) #uncomment line below to get network status debug logs #add_definitions(-DNETWORK_STATUS_LOG_LEVEL=ESP_LOG_DEBUG) -#add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG) +add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG) + #add_definitions(-DNETWORK_WIFI_LOG_LEVEL=ESP_LOG_DEBUG) -#add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG) +add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG) + #add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG) # utility to build sizes @@ -53,7 +60,6 @@ endfunction() set(EXTRA_COMPONENT_DIRS components/platform_console/app_recovery components/platform_console/app_squeezelite ) project(recovery) -spiffs_create_partition_image(spiffs spiffs FLASH_IN_PROJECT DEPENDS generate_spiffs_bin ) # we need own "esp_app_desc" to take precedence add_custom_command( @@ -106,7 +112,7 @@ esptool_py_flash_target_image(flash squeezelite "${otaapp_offset}" "${BUILD_DIR} add_custom_target(_jtag_scripts ALL BYPRODUCTS "flash_dbg_project_args" POST_BUILD - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_debug_scripts.cmake" + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_debug_scripts.cmake" ) if(CMAKE_HOST_UNIX) @@ -136,78 +142,95 @@ endif() # Include the protocol_buffers.cmake file add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/protobuf ${CMAKE_CURRENT_BINARY_DIR}/protobuf) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spiffs_src ${CMAKE_CURRENT_BINARY_DIR}/spiffs) + # ======================= DEBUG FLAGS ============================ +# target_compile_definitions(__idf_wifi-manager PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_app_recovery PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) +# target_compile_definitions(__idf_esp_event PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) +# target_compile_definitions(__idf_esp_netif PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_ERROR) +# target_compile_definitions(__idf_mdns PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_tcpip_adapter PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_tcp_transport PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_app_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_app_trace PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_app_update PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_asio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_audio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_bootloader_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_display PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_platform_config PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_squeezelite-ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_telnet PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_main PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + + + + + + + + + + + + + #target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) +# target_compile_definitions(__idf_services PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_services PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_wifi-manager PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_wifi PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_platform_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_wifi PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_platform_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_app_recovery PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) -target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) -target_compile_definitions(__idf_esp_event PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) -target_compile_definitions(__idf_esp_netif PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) - -target_compile_definitions(__idf_freertos PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_ERROR) -target_compile_definitions(__idf_mdns PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_tcpip_adapter PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_tcp_transport PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_app_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_app_trace PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_app_update PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_asio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_audio PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_bootloader_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_cbor PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_cmock PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_coap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_console PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_cxx PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_display PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_driver PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_driver_bt PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_efuse PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp-dsp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp-tls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp32 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_espcoredump PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_adc_cal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_common PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_gdbstub PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_hid PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_https_ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_http_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_http_server PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_hw_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_ipc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_local_ctrl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_pm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_ringbuf PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_rom PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_serial_slave_link PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_system PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_esp_timer PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_expat PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_fatfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_freemodbus PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_hal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_heap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_jsmn PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_json PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_esp_eth PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_INFO) + + + +# target_compile_definitions(__idf_freertos PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + + +# target_compile_definitions(__idf_cbor PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_cmock PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_coap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_cxx PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_adc_cal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_https_ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_http_client PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_http_server PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_hw_support PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_ipc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_local_ctrl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_pm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_ringbuf PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_rom PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_serial_slave_link PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_system PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_esp_timer PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_expat PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_fatfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_freemodbus PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_hal PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_heap PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_jsmn PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_json PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_libsodium PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_log PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_lwip PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_main PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(mbedcrypto PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(mbedx509 PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) @@ -217,24 +240,23 @@ target_compile_definitions(__idf_mbedtls PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG # target_compile_definitions(__idf_nvs_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_openssl PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_perfmon PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_platform_config PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_protobuf-c PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_protocomm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_pthread PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_raop PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_sdmmc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_soc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_spiffs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_spi_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_squeezelite PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_squeezelite-ota PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_telnet PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_tools PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_ulp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_unity PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_protobuf-c PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_protocomm PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_pthread PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_raop PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_sdmmc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_soc PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_spiffs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_spi_flash PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) + +# target_compile_definitions(__idf_tools PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_ulp PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_unity PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_vfs PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_wear_levelling PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) -target_compile_definitions(__idf_wifi_provisioning PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_wear_levelling PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) +# target_compile_definitions(__idf_wifi_provisioning PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_wpa_supplicant PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) # target_compile_definitions(__idf_xtensa PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG) \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index fb8815c6..d9c0e2c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,188 +1,82 @@ -FROM ubuntu:20.04 +FROM espressif/idf:v4.4.6 + +# Install additional dependencies +RUN apt-get update && apt-get install -y \ + python3-protobuf + +RUN DEBIAN_FRONTEND=noninteractive TZ=America/Toronto apt-get -y install tzdata + # Add any other dependencies you need + + # To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name. + # To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id. + # It is possibe to combine both, e.g.: + # IDF_CLONE_BRANCH_OR_TAG=release/vX.Y + # IDF_CHECKOUT_REF=. + # Docker build for release 4.3.5 as of 2023/05/18 + # docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv446 + # Updating the docker image in the repository + # docker push sle118/squeezelite-esp32-idfv446 + # or to do both: + # docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv446 && docker push sle118/squeezelite-esp32-idfv446 + # docker build . -t sle118/squeezelite-esp32-idfv446 && docker push sle118/squeezelite-esp32-idfv446 + #docker run --isolation=process --device="class/86E0D1E0-8089-11D0-9CE4-08003E301F73" mcr.microsoft.com/windows/servercore:1809 + # (windows) To run the image interactive : + # docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv446 + # (windows powershell) + # docker run --rm -v ${PWD}:/project -w /project -it sle118/squeezelite-esp32-idfv446 + # (linux) To run the image interactive : + # docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv446 + # to build the web app inside of the interactive session + # pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd + # + # to run the docker with netwotrk port published on the host: + # docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv446 -ARG DEBIAN_FRONTEND=noninteractive -ENV GCC_TOOLS_BASE=/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf- -# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name. -# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id. -# It is possibe to combine both, e.g.: -# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y -# IDF_CHECKOUT_REF=. -# Docker build for release 4.3.5 as of 2023/05/18 -# docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv435 -# Updating the docker image in the repository -# docker push sle118/squeezelite-esp32-idfv435 -# or to do both: -# docker build . --build-arg IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d -t sle118/squeezelite-esp32-idfv435 && docker push sle118/squeezelite-esp32-idfv435 -# -# (windows) To run the image interactive : -# docker run --rm -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435 -# (windows powershell) -# docker run --rm -v ${PWD}:/project -w /project -it sle118/squeezelite-esp32-idfv435 -# (linux) To run the image interactive : -# docker run --rm -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv435 -# to build the web app inside of the interactive session -# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd -# -# to run the docker with netwotrk port published on the host: -# docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435 - -ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git -ARG IDF_CLONE_BRANCH_OR_TAG=master -ARG IDF_CHECKOUT_REF=6d04316cbe4dc35ea7e4885e9821bd9958ac996d - -ENV IDF_PATH=/opt/esp/idf -ENV IDF_TOOLS_PATH=/opt/esp - -# We need libpython2.7 due to GDB tools -# we also need npm 8 for the webapp to work -RUN : \ - && apt-get update \ - && apt-get install -y \ - apt-utils \ - build-essential \ - bison \ - ca-certificates \ - ccache \ - check \ - curl \ - flex \ - git \ - git-lfs \ - gperf \ - lcov \ - libbsd-dev \ - libpython3.8 \ - libffi-dev \ - libncurses-dev \ - libusb-1.0-0-dev \ - make \ - ninja-build \ - python3.8 \ - python3-pip \ - python3-venv \ - ruby \ - unzip \ - wget \ - xz-utils \ - zip \ - npm \ - nodejs \ - && apt-get autoremove -y \ - && rm -rf /var/lib/apt/lists/* \ - && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \ - && python -m pip install --upgrade \ - pip \ - virtualenv \ - && cd /opt \ - && git clone https://github.com/HBehrens/puncover.git \ - && cd puncover \ - && python setup.py -q install \ - && echo IDF_CHECKOUT_REF=$IDF_CHECKOUT_REF IDF_CLONE_BRANCH_OR_TAG=$IDF_CLONE_BRANCH_OR_TAG \ - && git clone --recursive \ - ${IDF_CLONE_BRANCH_OR_TAG:+-b $IDF_CLONE_BRANCH_OR_TAG} \ - $IDF_CLONE_URL $IDF_PATH \ - && if [ -n "$IDF_CHECKOUT_REF" ]; then \ - cd $IDF_PATH \ - && git checkout $IDF_CHECKOUT_REF \ - && git submodule update --init --recursive; \ - fi \ - && update-ca-certificates --fresh \ - && $IDF_PATH/tools/idf_tools.py --non-interactive install required \ - && $IDF_PATH/tools/idf_tools.py --non-interactive install cmake \ - && $IDF_PATH/tools/idf_tools.py --non-interactive install-python-env \ - && : RUN : \ echo Installing pygit2 ******************************************************** \ - && . /opt/esp/python_env/idf4.3_py3.8_env/bin/activate \ - && ln -sf /opt/esp/python_env/idf4.3_py3.8_env/bin/python /usr/local/bin/python \ + && . /opt/esp/python_env/idf4.4_py3.8_env/bin/activate \ + && ln -sf /opt/esp/python_env/idf4.4_py3.8_env/bin/python /usr/local/bin/python \ && pip install pygit2 requests \ && pip show pygit2 \ && python --version \ && pip --version \ && pip install protobuf grpcio-tools \ && rm -rf $IDF_TOOLS_PATH/dist \ + && apt-get install -y nodejs \ && : -COPY docker/patches $IDF_PATH +# COPY docker/patches $IDF_PATH #set idf environment variabies -ENV PATH /opt/esp/idf/components/esptool_py/esptool:/opt/esp/idf/components/espcoredump:/opt/esp/idf/components/partition_table:/opt/esp/idf/components/app_update:/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin:/opt/esp/tools/xtensa-esp32s2-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s2-elf/bin:/opt/esp/tools/xtensa-esp32s3-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s3-elf/bin:/opt/esp/tools/riscv32-esp-elf/esp-2021r2-patch3-8.4.0/riscv32-esp-elf/bin:/opt/esp/tools/esp32ulp-elf/2.28.51-esp-20191205/esp32ulp-elf-binutils/bin:/opt/esp/tools/esp32s2ulp-elf/2.28.51-esp-20191205/esp32s2ulp-elf-binutils/bin:/opt/esp/tools/cmake/3.16.4/bin:/opt/esp/tools/openocd-esp32/v0.11.0-esp32-20220706/openocd-esp32/bin:/opt/esp/python_env/idf4.3_py3.8_env/bin:/opt/esp/idf/tools:$PATH +ENV PATH /opt/esp/idf/components/esptool_py/esptool:/opt/esp/idf/components/espcoredump:/opt/esp/idf/components/partition_table:/opt/esp/idf/components/app_update:/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin:/opt/esp/tools/xtensa-esp32s2-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s2-elf/bin:/opt/esp/tools/xtensa-esp32s3-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32s3-elf/bin:/opt/esp/tools/riscv32-esp-elf/esp-2021r2-patch3-8.4.0/riscv32-esp-elf/bin:/opt/esp/tools/esp32ulp-elf/2.28.51-esp-20191205/esp32ulp-elf-binutils/bin:/opt/esp/tools/esp32s2ulp-elf/2.28.51-esp-20191205/esp32s2ulp-elf-binutils/bin:/opt/esp/tools/cmake/3.16.4/bin:/opt/esp/tools/openocd-esp32/v0.11.0-esp32-20220706/openocd-esp32/bin:/opt/esp/python_env/idf4.4_py3.8_env/bin:/opt/esp/idf/tools:$PATH ENV GCC_TOOLS_BASE="/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-" -ENV IDF_PATH="/opt/esp/idf" -ENV IDF_PYTHON_ENV_PATH="/opt/esp/python_env/idf4.3_py3.8_env" -ENV IDF_TOOLS_EXPORT_CMD="/opt/esp/idf/export.sh" -ENV IDF_TOOLS_INSTALL_CMD="/opt/esp/idf/install.sh" -ENV IDF_TOOLS_PATH="/opt/esp" -ENV NODE_PATH="/v8/lib/node_modules" -ENV NODE_VERSION="8" +ENV IDF_PYTHON_ENV_PATH="/opt/esp/python_env/idf4.4_py3.8_env" ENV OPENOCD_SCRIPTS="/opt/esp/tools/openocd-esp32/v0.10.0-esp32-20211111/openocd-esp32/share/openocd/scripts" -# Ccache is installed, enable it by default - -# The constraint file has been downloaded and the right Python package versions installed. No need to check and -# download this at every invocation of the container. -ENV IDF_PYTHON_CHECK_CONSTRAINTS=no - -# Ccache is installed, enable it by default -ENV IDF_CCACHE_ENABLE=1 - -# Install QEMU runtime dependencies -RUN : \ - && apt-get update && apt-get install -y -q \ - libglib2.0-0 \ - libpixman-1-0 \ - && rm -rf /var/lib/apt/lists/* \ - && : - -# Install QEMU -ARG QEMU_VER=esp-develop-20220919 -ARG QEMU_DIST=qemu-${QEMU_VER}.tar.bz2 -ARG QEMU_SHA256=f6565d3f0d1e463a63a7f81aec94cce62df662bd42fc7606de4b4418ed55f870 -RUN : \ - && wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_DIST} \ - && echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \ - && tar -xf ${QEMU_DIST} -C /opt \ - && rm ${QEMU_DIST} \ - && : COPY docker/entrypoint.sh /opt/esp/entrypoint.sh COPY components/wifi-manager/webapp/package.json /opt - -ENV NODE_VERSION 8 - -SHELL ["/bin/bash", "--login", "-c"] -# Install nvm with node and npm -# RUN wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash \ -# && export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" \ -# && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" \ -# && nvm install $NODE_VERSION \ -# && nvm alias default $NODE_VERSION \ -# && nvm use default \ -# && echo installing nodejs version 16 \ -# && curl -sL https://deb.nodesource.com/setup_16.x | bash - \ -# && echo installing node modules \ -# && cd /opt \ -# && nvm use default \ -# && npm install -g \ -# && : - -RUN : \ - && curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \ - && apt-get install -y nodejs jq \ - && echo installing dev node modules globally \ - && cd /opt \ - && cat ./package.json | jq '.devDependencies | keys[] as $k | "\($k)@\(.[$k])"' | xargs -t npm install --global \ - && echo installing npm global packages \ - && npm i -g npm \ - && node --version \ - && npm install -g \ - && : -RUN : \ - && npm install -g html-webpack-plugin - - +ENV NODE_PATH="/v8/lib/node_modules" +ENV NODE_VERSION="8" ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH $IDF_PYTHON_ENV_PATH:$NVM_DIR/v$NODE_VERSION/bin:$PATH +SHELL ["/bin/bash", "--login", "-c"] + +# Install NVM, Node.js, and global NPM packages +RUN wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash \ + && export NVM_DIR="$HOME/.nvm" \ + && . "$NVM_DIR/nvm.sh" \ + && nvm install 16 \ + && nvm alias default 16 \ + && nvm use default \ + && echo "Node.js version:" && node --version \ + && echo "NPM version:" && npm --version \ + && echo "Installing global NPM packages..." \ + && cd /opt \ + && cat ./package.json | jq '.devDependencies | keys[] as $k | "\($k)@\(.[$k])"' | xargs -t npm install --global \ + && npm install -g html-webpack-plugin \ + && : + COPY ./docker/build_tools.py /usr/sbin/build_tools.py RUN : \ && echo Changing permissions ******************************************************** \ diff --git a/Makefile b/Makefile deleted file mode 100644 index 51ac175c..00000000 --- a/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# build system (Jenkins) should pass the following -#export PROJECT_BUILD_NAME="${build_version_prefix}${BUILD_NUMBER}" -#export PROJECT_BUILD_TARGET="${config_target}" - -#PROJECT_BUILD_NAME?=local -#PROJECT_CONFIG_TARGET?=custom -#PROJECT_NAME?=squeezelite.$(PROJECT_CONFIG_TARGET) -#PROJECT_VER?="$(PROJECT_BUILD_NAME)-$(PROJECT_CONFIG_TARGET)" - - - -#recovery: PROJECT_NAME:=recovery.$(PROJECT_CONFIG_TARGET) -#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1 - -PROJECT_NAME?=squeezelite -EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main - -#/-Wno-error=maybe-uninitialized -include $(IDF_PATH)/make/project.mk - -# for future gcc version, this could be needed: CPPFLAGS+= -Wno-error=format-overflow -Wno-error=stringop-truncation - diff --git a/Makefile_std.mk b/Makefile_std.mk deleted file mode 100644 index b1a67a7d..00000000 --- a/Makefile_std.mk +++ /dev/null @@ -1,3 +0,0 @@ -PROJECT_NAME?= squeezelite -EXTRA_COMPONENT_DIRS := $(PROJECT_PATH)/esp-dsp -include $(IDF_PATH)/make/project.mk \ No newline at end of file diff --git a/buildFirmware.sh b/buildFirmware.sh deleted file mode 100755 index 2dc9298d..00000000 --- a/buildFirmware.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - - - -echo "Build process started" -echo "Setting up build name and build number" -if [ -z "${TARGET_BUILD_NAME}" ] -then - export TARGET_BUILD_NAME="I2S-4MFlash" - echo "TARGET_BUILD_NAME is not set. Defaulting to ${TARGET_BUILD_NAME}" -fi -if [ -z "${BUILD_NUMBER}" ] -then - export BUILD_NUMBER="500" - echo "BUILD_NUMBER is not set. Defaulting to ${BUILD_NUMBER}" -fi -if [ -z "$DEPTH" ] -then - export DEPTH="16" - echo "DEPTH is not set. Defaulting to ${DEPTH}" -fi -if [ -z "$tag" ] -then - branch_name="$(git rev-parse --abbrev-ref HEAD)" - branch_name="${branch_name//[^a-zA-Z0-9\-~!@_\.]/}" - app_name="${TARGET_BUILD_NAME}.${DEPTH}.dev-$(git log --pretty=format:'%h' --max-count=1).${branch_name}" - echo "${app_name}">version.txt - echo "app_name is not set. Defaulting to ${app_name}" -else - echo "${tag}" >version.txt -fi - -echo "Copying target sdkconfig" -cp build-scripts/${TARGET_BUILD_NAME}-sdkconfig.defaults sdkconfig -echo "Building project" -idf.py build -DDEPTH=${DEPTH} -DBUILD_NUMBER=${BUILD_NUMBER}-${DEPTH} -echo "Generating size report" -idf.py size-components >build/size_components.txt -idf.py size-components-squeezelite build/size_components_squeezelite.txt -if [ -z "${artifact_file_name}" ] -then - echo "No artifact file name set. Will not generate zip file." -else - echo "Generating build artifact zip file" - zip -r build_output.zip build - zip build/${artifact_file_name} partitions*.csv components/ build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt -fi diff --git a/build_flash_cmd.sh b/build_flash_cmd.sh deleted file mode 100644 index 7124e1f3..00000000 --- a/build_flash_cmd.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash -echo -echo ================================================================= -echo Build flash command -echo ================================================================= -# Location of partitions.csv relative to this script -partitionsCsv="../partitions.csv" - -# File to output readme instructions to -outputReadme="./flash_cmd.txt" - -# File to output bash script to -outputBashScript="./writeSequeezeEsp.sh" - -# File to output bat script to -outputBatScript="./writeSequeezeEsp.bat" - -# The name of partitions to ignore from partitions.csv -paritionsToIgnore=( - "nvs" - "phy_init" - "storage" - "coredump" - "settings" -) - -# Function that maps partition name to actual bin file -# defaults to "[PARTION_NAME_FROM_CSV].bin" -function partitionNameToBinFile { - if [[ "$1" == "otadata" ]]; then - echo "ota_data_initial.bin" - elif [[ "$1" == "ota_0" || "$1" == "factory" ]]; then - echo "squeezelite.bin" - else - echo $1.bin - fi -} - -# write parameters for esptool.py -writeParameters="$writeParameters write_flash" -writeParameters="$writeParameters --flash_mode dio --flash_freq 80m --flash_size detect" - -# bootloader.bin and partitions.bin not in partitions.csv so manually add here -partitionsParameters=" 0x1000 bootloader/bootloader.bin" -partitionsParameters="$partitionsParameters 0x8000 partitions.bin" - -# ============================================================================== - -# Loop over partitions.csv and add partition bins and offsets to partitionsParameters - -for line in $($IDF_PATH/components/partition_table/gen_esp32part.py --quiet build/partitions.bin | grep '^[^#]') -do - partitionName=$(echo $line | awk -F',' '{printf "%s", $1}' ) - partitionOffset=$(echo $line |awk -F',' '{printf "%s", $4}' ) - partitionFile=$(partitionNameToBinFile $partitionName) - - if [[ " ${paritionsToIgnore[@]} " =~ " ${partitionName} " ]]; then - continue - fi - - partitionsParameters="$partitionsParameters $partitionOffset $partitionFile" - echo "$partitionsParameters" - -done - -# Write README Instructions -if [ ! -f "$outputReadme" ]; then - touch $outputReadme -fi - -echo "" >> $outputReadme -echo "====LINUX====" >> $outputReadme -echo "To flash sequeezelite run the following script:" >> $outputReadme -echo "$outputBashScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme -echo "e.g. $outputBashScript /dev/ttyUSB0 115200" >> $outputReadme -echo "" >> $outputReadme -echo "====WINDOWS====" >> $outputReadme -echo "To flash sequeezelite run the following script:" >> $outputReadme -echo "$outputBatScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme -echo "e.g. $outputBatScript COM11 115200" >> $outputReadme -echo "" >> $outputReadme -echo "If you don't know how to run the BAT file with arguments then you can" >> $outputReadme -echo "edit the bat file in Notepad. Open the file up and edit the following:" >> $outputReadme -echo "Change 'set port=%1' to 'set port=[PORT_HERE]'. E.g. 'set port=COM11'" >> $outputReadme -echo "Change 'set baud=%2' to 'set baud=[BAUD_RATE]'. E.g. 'set baud=115200'" >> $outputReadme -echo "" >> $outputReadme -echo "====MANUAL====" >> $outputReadme -echo "Python esptool.py --port [PORT_HERE] --baud [BAUD_RATE] $writeParameters $partitionsParameters" >> $outputReadme - -# Write Linux BASH File -if [ ! -f "$outputBashScript" ]; then - touch $outputBashScript -fi - -echo "#!/bin/bash" >> $outputBashScript -echo >> $outputBashScript -echo "port=\$1" >> $outputBashScript -echo "baud=\$2" >> $outputBashScript -linuxFlashCommand="Python esptool.py --port \$port --baud \$baud" -echo "$linuxFlashCommand $writeParameters $partitionsParameters" >> $outputBashScript - -# Write Windows BAT File -if [ ! -f "$outputBatScript" ]; then - touch $outputBatScript -fi - -echo "echo off" >> $outputBatScript -echo "" >> $outputBatScript -echo "set port=%1" >> $outputBatScript -echo "set baud=%2" >> $outputBatScript -windowsFlashCommand="Python esptool.py --port %port% --baud %baud%" -echo "$windowsFlashCommand $writeParameters $partitionsParameters" >> $outputBatScript - diff --git a/components/display/CMakeLists.txt b/components/display/CMakeLists.txt index 31e1c10e..b036e9ca 100644 --- a/components/display/CMakeLists.txt +++ b/components/display/CMakeLists.txt @@ -3,7 +3,7 @@ set(TJPGD tjpgd) idf_component_register(SRC_DIRS . core core/ifaces INCLUDE_DIRS . core - REQUIRES platform_config tools esp_common spiffs + REQUIRES tools platform_config esp_common spiffs PRIV_REQUIRES services freertos driver ${TJPGD} EMBED_FILES note.jpg ) diff --git a/components/display/ILI9341.c b/components/display/ILI9341.c index af0ce1d4..f6a2dc30 100644 --- a/components/display/ILI9341.c +++ b/components/display/ILI9341.c @@ -319,12 +319,12 @@ static const struct GDS_Device ILI9341_X = { .Mode = GDS_RGB565, .Depth = 16, }; -struct GDS_Device* ILI9341_Detect(sys_Display * Driver, struct GDS_Device* Device) { +struct GDS_Device* ILI9341_Detect(sys_display_config * Driver, struct GDS_Device* Device) { uint8_t Model; int Depth=16; // 16bit colordepth - if(Driver->common.driver == sys_DisplayDriverEnum_ILI9341) Model = ILI9341; - else if(Driver->common.driver == sys_DisplayDriverEnum_ILI9341_24) Model = ILI9341_24; + if(Driver->common.driver == sys_display_drivers_ILI9341) Model = ILI9341; + else if(Driver->common.driver == sys_display_drivers_ILI9341_24) Model = ILI9341_24; else return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); diff --git a/components/display/SH1106.c b/components/display/SH1106.c index 78a44f03..7a2f0300 100644 --- a/components/display/SH1106.c +++ b/components/display/SH1106.c @@ -152,9 +152,9 @@ static const struct GDS_Device SH1106 = { #endif }; -struct GDS_Device* SH1106_Detect(sys_Display * Driver, struct GDS_Device* Device) { +struct GDS_Device* SH1106_Detect(sys_display_config * Driver, struct GDS_Device* Device) { // if (!strcasestr(Driver, "SH1106")) return NULL; - if(Driver->common.driver != sys_DisplayDriverEnum_SH1106) return NULL; + if(Driver->common.driver != sys_display_drivers_SH1106) return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); *Device = SH1106; diff --git a/components/display/SSD1306.c b/components/display/SSD1306.c index 44d07cdc..4f1bb73f 100644 --- a/components/display/SSD1306.c +++ b/components/display/SSD1306.c @@ -162,8 +162,8 @@ static const struct GDS_Device SSD1306 = { #endif }; -struct GDS_Device* SSD1306_Detect(sys_Display * Driver, struct GDS_Device* Device) { - if(Driver->common.driver != sys_DisplayDriverEnum_SSD1306) return NULL; +struct GDS_Device* SSD1306_Detect(sys_display_config * Driver, struct GDS_Device* Device) { + if(Driver->common.driver != sys_display_drivers_SSD1306) return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); *Device = SSD1306; diff --git a/components/display/SSD1322.c b/components/display/SSD1322.c index 0f368a60..e58f03bf 100644 --- a/components/display/SSD1322.c +++ b/components/display/SSD1322.c @@ -191,8 +191,8 @@ static const struct GDS_Device SSD1322 = { .Mode = GDS_GRAYSCALE, .Depth = 4, }; -struct GDS_Device* SSD1322_Detect(sys_Display * Driver, struct GDS_Device* Device) { - if(Driver->common.driver != sys_DisplayDriverEnum_SSD1322) return NULL; +struct GDS_Device* SSD1322_Detect(sys_display_config * Driver, struct GDS_Device* Device) { + if(Driver->common.driver != sys_display_drivers_SSD1322) return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); diff --git a/components/display/SSD132x.c b/components/display/SSD132x.c index 5020b629..c0b32afc 100644 --- a/components/display/SSD132x.c +++ b/components/display/SSD132x.c @@ -319,12 +319,12 @@ static const struct GDS_Device SSD132x = { .Mode = GDS_GRAYSCALE, .Depth = 4, }; -struct GDS_Device* SSD132x_Detect(sys_Display * Driver, struct GDS_Device* Device) { +struct GDS_Device* SSD132x_Detect(sys_display_config * Driver, struct GDS_Device* Device) { uint8_t Model; int Depth; - if(Driver->common.driver == sys_DisplayDriverEnum_SSD1326) Model = SSD1326; - else if(Driver->common.driver == sys_DisplayDriverEnum_SSD1327) Model = SSD1327; + if(Driver->common.driver == sys_display_drivers_SSD1326) Model = SSD1326; + else if(Driver->common.driver == sys_display_drivers_SSD1327) Model = SSD1327; return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); diff --git a/components/display/SSD1351.c b/components/display/SSD1351.c index d1c7b3a8..d692c02a 100644 --- a/components/display/SSD1351.c +++ b/components/display/SSD1351.c @@ -268,10 +268,10 @@ static const struct GDS_Device SSD1351 = { .Mode = GDS_RGB565, .Depth = 16, }; -struct GDS_Device* SSD1351_Detect(sys_Display * Driver, struct GDS_Device* Device) { +struct GDS_Device* SSD1351_Detect(sys_display_config * Driver, struct GDS_Device* Device) { int Depth; - if(Driver->common.driver != sys_DisplayDriverEnum_SSD1351) return NULL; + if(Driver->common.driver != sys_display_drivers_SSD1351) return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); diff --git a/components/display/SSD1675.c b/components/display/SSD1675.c index d298f228..a1b01781 100644 --- a/components/display/SSD1675.c +++ b/components/display/SSD1675.c @@ -224,30 +224,31 @@ static bool Init( struct GDS_Device* Device ) { Update( Device ); return true; -} +} static const struct GDS_Device SSD1675 = { - .DrawBitmapCBR = DrawBitmapCBR, .ClearWindow = ClearWindow, - .DrawPixelFast = _DrawPixel, - .Update = Update, .Init = Init, - .Mode = GDS_MONO, .Depth = 1, - .Alloc = GDS_ALLOC_NONE, -}; + .DrawBitmapCBR = DrawBitmapCBR, + .ClearWindow = ClearWindow, + .DrawPixelFast = _DrawPixel, + .Update = Update, + .Init = Init, + .Mode = GDS_MONO, + .Depth = 1, + .Alloc = GDS_ALLOC_NONE, +}; -struct GDS_Device* SSD1675_Detect(sys_Display * Driver, struct GDS_Device* Device) { - if(Driver->common.driver != sys_DisplayDriverEnum_SSD1675) return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - *Device = SSD1675; - - char *p; - struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private; - Private->ReadyPin = -1; - if(Driver->common.has_ready && Driver->common.ready.pin >=0){ - Private->ReadyPin = Driver->common.ready.pin; - } - - ESP_LOGI(TAG, "SSD1675 driver with ready GPIO %d", Private->ReadyPin); - - return Device; +struct GDS_Device* SSD1675_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + if (Driver->common.driver != sys_display_drivers_SSD1675) return NULL; + + if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); + *Device = SSD1675; + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->ReadyPin = -1; + if (Driver->common.ready >= 0) { + Private->ReadyPin = Driver->common.ready; + } + + ESP_LOGI(TAG, "SSD1675 driver with ready GPIO %d", Private->ReadyPin); + + return Device; } \ No newline at end of file diff --git a/components/display/ST77xx.c b/components/display/ST77xx.c index f874067c..42260375 100644 --- a/components/display/ST77xx.c +++ b/components/display/ST77xx.c @@ -273,11 +273,11 @@ static const struct GDS_Device ST77xx = { .Mode = GDS_RGB565, .Depth = 16, }; -struct GDS_Device* ST77xx_Detect(sys_Display * Driver, struct GDS_Device* Device) { +struct GDS_Device* ST77xx_Detect(sys_display_config * Driver, struct GDS_Device* Device) { uint8_t Model; int Depth; - if(Driver->common.driver == sys_DisplayDriverEnum_ST7735) Model = ST7735; - else if(Driver->common.driver == sys_DisplayDriverEnum_ST7789) Model = ST7789; + if(Driver->common.driver == sys_display_drivers_ST7735) Model = ST7735; + else if(Driver->common.driver == sys_display_drivers_ST7789) Model = ST7789; else return NULL; if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); diff --git a/components/display/core/gds.c b/components/display/core/gds.c index 44581774..4ebe6477 100644 --- a/components/display/core/gds.c +++ b/components/display/core/gds.c @@ -15,7 +15,7 @@ #include "driver/gpio.h" #include "driver/ledc.h" #include "esp_log.h" -#include "Configurator.h" +#include "Config.h" #include "gds.h" #include "gds_private.h" @@ -30,8 +30,8 @@ static struct GDS_BacklightPWM PWMConfig; static char TAG[] = "gds"; -struct GDS_Device* GDS_AutoDetect( sys_Display * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM* PWM ) { - if (!Driver->has_common || Driver->common.driver == sys_DisplayDriverEnum_UNSPECIFIED_DRIVER) return NULL; +struct GDS_Device* GDS_AutoDetect( sys_display_config * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM* PWM ) { + if (!Driver->has_common || Driver->common.driver == sys_display_drivers_UNSPECIFIED) return NULL; if (PWM) PWMConfig = *PWM; for (int i = 0; DetectFunc[i]; i++) { diff --git a/components/display/core/gds.h b/components/display/core/gds.h index 0b96c7a4..fdac295a 100644 --- a/components/display/core/gds.h +++ b/components/display/core/gds.h @@ -3,7 +3,7 @@ #include #include -#include "Configurator.h" +#include "Config.h" /* NOTE for drivers: The build-in DrawPixel(Fast), DrawCBR and ClearWindow have optimized for 1 bit @@ -34,9 +34,9 @@ struct GDS_Layout { bool ColorSwap; }; -typedef struct GDS_Device* GDS_DetectFunc(sys_Display * Driver, struct GDS_Device *Device); +typedef struct GDS_Device* GDS_DetectFunc(sys_display_config * Driver, struct GDS_Device *Device); -struct GDS_Device* GDS_AutoDetect( sys_Display * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM *PWM ); +struct GDS_Device* GDS_AutoDetect( sys_display_config * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM *PWM ); void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ); void GDS_DisplayOn( struct GDS_Device* Device ); diff --git a/components/display/core/gds_font.c b/components/display/core/gds_font.c index 0cb9ca49..59fd1858 100644 --- a/components/display/core/gds_font.c +++ b/components/display/core/gds_font.c @@ -40,9 +40,10 @@ static bool LoadFont(struct GDS_FontDef ** fontPtr, const char * fileName){ ESP_LOGE(TAG, "Invalid pointer for LoadFont"); return false; } - + char font_file_name[CONFIG_SPIFFS_OBJ_NAME_LEN+1]={0}; + snprintf(font_file_name,sizeof(font_file_name),"/spiffs/fonts/%s",fileName); // Allocate DMA-capable memory for the font - struct GDS_FontDef* loadedFont = load_file_dma(NULL,"fonts",fileName); + struct GDS_FontDef* loadedFont = load_file_dma(NULL,font_file_name); // Check if allocation succeeded if (loadedFont == NULL) { diff --git a/components/display/display.c b/components/display/display.c index 8d5c1e10..10aaecaa 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -22,7 +22,7 @@ #include "gds_text.h" #include "gds_font.h" #include "gds_image.h" -#include "Configurator.h" +#include "Config.h" static const char *TAG = "display"; #define min(a,b) (((a) < (b)) ? (a) : (b)) @@ -44,7 +44,7 @@ static EXT_RAM_ATTR struct { char header[HEADER_SIZE + 1]; char string[SCROLLABLE_SIZE + 1]; int offset, boundary; - sys_Metadata *metadata_config; + sys_metadata_config *metadata_config; bool timer, refresh; uint32_t elapsed; struct { @@ -76,10 +76,11 @@ GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD void display_init(char *welcome) { bool init = false; int width = -1, height = -1, backlight_pin = -1, RST_pin = -1; - sys_Display * sys_display; - sys_DispCommon * common; + sys_display_config * sys_display; + sys_display_common * common; - if(!SYS_DISPLAY(sys_display) || !SYS_DISPLAY_COMMON(common)){ + if(!SYS_DISPLAY(sys_display) || !SYS_DISPLAY_COMMON(common) || common->driver == sys_display_drivers_UNSPECIFIED){ + ESP_LOGI(TAG,"No display configuration"); return; } // // so far so good @@ -87,11 +88,10 @@ void display_init(char *welcome) { ESP_LOGE(TAG,"Misconfigured display missing data"); return; } - - ESP_LOGI(TAG, "Trying to configure display type %s, driver: %s", - sys_DeviceTypeEnum_name(sys_display->type), - sys_DisplayDriverEnum_name(common->driver)); - if (common->has_back && common->back.pin >= 0) { + ESP_LOGI(TAG, "Initializing display type %s, driver: %s", + sys_dev_common_types_name(sys_display->type), + sys_display_drivers_name(common->driver)); + if (common->back >= 0) { struct GDS_BacklightPWM PWMConfig = { .Channel = pwm_system.base_channel++, .Timer = pwm_system.timer, .Max = pwm_system.max, .Init = false }; display = GDS_AutoDetect(sys_display, drivers, &PWMConfig); } else { @@ -99,38 +99,27 @@ void display_init(char *welcome) { } if (display) { - if(common->has_reset){ - RST_pin = common->reset.pin; - } - if(common->has_back){ - backlight_pin = common->back.pin; - } + RST_pin = common->reset; + backlight_pin = common->back; width = common->width; height = common->height; // Detect driver interface - if (sys_display->which_dispType == sys_Display_i2c_tag && i2c_system_port != -1){ + if (sys_display->which_dispType == sys_display_config_i2c_tag && platform->dev.i2c.port != sys_i2c_port_UNSPECIFIED){ int address = 0x3C; address = sys_display->dispType.i2c.address; init = true; - GDS_I2CInit( i2c_system_port, -1, -1, i2c_system_speed ) ; + GDS_I2CInit( platform->dev.i2c.port-sys_i2c_port_PORT0, -1, -1, platform->dev.i2c.speed ) ; GDS_I2CAttachDevice( display, width, height, address, RST_pin, backlight_pin ); ESP_LOGI(TAG, "Display is I2C on port %u", address); - } else if (sys_display->which_dispType == sys_Display_spi_tag && spi_system_host != -1) { + } else if (sys_display->which_dispType == sys_display_config_spi_tag && spi_system_host != -1) { int CS_pin = -1, speed = 0, mode = 0; - if(sys_display->dispType.spi.has_cs){ - CS_pin = sys_display->dispType.spi.cs.pin; - } + CS_pin = sys_display->dispType.spi.cs; speed = sys_display->dispType.spi.speed; + mode = sys_display->dispType.spi.mode; - //todo: what is mode? - - // PARSE_PARAM(config, "mode", '=', mode); - - // todo: need to handle display offsets - init = true; GDS_SPIInit( spi_system_host, spi_system_dc_gpio ); GDS_SPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode ); @@ -174,7 +163,7 @@ void display_init(char *welcome) { // leave room for artwork is display is horizontal-style if (displayer.metadata_config->has_artwork && displayer.metadata_config->artwork.enabled) { - // todo : check for resize flag + #pragma message("todo: check for resize flag and possibly offsets?") displayer.artwork.enable = true; displayer.artwork.fit = true; if (height <= 64 && width > height * 2) diff --git a/components/driver_bt/bt_app_core.c b/components/driver_bt/bt_app_core.c index fd7c1bdf..281ad606 100644 --- a/components/driver_bt/bt_app_core.c +++ b/components/driver_bt/bt_app_core.c @@ -6,31 +6,31 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include -#include +#include "bt_app_core.h" +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_gap_bt_api.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/task.h" -#include "esp_bt.h" -#include "esp_bt_main.h" -#include "esp_gap_bt_api.h" -#include "bt_app_core.h" #include "tools.h" +#include +#include +#include -static const char *TAG = "btappcore"; +static const char* TAG = "btappcore"; -static void bt_app_task_handler(void *arg); -static bool bt_app_send_msg(bt_app_msg_t *msg); -static void bt_app_work_dispatched(bt_app_msg_t *msg); +static void bt_app_task_handler(void* arg); +static bool bt_app_send_msg(bt_app_msg_t* msg); +static void bt_app_work_dispatched(bt_app_msg_t* msg); static xQueueHandle s_bt_app_task_queue; static bool running; -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) -{ - ESP_LOGV(TAG,"%s event 0x%x, param len %d", __func__, event, param_len); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, + bt_app_copy_cb_t p_copy_cback) { + ESP_LOGV(TAG, "%s event 0x%x, param len %d", __func__, event, param_len); bt_app_msg_t msg; memset(&msg, 0, sizeof(bt_app_msg_t)); @@ -54,36 +54,33 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, i return false; } -static bool bt_app_send_msg(bt_app_msg_t *msg) -{ +static bool bt_app_send_msg(bt_app_msg_t* msg) { if (msg == NULL) { return false; } if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_RATE_MS) != pdTRUE) { - ESP_LOGE(TAG,"%s xQueue send failed", __func__); + ESP_LOGE(TAG, "%s xQueue send failed", __func__); return false; } return true; } -static void bt_app_work_dispatched(bt_app_msg_t *msg) -{ +static void bt_app_work_dispatched(bt_app_msg_t* msg) { if (msg->cb) { msg->cb(msg->event, msg->param); } } -static void bt_app_task_handler(void *arg) -{ +static void bt_app_task_handler(void* arg) { bt_app_msg_t msg; - esp_err_t err; - - s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); - - esp_bt_controller_mem_release(ESP_BT_MODE_BLE); + esp_err_t err; + + s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); + + esp_bt_controller_mem_release(ESP_BT_MODE_BLE); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE ) { + if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err)); goto exit; @@ -104,17 +101,16 @@ static void bt_app_task_handler(void *arg) goto exit; } } - - /* Bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch((bt_av_hdl_stack_evt_t*) arg, BT_APP_EVT_STACK_UP, NULL, 0, NULL); - + + /* Bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch((bt_av_hdl_stack_evt_t*)arg, BT_APP_EVT_STACK_UP, NULL, 0, NULL); #if (CONFIG_BT_SSP_ENABLED) /* Set default parameters for Secure Simple Pairing */ esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); #endif - + /* * Set default parameters for Legacy Pairing * Use variable pin, input pin code when pairing @@ -122,19 +118,19 @@ static void bt_app_task_handler(void *arg) esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; esp_bt_pin_code_t pin_code; esp_bt_gap_set_pin(pin_type, 0, pin_code); - - running = true; - - while (running) { + + running = true; + + while (running) { if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) { - ESP_LOGV(TAG,"%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); - + ESP_LOGV(TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); + switch (msg.sig) { case BT_APP_SIG_WORK_DISPATCH: bt_app_work_dispatched(&msg); break; default: - ESP_LOGW(TAG,"%s, unhandled sig: %d", __func__, msg.sig); + ESP_LOGW(TAG, "%s, unhandled sig: %d", __func__, msg.sig); break; } @@ -142,40 +138,37 @@ static void bt_app_task_handler(void *arg) free(msg.param); } } else { - ESP_LOGW(TAG,"No messaged received from queue."); + ESP_LOGW(TAG, "No messaged received from queue."); } } - - ESP_LOGD(TAG, "bt_app_task shutting down"); - - if (esp_bluedroid_disable() != ESP_OK) goto exit; - // this disable has a sleep timer BTA_DISABLE_DELAY in bt_target.h and - // if we don't wait for it then disable crashes... don't know why - vTaskDelay(2*200 / portTICK_PERIOD_MS); - + + ESP_LOGD(TAG, "bt_app_task shutting down"); + + if (esp_bluedroid_disable() != ESP_OK) goto exit; + // this disable has a sleep timer BTA_DISABLE_DELAY in bt_target.h and + // if we don't wait for it then disable crashes... don't know why + vTaskDelay(2 * 200 / portTICK_PERIOD_MS); + ESP_LOGD(TAG, "esp_bluedroid_disable called successfully"); if (esp_bluedroid_deinit() != ESP_OK) goto exit; - + ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully"); if (esp_bt_controller_disable() != ESP_OK) goto exit; - + ESP_LOGD(TAG, "esp_bt_controller_disable called successfully"); if (esp_bt_controller_deinit() != ESP_OK) goto exit; - - ESP_LOGD(TAG, "bt stopped successfully"); + + ESP_LOGD(TAG, "bt stopped successfully"); exit: - vQueueDelete(s_bt_app_task_queue); - running = false; + vQueueDelete(s_bt_app_task_queue); + running = false; vTaskDelete(NULL); } -void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler) -{ +void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler) { + xTaskCreate(bt_app_task_handler, "BtAppT", 4096, handler, configMAX_PRIORITIES - 3, NULL); } -void bt_app_task_shut_down(void) -{ - running = false; -} +void bt_app_task_shut_down(void) { running = false; } diff --git a/components/driver_bt/bt_app_core.h b/components/driver_bt/bt_app_core.h index 7ccf9651..7ef70c90 100644 --- a/components/driver_bt/bt_app_core.h +++ b/components/driver_bt/bt_app_core.h @@ -8,53 +8,58 @@ #ifndef __BT_APP_CORE_H__ #define __BT_APP_CORE_H__ +#include "Status.pb.h" #include "esp_log.h" #include "time.h" -#include #include +#include #include -#include "Status.pb.h" - -#define BT_APP_CORE_TAG "BT_APP_CORE" -#define BT_APP_SIG_WORK_DISPATCH (0x01) +#ifdef __cplusplus +extern "C" { +#endif +#define BT_APP_CORE_TAG "BT_APP_CORE" +#define BT_APP_SIG_WORK_DISPATCH (0x01) enum { BT_APP_EVT_STACK_UP = 0, }; - -extern sys_AV_STATE bt_app_source_get_a2d_state(); -extern sys_MEDIA_STATE bt_app_source_get_media_state(); +extern sys_status_av_states bt_app_source_get_a2d_state(); +extern sys_status_media_states bt_app_source_get_media_state(); /** * @brief handler for the dispatched work */ -typedef void (* bt_app_cb_t) (uint16_t event, void *param); +typedef void (*bt_app_cb_t)(uint16_t event, void* param); /* message to be sent */ typedef struct { - uint16_t sig; /*!< signal to bt_app_task */ - uint16_t event; /*!< message event id */ - bt_app_cb_t cb; /*!< context switch callback */ - void *param; /*!< parameter area needs to be last */ + uint16_t sig; /*!< signal to bt_app_task */ + uint16_t event; /*!< message event id */ + bt_app_cb_t cb; /*!< context switch callback */ + void* param; /*!< parameter area needs to be last */ } bt_app_msg_t; /** * @brief parameter deep-copy function to be customized */ -typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src); +typedef void (*bt_app_copy_cb_t)(bt_app_msg_t* msg, void* p_dest, void* p_src); /** * @brief callback for startup event */ -typedef void bt_av_hdl_stack_evt_t(uint16_t event, void *p_param); +typedef void bt_av_hdl_stack_evt_t(uint16_t event, void* p_param); /** * @brief work dispatcher for the application task */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, + bt_app_copy_cb_t p_copy_cback); void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler); void bt_app_task_shut_down(void); #endif /* __BT_APP_CORE_H__ */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index c5e9db08..16fa5ccf 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -21,7 +21,7 @@ #include "esp_gap_bt_api.h" #include "esp_a2dp_api.h" #include "esp_avrc_api.h" -#include "Configurator.h" +#include "Config.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "tools.h" @@ -45,7 +45,6 @@ static const char BT_RC_CT_TAG[] = "RCCT"; #define CONFIG_BT_NAME "ESP32-BT" #endif -static char * bt_name = NULL; static bool (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...); static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len); @@ -511,7 +510,7 @@ static void volume_set_by_local_host(int value, bool is_step) _lock_release(&s_volume_lock); if(sys_state->bt_sink_volume != s_volume){ sys_state->bt_sink_volume = s_volume; - configurator_raise_state_changed(); + config_raise_state_changed(); } if (s_volume_notify) { @@ -567,8 +566,8 @@ void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb) bt_app_a2d_cmd_cb = cmd_handler; cmd_handler_chain = cmd_cb; bt_app_a2d_data_cb = data_cb; - sys_BluetoothSink * bt_sink; - if(!SYS_SERVICES_BTSINK(bt_sink)){ + sys_services_bt_sink * bt_sink; + if(!sys_services_config_BTSINK(bt_sink)){ return; } char pin_code[ESP_BT_PIN_CODE_LEN+1] = "1234\0"; @@ -583,7 +582,7 @@ void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb) */ esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED; strncpy(pin_code,bt_sink->pin,sizeof(pin_code)); - if(SYS_SERVICES_BTSINK(bt_sink) && strlen(bt_sink->pin)>ESP_BT_PIN_CODE_LEN){ + if( strlen(bt_sink->pin)>ESP_BT_PIN_CODE_LEN){ ESP_LOGW(BT_AV_TAG, "BT Sink pin code [%s] too long. ", bt_sink->pin); pin_code[ESP_BT_PIN_CODE_LEN] = '\0'; @@ -606,7 +605,6 @@ void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb) if (bError) memcpy(esp_pin_code, "1234", 4); esp_bt_gap_set_pin(pin_type, strlen(pin_code), esp_pin_code); - free(pin_code); } void bt_sink_deinit(void) diff --git a/components/driver_bt/bt_app_source.c b/components/driver_bt/bt_app_source.c index 724ca50c..047b9a1f 100644 --- a/components/driver_bt/bt_app_source.c +++ b/components/driver_bt/bt_app_source.c @@ -20,8 +20,10 @@ #include "cJSON.h" #include "tools.h" #include "accessors.h" -#include "Configurator.h" +#include "Config.h" #include "Status.pb.h" +#include "bootstate.h" + static const char * TAG = "bt_app_source"; static const char * BT_RC_CT_TAG="RCCT"; @@ -31,11 +33,12 @@ extern void output_bt_stop(void); extern void output_bt_start(void); extern char* output_state_str(void); extern bool output_stopped(void); -extern bool is_recovery_running; +extern sys_squeezelite_config* get_profile(const char* name); + static void bt_app_av_state_connecting(uint16_t event, void *param); static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param); -sys_OutputBT * out_bt = NULL; +sys_squeezelite_bt * out_bt = NULL; #define BT_APP_HEART_BEAT_EVT (0xff00) @@ -76,8 +79,8 @@ static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *even static esp_bd_addr_t s_peer_bda = {0}; static uint8_t s_peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; -sys_AV_STATE bt_app_source_a2d_state = sys_AV_STATE_A_IDLE; -sys_MEDIA_STATE bt_app_source_media_state = sys_MEDIA_STATE_M_IDLE; +sys_status_av_states bt_app_source_a2d_state = sys_status_av_states_A_IDLE; +sys_status_media_states bt_app_source_media_state = sys_status_media_states_M_IDLE; static uint32_t s_pkt_cnt = 0; static TimerHandle_t s_tmr=NULL; static int prev_duration=10000; @@ -175,23 +178,23 @@ static void peers_list_maintain(const char * s_peer_bdname, int32_t rssi){ } } -sys_AV_STATE bt_app_source_get_a2d_state(){ +sys_status_av_states bt_app_source_get_a2d_state(){ if(!is_recovery_running){ // if we are in recovery mode, don't log BT status - ESP_LOGD(TAG,"a2dp status: %u = %s", bt_app_source_a2d_state, sys_AV_STATE_name(bt_app_source_a2d_state)); + ESP_LOGD(TAG,"a2dp status: %u = %s", bt_app_source_a2d_state, sys_status_av_states_name(bt_app_source_a2d_state)); } return bt_app_source_a2d_state; } -sys_MEDIA_STATE bt_app_source_get_media_state(){ - ESP_LOGD(TAG,"media state : %s ", sys_MEDIA_STATE_name(bt_app_source_media_state)); +sys_status_media_states bt_app_source_get_media_state(){ + ESP_LOGD(TAG,"media state : %s ", sys_status_media_states_name(bt_app_source_media_state)); return bt_app_source_media_state; } void set_app_source_state(int new_state){ if(bt_app_source_a2d_state!=new_state){ - ESP_LOGD(TAG, "Updating state from %s to %s", sys_AV_STATE_name(bt_app_source_a2d_state), sys_AV_STATE_name(new_state)); + ESP_LOGD(TAG, "Updating state from %s to %s", sys_status_av_states_name(bt_app_source_a2d_state), sys_status_av_states_name(new_state)); bt_app_source_a2d_state=new_state; } } @@ -202,39 +205,37 @@ void set_a2dp_media_state(int new_state){ } } -void hal_bluetooth_init() -{ - - if(!ASSIGN_COND_VAL_3LVL(services,squeezelite,output_bt,out_bt) ){ - ESP_LOGD(TAG,"Bluetooth not configured"); +void hal_bluetooth_init() { + sys_squeezelite_config* config = get_profile(NULL); // get the active profile + sys_squeezelite_bt* out_bt = (config && config->has_output_bt) ? &config->output_bt : NULL; + if (!out_bt) { + ESP_LOGD(TAG, "Bluetooth not configured"); return; } - if(strlen(out_bt->sink_name) == 0){ - ESP_LOGE(TAG,"Sink name not configured!"); + if (strlen(out_bt->sink_name) == 0) { + ESP_LOGE(TAG, "Sink name not configured!"); return; } - ESP_LOGD(TAG,"Initializing bluetooth sink"); + ESP_LOGD(TAG, "Initializing bluetooth sink"); - - // create task and run event loop + // create task and run event loop bt_app_task_start_up(bt_av_hdl_stack_evt); - /* - * Set default parameters for Legacy Pairing - * Use variable pin, input pin code when pairing - */ - esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; + /* + * Set default parameters for Legacy Pairing + * Use variable pin, input pin code when pairing + */ + esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; uint8_t pin_code_len; - uint8_t *pin_code; - if(strlen(out_bt->pin) == 0){ - pin_code = (uint8_t *)"0000"; + uint8_t* pin_code; + if (strlen(out_bt->pin) == 0) { + pin_code = (uint8_t*)"0000"; pin_code_len = 4; - } - else { - pin_code = (uint8_t *) out_bt->pin; + } else { + pin_code = (uint8_t*)out_bt->pin; pin_code_len = strlen(out_bt->pin); } - esp_bt_gap_set_pin(pin_type, pin_code_len,pin_code); + esp_bt_gap_set_pin(pin_type, pin_code_len, pin_code); } void hal_bluetooth_stop(void) { @@ -301,8 +302,8 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) { peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_PURGE); - if (bt_app_source_a2d_state == sys_AV_STATE_A_DISCOVERED) { - set_app_source_state(sys_AV_STATE_A_CONNECTING); + if (bt_app_source_a2d_state == sys_status_av_states_A_DISCOVERED) { + set_app_source_state(sys_status_av_states_A_CONNECTING); ESP_LOGI(TAG,"Discovery completed. Ready to start connecting to %s. ", s_peer_bdname); esp_a2d_source_connect(s_peer_bda); } else { @@ -403,7 +404,7 @@ static const char * conn_state_str(esp_a2d_connection_state_t state){ static void unexpected_connection_state(int from, esp_a2d_connection_state_t to) { - ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", sys_AV_STATE_name(from), from,conn_state_str(to), to); + ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", sys_status_av_states_name(from), from,conn_state_str(to), to); } static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param){ @@ -444,20 +445,20 @@ static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t * else { ESP_LOGW(TAG,"A2DP connect unsuccessful"); } - set_app_source_state(sys_AV_STATE_A_UNCONNECTED); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); break; case ESP_A2D_CONNECTION_STATE_CONNECTING: break; case ESP_A2D_CONNECTION_STATE_CONNECTED: - set_app_source_state(sys_AV_STATE_A_CONNECTED); - set_a2dp_media_state(sys_MEDIA_STATE_M_IDLE); + set_app_source_state(sys_status_av_states_A_CONNECTED); + set_a2dp_media_state(sys_status_media_states_M_IDLE); ESP_LOGD(TAG,"Setting scan mode to ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE"); esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); ESP_LOGD(TAG,"Done setting scan mode. App state is now CONNECTED and media state IDLE."); break; case ESP_A2D_CONNECTION_STATE_DISCONNECTING: unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - set_app_source_state(sys_AV_STATE_A_CONNECTING); + set_app_source_state(sys_status_av_states_A_CONNECTING); break; default: break; @@ -469,7 +470,7 @@ static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *p { case ESP_A2D_CONNECTION_STATE_DISCONNECTED: ESP_LOGW(TAG,"a2dp disconnected"); - set_app_source_state(sys_AV_STATE_A_UNCONNECTED); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); break; case ESP_A2D_CONNECTION_STATE_CONNECTING: @@ -479,7 +480,7 @@ static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *p unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); break; case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - set_app_source_state(sys_AV_STATE_A_DISCONNECTING); + set_app_source_state(sys_status_av_states_A_DISCONNECTING); break; default: @@ -493,7 +494,7 @@ static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_ { case ESP_A2D_CONNECTION_STATE_DISCONNECTED: ESP_LOGI(TAG,"a2dp disconnected"); - set_app_source_state(sys_AV_STATE_A_UNCONNECTED); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); break; case ESP_A2D_CONNECTION_STATE_CONNECTING: @@ -513,24 +514,24 @@ static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_ static void bt_app_av_sm_hdlr(uint16_t event, void *param) { - ESP_LOGV(TAG,"bt_app_av_sm_hdlr.%s a2d state: %s", event==BT_APP_HEART_BEAT_EVT?"Heart Beat.":"",sys_AV_STATE_name(bt_app_source_a2d_state)); + ESP_LOGV(TAG,"bt_app_av_sm_hdlr.%s a2d state: %s", event==BT_APP_HEART_BEAT_EVT?"Heart Beat.":"",sys_status_av_states_name(bt_app_source_a2d_state)); switch (bt_app_source_a2d_state) { - case sys_AV_STATE_A_DISCOVERING: - ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_AV_STATE_name(bt_app_source_a2d_state), event, output_state_str()); + case sys_status_av_states_A_DISCOVERING: + ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); break; - case sys_AV_STATE_A_DISCOVERED: - ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_AV_STATE_name(bt_app_source_a2d_state), event, output_state_str()); + case sys_status_av_states_A_DISCOVERED: + ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); break; - case sys_AV_STATE_A_UNCONNECTED: + case sys_status_av_states_A_UNCONNECTED: bt_app_av_state_unconnected(event, param); break; - case sys_AV_STATE_A_CONNECTING: + case sys_status_av_states_A_CONNECTING: bt_app_av_state_connecting(event, param); break; - case sys_AV_STATE_A_CONNECTED: + case sys_status_av_states_A_CONNECTED: bt_app_av_state_connected(event, param); break; - case sys_AV_STATE_A_DISCONNECTING: + case sys_status_av_states_A_DISCONNECTING: bt_app_av_state_disconnecting(event, param); break; default: @@ -591,7 +592,7 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param) uint8_t nameLen = 0; esp_bt_gap_dev_prop_t *p; memset(bda_str, 0x00, sizeof(bda_str)); - if(bt_app_source_a2d_state != sys_AV_STATE_A_DISCOVERING) + if(bt_app_source_a2d_state != sys_status_av_states_A_DISCOVERING) { // Ignore messages that might have been queued already // when we've discovered the target device. @@ -650,7 +651,7 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param) if (squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) >0 && strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) { ESP_LOGI(TAG,"Found our target device. address %s, name %s", bda_str, s_peer_bdname); memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN); - set_app_source_state(sys_AV_STATE_A_DISCOVERED); + set_app_source_state(sys_status_av_states_A_DISCOVERED); esp_bt_gap_cancel_discovery(); } else { ESP_LOGV(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name?squeezelite_conf.sink_name:"N/A"); @@ -698,7 +699,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) /* start device discovery */ ESP_LOGI(TAG,"Starting device discovery..."); - set_app_source_state(sys_AV_STATE_A_DISCOVERING); + set_app_source_state(sys_status_av_states_A_DISCOVERING); esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); /* create and start heart beat timer */ @@ -722,7 +723,7 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: { - ESP_LOGD(TAG,"Received %s message", sys_ESP_AVRC_CT_name(event)); + ESP_LOGD(TAG,"Received %s message", sys_status_avrc_ct_name(event)); bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); break; } @@ -735,7 +736,7 @@ static void bt_app_av_media_proc(uint16_t event, void *param) { esp_a2d_cb_param_t *a2d = NULL; switch (bt_app_source_media_state) { - case sys_MEDIA_STATE_M_IDLE: { + case sys_status_media_states_M_IDLE: { if (event == BT_APP_HEART_BEAT_EVT) { if(!output_stopped()) { @@ -749,34 +750,34 @@ static void bt_app_av_media_proc(uint16_t event, void *param) a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS ) { ESP_LOGI(TAG,"a2dp media ready, starting playback!"); - set_a2dp_media_state(sys_MEDIA_STATE_M_STARTING); + set_a2dp_media_state(sys_status_media_states_M_STARTING); esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_START); } } break; } - case sys_MEDIA_STATE_M_STARTING: { + case sys_status_media_states_M_STARTING: { if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { a2d = (esp_a2d_cb_param_t *)(param); if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_START && a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { ESP_LOGI(TAG,"a2dp media started successfully."); output_bt_start(); - set_a2dp_media_state(sys_MEDIA_STATE_M_STARTED); + set_a2dp_media_state(sys_status_media_states_M_STARTED); } else { // not started succesfully, transfer to idle state ESP_LOGI(TAG,"a2dp media start failed."); - set_a2dp_media_state(sys_MEDIA_STATE_M_IDLE); + set_a2dp_media_state(sys_status_media_states_M_IDLE); } } break; } - case sys_MEDIA_STATE_M_STARTED: { + case sys_status_media_states_M_STARTED: { if (event == BT_APP_HEART_BEAT_EVT) { if(output_stopped()) { ESP_LOGI(TAG,"Output state is %s. Stopping a2dp media ...", output_state_str()); - set_a2dp_media_state(sys_MEDIA_STATE_M_STOPPING); + set_a2dp_media_state(sys_status_media_states_M_STOPPING); esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP); } else { output_bt_tick(); @@ -784,15 +785,15 @@ static void bt_app_av_media_proc(uint16_t event, void *param) } break; } - case sys_MEDIA_STATE_M_STOPPING: { - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(sys_MEDIA_STATE_M_STOPPING)); + case sys_status_media_states_M_STOPPING: { + ESP_LOG_DEBUG_EVENT(TAG,QUOTE(sys_status_media_states_M_STOPPING)); if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { a2d = (esp_a2d_cb_param_t *)(param); if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP && a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { ESP_LOGI(TAG,"a2dp media stopped successfully..."); output_bt_stop(); - set_a2dp_media_state(sys_MEDIA_STATE_M_IDLE); + set_a2dp_media_state(sys_status_media_states_M_IDLE); } else { ESP_LOGI(TAG,"a2dp media stopping..."); esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP); @@ -801,9 +802,9 @@ static void bt_app_av_media_proc(uint16_t event, void *param) break; } - case sys_MEDIA_STATE_M_WAIT_DISCONNECT:{ + case sys_status_media_states_M_WAIT_DISCONNECT:{ esp_a2d_source_disconnect(s_peer_bda); - set_app_source_state(sys_AV_STATE_A_DISCONNECTING); + set_app_source_state(sys_status_av_states_A_DISCONNECTING); ESP_LOGI(TAG,"a2dp disconnecting..."); } } @@ -843,11 +844,11 @@ static void bt_app_av_state_unconnected(uint16_t event, void *param) uint8_t *p = s_peer_bda; ESP_LOGI(TAG, "a2dp connecting to %s, BT peer: %02x:%02x:%02x:%02x:%02x:%02x",s_peer_bdname,p[0], p[1], p[2], p[3], p[4], p[5]); if(esp_a2d_source_connect(s_peer_bda)==ESP_OK) { - set_app_source_state(sys_AV_STATE_A_CONNECTING); + set_app_source_state(sys_status_av_states_A_CONNECTING); s_connecting_intv = 0; } else { - set_app_source_state(sys_AV_STATE_A_UNCONNECTED); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); // there was an issue connecting... continue to discover ESP_LOGE(TAG,"Attempt at connecting failed, restart at discover..."); esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); @@ -877,7 +878,7 @@ static void bt_app_av_state_connecting(uint16_t event, void *param) break; case BT_APP_HEART_BEAT_EVT: if (++s_connecting_intv >= 2) { - set_app_source_state(sys_AV_STATE_A_UNCONNECTED); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); ESP_LOGW(TAG,"A2DP Connect time out! Setting state to Unconnected. "); s_connecting_intv = 0; } diff --git a/components/led_strip/CMakeLists.txt b/components/led_strip/CMakeLists.txt index c7e9f3f0..a62e1f2a 100644 --- a/components/led_strip/CMakeLists.txt +++ b/components/led_strip/CMakeLists.txt @@ -1,7 +1,7 @@ idf_component_register(SRC_DIRS . INCLUDE_DIRS . - REQUIRES platform_config tools esp_common + REQUIRES tools platform_config esp_common PRIV_REQUIRES services freertos driver ) diff --git a/components/led_strip/led_vu.c b/components/led_strip/led_vu.c index 6367208c..f62b596b 100644 --- a/components/led_strip/led_vu.c +++ b/components/led_strip/led_vu.c @@ -23,7 +23,7 @@ #include "globdefs.h" #include "monitor.h" #include "led_strip.h" -#include "Configurator.h" +#include "Config.h" #include "accessors.h" #include "led_vu.h" @@ -76,22 +76,23 @@ static void battery_svc(float value, int cells) { * */ void led_vu_init() -{ - sys_LEDStrip * config = NULL; +{ + sys_dev_led_strip*config; if(!SYS_DEV_LEDSTRIP(config)){ + ESP_LOGI(TAG,"No LED Strip configuration"); return; } - if(!!config->has_gpio ){ + if(config->gpio<0){ + ESP_LOGI(TAG,"LED Strip has no GPIO configured"); return; } - // char* config = config_alloc_get_str("led_vu_config", NULL, "N/A"); - + ESP_LOGI(TAG, "Initializing led_vu"); // Initialize led VU strip strip.length = config->length; - strip.gpio = config->gpio.pin; + strip.gpio = config->gpio; // check for valid configuration - if (config->strip_type == sys_LEDStripType_LS_UNKNOWN || !config->has_gpio || config->gpio.pin <0) { + if (config->strip_type == sys_dev_strip_types_LS_UNKNOWN || config->gpio <0) { ESP_LOGI(TAG, "led_vu configuration invalid"); return; } @@ -117,7 +118,7 @@ void led_vu_init() ESP_LOGI(TAG, "vu meter using length:%d left:%d right:%d status:%d", strip.vu_length, strip.vu_start_l, strip.vu_start_r, strip.vu_status); // create driver configuration - led_strip_config.rgb_led_type = config->strip_type == sys_LEDStripType_LS_WS2812?RGB_LED_TYPE_WS2812:RGB_LED_TYPE_MAX; + led_strip_config.rgb_led_type = config->strip_type == sys_dev_strip_types_LS_WS2812?RGB_LED_TYPE_WS2812:RGB_LED_TYPE_MAX; led_strip_config.access_semaphore = xSemaphoreCreateBinary(); led_strip_config.led_strip_length = strip.length; led_strip_config.led_strip_working = heap_caps_malloc(strip.length * sizeof(struct led_color_t), MALLOC_CAP_8BIT); diff --git a/components/metrics/CMakeLists.txt b/components/metrics/CMakeLists.txt index 289ff534..ec5fb2bf 100644 --- a/components/metrics/CMakeLists.txt +++ b/components/metrics/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRC_DIRS . INCLUDE_DIRS . - REQUIRES json tools platform_config wifi-manager esp-tls platform_config + REQUIRES json tools platform_config wifi-manager esp-tls PRIV_REQUIRES esp32 freertos ) diff --git a/components/metrics/Metrics.cpp b/components/metrics/Metrics.cpp index d1656ee2..fe1b0d15 100644 --- a/components/metrics/Metrics.cpp +++ b/components/metrics/Metrics.cpp @@ -20,13 +20,12 @@ #include "cJSON.h" #include "freertos/timers.h" #include "network_manager.h" -// #include "Configurator.h" +// #include "Config.h" #pragma message("fixme: search for TODO below") static const char* TAG = "metrics"; #if CONFIG_WITH_METRICS -extern bool is_network_connected(); #define METRICS_CLIENT_ID_LEN 50 #define MAX_HTTP_RECV_BUFFER 512 diff --git a/components/platform_config/CMakeLists.txt b/components/platform_config/CMakeLists.txt index d13b2517..658c41a1 100644 --- a/components/platform_config/CMakeLists.txt +++ b/components/platform_config/CMakeLists.txt @@ -1,5 +1,7 @@ +set(CMAKE_CXX_STANDARD 20) idf_component_register(SRC_DIRS . INCLUDE_DIRS . - PRIV_REQUIRES tools newlib console esp_common freertos tools services - REQUIRES spiffs + PRIV_REQUIRES newlib console esp_common freertos + REQUIRES spiffs tools services esp_http_server ) +add_dependencies(${COMPONENT_LIB} generate_plugins_files) \ No newline at end of file diff --git a/components/platform_config/Config.cpp b/components/platform_config/Config.cpp new file mode 100644 index 00000000..ccedda64 --- /dev/null +++ b/components/platform_config/Config.cpp @@ -0,0 +1,266 @@ +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "Config.h" +#include "PBW.h" +#include "WifiList.h" +#include "bootstate.h" +#include "DAC.pb.h" +#include "esp_log.h" +#include "esp_system.h" +#include "pb_common.h" // Nanopb header for encoding (serialization) +#include "pb_decode.h" // Nanopb header for decoding (deserialization) +#include "pb_encode.h" // Nanopb header for encoding (serialization) +#include "tools.h" +#include +#include +#include +#include +#include + +static const char* TAG = "Configurator"; + +using namespace System; +__attribute__((section(".ext_ram.bss"))) sys_config* platform; +__attribute__((section(".ext_ram.bss"))) sys_state_data* sys_state; +__attribute__((section(".ext_ram.bss"))) sys_dac_default_sets* default_dac_sets; + +__attribute__((section(".ext_ram.bss"))) System::PB configWrapper("config", &sys_config_msg, sizeof(sys_config_msg)); +__attribute__((section(".ext_ram.bss"))) System::PB stateWrapper("state", &sys_state_data_msg, sizeof(sys_state_data_msg)); +__attribute__((section(".ext_ram.bss"))) System::PB defaultSets("default_sets", &sys_dac_default_sets_msg, sizeof(sys_dac_default_sets_msg)); + +const int MaxDelay = 1000; +bool config_update_mac_string(const pb_msgdesc_t* desc, uint32_t field_tag, void* message) { + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { + if (!iter.pData) { + ESP_LOGW(TAG, "Unable to check mac string member. Data not initialized"); + return false; + } + if (iter.pData) { + auto curvalue = std::string((char*)iter.pData); + if (curvalue.find(get_mac_str()) != std::string::npos) { + ESP_LOGD(TAG, "Entry already has mac string: %s", curvalue.c_str()); + return true; + } + if (curvalue.find("@@init_from_mac@@") == std::string::npos) { + ESP_LOGW(TAG, "Member not configured for mac address or was overwritten: %s", curvalue.c_str()); + return false; + } + auto newval = std::string("squeezelite-") + get_mac_str(); + if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { + ESP_LOGD(TAG, "Field is a pointer. Freeing previous value if any: %s", STR_OR_BLANK((char*)iter.pField)); + FREE_AND_NULL(*(char**)iter.pField); + ESP_LOGD(TAG, "Field is a pointer. Setting new value as %s", newval.c_str()); + *(char**)iter.pField = strdup_psram(newval.c_str()); + } else if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { + ESP_LOGD(TAG, "Static string. Setting new value as %s from %s", newval.c_str(), STR_OR_BLANK((char*)iter.pData)); + memset((char*)iter.pData, 0x00, iter.data_size); + strncpy((char*)iter.pData, newval.c_str(), iter.data_size); + } + } else { + ESP_LOGE(TAG, "Set mac string failed: member should be initialized with default"); + return false; + } + } + return true; +} +bool set_pb_string_from_mac(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) { + if (!stream) { + // This is a size calculation pass, return true to indicate field presence + return true; + } + + // Generate the string based on MAC and prefix + const char* prefix = reinterpret_cast(*arg); + char* value = alloc_get_string_with_mac(prefix && strlen(prefix) > 0 ? prefix : "squeezelite-"); + + // Write the string to the stream + if (!pb_encode_string(stream, (uint8_t*)value, strlen(value))) { + free(value); // Free memory if encoding fails + return false; + } + + free(value); // Free memory after encoding + return true; +} + +bool config_erase_config() { + // make sure the config object doesn't have + // any pending changes to commit + ESP_LOGW(TAG, "Erasing configuration object and rebooting"); + configWrapper.ResetModified(); + // Erase the file and reboot + erase_path(configWrapper.GetFileName().c_str(), false); + guided_factory(); + return true; +} +void set_mac_string() { + auto expected = std::string("squeezelite-") + get_mac_str(); + bool changed = false; + auto config = configWrapper.get(); + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_device_tag, &config->names) || changed; + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_airplay_tag, &config->names) || changed; + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_spotify_tag, &config->names) || changed; + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, &config->names) || changed; + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, &config->names) || changed; + changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, &config->names) || changed; + + if (changed) { + ESP_LOGI(TAG, "One or more name was changed. Committing"); + configWrapper.RaiseChangedAsync(); + } +} + +void config_load() { + ESP_LOGI(TAG, "Loading configuration."); + bool restart = false; + sys_state = stateWrapper.get(); + platform = configWrapper.get(); + default_dac_sets = defaultSets.get(); + + assert(platform != nullptr); + assert(sys_state != nullptr); + assert(default_dac_sets != nullptr); + + configWrapper.get()->net.credentials = reinterpret_cast(new WifiList("wifi")); + assert(configWrapper.get()->net.credentials != nullptr); + + if (!stateWrapper.FileExists()) { + ESP_LOGI(TAG, "State file not found or is empty. "); + stateWrapper.Reinitialize(true); + stateWrapper.SetTarget(CONFIG_FW_PLATFORM_NAME); + } else { + stateWrapper.LoadFile(); + } + if (!configWrapper.FileExists()) { + ESP_LOGI(TAG, "Configuration file not found or is empty. "); + configWrapper.Reinitialize(true); + ESP_LOGI(TAG, "Current device name after load: %s", platform->names.device); + + configWrapper.SetTarget(CONFIG_FW_PLATFORM_NAME,true); + set_mac_string(); + ESP_LOGW(TAG, "Restart required after initializing configuration"); + restart = true; + + } else { + configWrapper.LoadFile(); + if (configWrapper.GetTargetName().empty() && !std::string(CONFIG_FW_PLATFORM_NAME).empty()) { + ESP_LOGW(TAG, "Config target is empty. Updating to %s", CONFIG_FW_PLATFORM_NAME); + configWrapper.Reinitialize(false,true,std::string(CONFIG_FW_PLATFORM_NAME)); + ESP_LOGW(TAG, "Restart required due to target change"); + restart = true; + } + } + if (!defaultSets.FileExists()) { + ESP_LOGE(TAG, "Default Sets file not found or is empty. (%s)", defaultSets.GetFileName().c_str()); + } else { + defaultSets.LoadFile(); + } + if (restart) { + network_async_reboot(OTA); + } +} +void config_dump_config() { + auto serialized = configWrapper.Encode(); + dump_data(serialized.data(), serialized.size()); +} + +void config_set_target(const char* target_name, bool reset) { + std::string new_target = std::string(target_name); + bool restart = false; + if (configWrapper.GetTargetName() != new_target) { + ESP_LOGI(TAG, "Setting configuration target name to %s, %s", target_name, reset ? "full reset" : "reapply only"); + if (reset) { + ESP_LOGD(TAG, "Reinitializing Config structure"); + configWrapper.Reinitialize(false,true,new_target); + } else { + ESP_LOGD(TAG, "Loading Config target values for %s", target_name); + configWrapper.SetTarget(target_name,true); + configWrapper.LoadTargetValues(); + configWrapper.RaiseChangedAsync(); + } + restart = true; + } else { + ESP_LOGW(TAG, "Target name has no change"); + } + if (stateWrapper.GetTargetName() != new_target) { + ESP_LOGI(TAG, "Setting state target name to %s, %s", target_name, reset ? "full reset" : "reapply only"); + restart=true; + if (reset) { + ESP_LOGD(TAG, "Reinitializing State structure"); + stateWrapper.Reinitialize(false,true,new_target); + } else { + ESP_LOGD(TAG, "Loading State target values for %s", target_name); + stateWrapper.SetTarget(target_name,true); + stateWrapper.LoadTargetValues(); + stateWrapper.RaiseChangedAsync(); + } + } + ESP_LOGD(TAG, "Done updating target to %s", target_name); + if(restart){ + network_async_reboot(RESTART); + } +} +void config_set_target_no_reset(const char* target_name) { config_set_target(target_name, false); } +void config_set_target_reset(const char* target_name) { config_set_target(target_name, true); } +void config_raise_changed(bool sync) { + if (sync) { + configWrapper.CommitChanges(); + } else { + configWrapper.RaiseChangedAsync(); + } +} +void config_commit_protowrapper(void* protoWrapper) { + ESP_LOGD(TAG, "Committing synchronously"); + PBHelper::SyncCommit(protoWrapper); +} + +void config_commit_state() { stateWrapper.CommitChanges(); } +void config_raise_state_changed() { stateWrapper.RaiseChangedAsync(); } + +bool config_has_changes() { return configWrapper.HasChanges() || stateWrapper.HasChanges(); } + +bool config_waitcommit() { return configWrapper.WaitForCommit(2) && stateWrapper.WaitForCommit(2); } + +bool config_http_send_config(httpd_req_t* req) { + try { + auto data = configWrapper.Encode(); + httpd_resp_send(req, (const char*)data.data(), data.size()); + return true; + } catch (const std::runtime_error& e) { + std::string errdesc = (std::string("Unable to get configuration: ") + e.what()); + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, errdesc.c_str()); + } + return false; +} + +bool system_set_string(const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value) { + pb_field_iter_t iter; + ESP_LOGD(TAG,"system_set_string. Getting new value"); + std::string newval = std::string(STR_OR_BLANK(value)); + ESP_LOGD(TAG,"system_set_string. Done getting new value"); + ESP_LOGD(TAG, "Setting value [%s] in message field tag %d", newval.c_str(), field_tag); + if (pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { + std::string old= std::string((char*)iter.pData); + if (iter.pData && old == newval) { + ESP_LOGW(TAG, "No change, from and to values are the same: [%s]", newval.c_str()); + return false; + } + if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { + ESP_LOGD(TAG, "Field is a pointer. Freeing previous value if any: %s", STR_OR_BLANK((char*)iter.pField)); + FREE_AND_NULL(*(char**)iter.pField); + ESP_LOGD(TAG, "Field is a pointer. Setting new value "); + if (!newval.empty()) { + *(char**)iter.pField = strdup_psram(newval.c_str()); + } + + } else if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { + ESP_LOGD(TAG, "Static string. Setting new value. Existing value: %s", (char*)iter.pData); + memset((char*)iter.pData, 0x00, iter.data_size); + if (!newval.empty()) { + strncpy((char*)iter.pData, newval.c_str(), iter.data_size); + } + } + ESP_LOGD(TAG, "Done setting value "); + } + return true; +} diff --git a/components/platform_config/Config.h b/components/platform_config/Config.h new file mode 100644 index 00000000..40b819ae --- /dev/null +++ b/components/platform_config/Config.h @@ -0,0 +1,49 @@ +#pragma once +#include "State.pb.h" +#include "Status.pb.h" +#include "configuration.pb.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "freertos/semphr.h" +#include "freertos/timers.h" +#include "status.pb.h" +#include "accessors.h" +#include "esp_http_server.h" +#include "PBW.h" + +#ifdef __cplusplus +extern System::PB stateWrapper; +extern System::PB configWrapper; +extern "C" { +#endif +#define PLATFORM_GET_PTR(base, sname) \ + { \ + (base && (base)->##has_##(sname) ? &(base)->sname : NULL) +#define PLATFORM_DEVICES PLATFORM_GET_PTR(platform) +void config_load(); +bool config_waitcommit(); +bool config_has_changes(); +void config_raise_changed(bool sync); +void config_raise_state_changed(); +bool config_has_changes(); +bool config_waitcommit(); +void config_set_target(const char* target_name); +void config_set_target_no_reset(const char* target_name); +void config_set_target_reset(const char* target_name); + +void config_commit_protowrapper(void * protoWrapper); +bool config_http_send_config(httpd_req_t* req); +bool config_erase_config(); +void set_mac_string(); +void config_dump_config(); +bool system_set_string( + const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value); +extern sys_config* platform; +extern sys_state_data* sys_state; +extern sys_config* presets; +#ifdef __cplusplus +} + + +#endif + diff --git a/components/platform_config/Configurator.cpp b/components/platform_config/Configurator.cpp deleted file mode 100644 index 382c7442..00000000 --- a/components/platform_config/Configurator.cpp +++ /dev/null @@ -1,480 +0,0 @@ -#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE -#include "Configurator.h" -#include "esp_log.h" -#include "esp_system.h" -#include "pb_common.h" // Nanopb header for encoding (serialization) -#include "pb_decode.h" // Nanopb header for decoding (deserialization) -#include "pb_encode.h" // Nanopb header for encoding (serialization) -// #include "sys_options.h" -#include "tools.h" -#include -#include -static const char* TAG = "Configurator"; -static const char* targets_folder = "targets"; -static const char* config_file_name = "settings.bin"; -static const char* state_file_name = "state.bin"; -__attribute__((section(".ext_ram.bss"))) PlatformConfig::Configurator configurator; -sys_Config* platform = NULL; -sys_State* sys_state = NULL; - -bool set_pb_string_from_mac(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) { - if (!stream) { - // This is a size calculation pass, return true to indicate field presence - return true; - } - - // Generate the string based on MAC and prefix - const char* prefix = reinterpret_cast(*arg); - char* value = alloc_get_string_with_mac(prefix && strlen(prefix) > 0 ? prefix : "squeezelite-"); - - // Write the string to the stream - if (!pb_encode_string(stream, (uint8_t*)value, strlen(value))) { - free(value); // Free memory if encoding fails - return false; - } - - free(value); // Free memory after encoding - return true; -} - -namespace PlatformConfig { - -EXT_RAM_ATTR static const int NO_COMMIT_PENDING = BIT0; -EXT_RAM_ATTR static const int LOAD_BIT = BIT1; -EXT_RAM_ATTR static const int NO_STATE_COMMIT_PENDING = BIT2; - -const int Configurator::MaxDelay = 1000; -const int Configurator::LockMaxWait = 20 * Configurator::MaxDelay; - -EXT_RAM_ATTR TimerHandle_t Configurator::_timer; -EXT_RAM_ATTR SemaphoreHandle_t Configurator::_mutex; -EXT_RAM_ATTR SemaphoreHandle_t Configurator::_state_mutex; -EXT_RAM_ATTR EventGroupHandle_t Configurator::_group; - -static void ConfiguratorCallback(TimerHandle_t xTimer) { - static int cnt = 0, scnt = 0; - if (configurator.HasChanges()) { - ESP_LOGI(TAG, "Configuration has some uncommitted entries"); - configurator.CommitChanges(); - } else { - if (++cnt >= 15) { - ESP_LOGV(TAG, "commit timer: commit flag not set"); - cnt = 0; - } - } - if (configurator.HasStateChanges()) { - ESP_LOGI(TAG, "State has some uncommitted changes"); - configurator.CommitState(); - } else { - if (++scnt >= 15) { - ESP_LOGV(TAG, "commit timer: commit flag not set"); - cnt = 0; - } - } - xTimerReset(xTimer, 10); -} -void Configurator::RaiseStateModified() { SetGroupBit(NO_STATE_COMMIT_PENDING, false); } -void Configurator::RaiseModified() { SetGroupBit(NO_COMMIT_PENDING, false); } -void Configurator::ResetModified() { - ESP_LOGV(TAG, "Resetting the global commit flag."); - SetGroupBit(NO_COMMIT_PENDING, false); -} -void Configurator::ResetStateModified() { - ESP_LOGV(TAG, "Resetting the state commit flag."); - SetGroupBit(NO_STATE_COMMIT_PENDING, false); -} -bool Configurator::SetGroupBit(int bit_num, bool flag) { - bool result = true; - int curFlags = xEventGroupGetBits(_group); - if ((curFlags & LOAD_BIT) && bit_num == NO_COMMIT_PENDING) { - ESP_LOGD(TAG, "Loading config, ignoring changes"); - result = false; - } - if (result) { - bool curBit = (xEventGroupGetBits(_group) & bit_num); - if (curBit == flag) { - ESP_LOGV(TAG, "Flag %d already %s", bit_num, flag ? "Set" : "Cleared"); - result = false; - } - } - if (result) { - ESP_LOGV(TAG, "%s Flag %d ", flag ? "Setting" : "Clearing", bit_num); - if (!flag) { - xEventGroupClearBits(_group, bit_num); - } else { - xEventGroupSetBits(_group, bit_num); - } - } - return result; -} -bool Configurator::Lock() { - ESP_LOGV(TAG, "Locking Configurator"); - if (xSemaphoreTake(_mutex, LockMaxWait) == pdTRUE) { - ESP_LOGV(TAG, "Configurator locked!"); - return true; - } else { - ESP_LOGE(TAG, "Semaphore take failed. Unable to lock Configurator"); - return false; - } -} -bool Configurator::LockState() { - ESP_LOGV(TAG, "Locking State"); - if (xSemaphoreTake(_state_mutex, LockMaxWait) == pdTRUE) { - ESP_LOGV(TAG, "State locked!"); - return true; - } else { - ESP_LOGE(TAG, "Semaphore take failed. Unable to lock State"); - return false; - } -} -void* Configurator::AllocGetConfigBuffer(size_t* sz, sys_Config* config) { - size_t datasz; - pb_byte_t* data = NULL; - - if (!pb_get_encoded_size(&datasz, sys_Config_fields, (const void*)platform) || datasz <= 0) { - return data; - } - data = (pb_byte_t*)malloc_init_external(datasz * sizeof(pb_byte_t)); - pb_ostream_t stream = pb_ostream_from_buffer(data, datasz); - pb_encode(&stream, sys_Config_fields, (const void*)platform); - if (sz) { - *sz = datasz * sizeof(pb_byte_t); - } - return data; -} -void* Configurator::AllocGetConfigBuffer(size_t* sz) { - return AllocGetConfigBuffer(sz, &this->_root); -} -bool Configurator::WaitForCommit() { - bool commit_pending = (xEventGroupGetBits(_group) & NO_COMMIT_PENDING) == 0; - while (commit_pending) { - ESP_LOGW(TAG, "Waiting for config commit ..."); - commit_pending = (xEventGroupWaitBits(_group, NO_COMMIT_PENDING | NO_STATE_COMMIT_PENDING, pdFALSE, pdTRUE, - (MaxDelay * 2) / portTICK_PERIOD_MS) & - ( NO_COMMIT_PENDING | NO_STATE_COMMIT_PENDING)) == 0; - if (commit_pending) { - ESP_LOGW(TAG, "Timeout waiting for config commit."); - } else { - ESP_LOGI(TAG, "Config committed!"); - } - } - return !commit_pending; -} -void Configurator::CommitChanges() { - esp_err_t err = ESP_OK; - ESP_LOGI(TAG, "Committing configuration to flash. Locking config object."); - if (!Lock()) { - ESP_LOGE(TAG, "Unable to lock config for commit "); - return; - } - ESP_LOGV(TAG, "Config Locked. Committing"); - Commit(&_root); - ResetModified(); - Unlock(); - ESP_LOGI(TAG, "Done Committing configuration to flash."); -} - -bool Configurator::CommitState() { - esp_err_t err = ESP_OK; - ESP_LOGI(TAG, "Committing configuration to flash. Locking config object."); - if (!LockState()) { - ESP_LOGE(TAG, "Unable to lock config for commit "); - return false; - } - ESP_LOGV(TAG, "Config Locked. Committing"); - CommitState(&_sys_state); - ResetStateModified(); - Unlock(); - ESP_LOGI(TAG, "Done Committing configuration to flash."); - return true; -} -bool Configurator::HasChanges() { return (xEventGroupGetBits(_group) & NO_COMMIT_PENDING); } -bool Configurator::HasStateChanges() { return (xEventGroupGetBits(_group) & NO_STATE_COMMIT_PENDING); } -void Configurator::Unlock() { - ESP_LOGV(TAG, "Unlocking Configurator!"); - xSemaphoreGive(_mutex); -} -void Configurator::UnlockState() { - ESP_LOGV(TAG, "Unlocking State!"); - xSemaphoreGive(_state_mutex); -} - -void Configurator::ResetStructure(sys_Config* config) { - if (!config) { - return; - } - sys_Config blankconfig = sys_Config_init_default; - memcpy(config, &blankconfig, sizeof(blankconfig)); -} -bool Configurator::LoadDecodeBuffer(void* buffer, size_t buffer_size) { - size_t msgsize = 0; - size_t newsize = 0; - sys_Config config = sys_Config_init_default; - bool result = Configurator::LoadDecode(buffer, buffer_size, &config); - if (result) { - Configurator::ApplyTargetSettings(&config); - } - if (result) { - void* currentbuffer = AllocGetConfigBuffer(&msgsize); - void* newbuffer = AllocGetConfigBuffer(&newsize, &config); - if (msgsize != newsize || !memcmp(currentbuffer, newbuffer, msgsize)) { - ESP_LOGI(TAG, "Config change detected."); - // todo: here we are assuming that all strings and repeated elements have fixed size - // and therefore size should always be the same. - result = Configurator::LoadDecode(buffer, buffer_size, &this->_root); - RaiseModified(); - } - free(currentbuffer); - free(newbuffer); - } - return result; -} -bool Configurator::LoadDecodeState() { - bool result = true; - sys_State blank_state = sys_State_init_default; - FILE* file = open_file("rb", state_file_name); - if (file == nullptr) { - ESP_LOGD(TAG,"No state file found. Initializing "); - pb_release(&sys_State_msg,(void *)&_sys_state); - memcpy(&_sys_state, &blank_state, sizeof(sys_State)); - ESP_LOGD(TAG,"Done Initializing state"); - return true; - } - ESP_LOGD(TAG, "Creating binding"); - pb_istream_t filestream = {&in_file_binding,NULL,0}; - ESP_LOGD(TAG, "Starting encode"); - if (!pb_decode(&filestream, &sys_State_msg, (void*)&_sys_state)) { - ESP_LOGE(TAG, "Decoding failed: %s\n", PB_GET_ERROR(&filestream)); - result = false; - } - - fclose(file); - configurator_raise_state_changed(); - ESP_LOGD(TAG, "State loaded"); - return true; -} -bool Configurator::LoadDecode( - void* buffer, size_t buffer_size, sys_Config* conf_root, bool noinit) { - if (!conf_root || !buffer) { - ESP_LOGE(TAG, "Invalid arguments passed to Load"); - } - bool result = true; - // Prepare to read the data into the 'config' structure - pb_istream_t stream = pb_istream_from_buffer((uint8_t*)buffer, buffer_size); - - // Decode the Protocol Buffers message - if (noinit) { - ESP_LOGD(TAG, "Decoding WITHOUT initialization"); - result = pb_decode_noinit(&stream, &sys_Config_msg, conf_root); - } else { - ESP_LOGD(TAG, "Decoding WITH initialization"); - result = pb_decode(&stream, &sys_Config_msg, conf_root); - } - if (!result) { - ESP_LOGE(TAG, "Failed to decode settings: %s", PB_GET_ERROR(&stream)); - return false; - } - ESP_LOGD(TAG, "Settings decoded"); - return true; -} - -bool Configurator::Commit(sys_Config* config) { - if (!config) { - ESP_LOGE(TAG, "Invalid configuration structure!"); - return false; - } - FILE* file = open_file("wb", config_file_name); - bool result = true; - if (file == nullptr) { - return false; - } - ESP_LOGD(TAG, "Creating binding"); - pb_ostream_t filestream = {&out_file_binding, file, SIZE_MAX, 0}; - ESP_LOGD(TAG, "Starting encode"); - if (!pb_encode(&filestream, sys_Config_fields, (void*)config)) { - ESP_LOGE(TAG, "Encoding failed: %s\n", PB_GET_ERROR(&filestream)); - result = false; - } - ESP_LOGD(TAG, "Encoded size: %d", filestream.bytes_written); - if (filestream.bytes_written == 0) { - ESP_LOGE(TAG, "Empty configuration!"); - ESP_LOGD(TAG, "Device name: %s", config->names.device); - } - - fclose(file); - return result; -} - -bool Configurator::CommitState(sys_State* state) { - if (!state) { - ESP_LOGE(TAG, "Invalid state structure!"); - return false; - } - FILE* file = open_file("wb", state_file_name); - bool result = true; - if (file == nullptr) { - return false; - } - ESP_LOGD(TAG, "Creating binding for state commit"); - pb_ostream_t filestream = {&out_file_binding, file, SIZE_MAX, 0}; - ESP_LOGD(TAG, "Starting state encode"); - if (!pb_encode(&filestream, sys_Config_fields, (void*)state)) { - ESP_LOGE(TAG, "Encoding failed: %s\n", PB_GET_ERROR(&filestream)); - result = false; - } - ESP_LOGD(TAG, "Encoded size: %d", filestream.bytes_written); - if (filestream.bytes_written == 0) { - ESP_LOGE(TAG, "Empty state!"); - } - - fclose(file); - return result; -} - - -void Configurator::InitLoadConfig(const char* filename) { - return Configurator::InitLoadConfig(filename, &this->_root); -} -void Configurator::InitLoadConfig(const char* filename, sys_Config* conf_root, bool noinit) { - esp_err_t err = ESP_OK; - size_t data_length = 0; - bool result = false; - ESP_LOGI(TAG, "Loading settings from %s", filename); - void* data = load_file(&data_length, filename); - if (!data) { - ESP_LOGW(TAG, "Config file %s was empty. ", filename); - return; - } else { - result = LoadDecode(data, data_length, conf_root, noinit); - free(data); - } - if (ApplyTargetSettings(conf_root)) { - result = true; - } - if (result) { - _timer = xTimerCreate( - "configTimer", MaxDelay / portTICK_RATE_MS, pdFALSE, NULL, ConfiguratorCallback); - if (xTimerStart(_timer, MaxDelay / portTICK_RATE_MS) != pdPASS) { - ESP_LOGE(TAG, "config commitment timer failed to start."); - } - } - - return; -} -bool Configurator::ApplyTargetSettings() { return ApplyTargetSettings(&this->_root); } -bool Configurator::ApplyTargetSettings(sys_Config* conf_root) { - size_t data_length = 0; - bool result = false; - std::string target_name = conf_root->target; - std::string target_file; - -#ifdef CONFIG_FW_PLATFORM_NAME - if( target_name.empty()){ - target_name = CONFIG_FW_PLATFORM_NAME; - } -#endif - target_file = target_name+ std::string(".bin"); - - std::transform(target_file.begin(), target_file.end(), target_file.begin(), - [](unsigned char c){ return std::tolower(c); }); - if (target_file.empty() || !get_file_info(NULL, targets_folder, target_file.c_str())) { - ESP_LOGD(TAG, "Platform settings file not found: %s", target_file.c_str()); - return result; - } - - ESP_LOGI(TAG, "Applying target %s settings", target_name.c_str()); - void* data = load_file(&data_length, targets_folder, target_file.c_str()); - if (!data) { - ESP_LOGE(TAG, "File read fail"); - return false; - } else { - - result = LoadDecode(data, data_length, conf_root, true); - if (result) { - ESP_LOGI(TAG, "Target %s settings loaded", target_name.c_str()); - } - free(data); - } - - return result; -} - -}; // namespace PlatformConfig - -void configurator_reset_configuration() { - ESP_LOGI(TAG, "Creating default configuration file. "); - sys_Config config = sys_Config_init_default; - ESP_LOGD(TAG, "Device name before target settings: %s", config.names.device); - PlatformConfig::Configurator::ApplyTargetSettings(&config); - ESP_LOGD(TAG, "Device name after target settings: %s", config.names.device); - ESP_LOGD(TAG, "Committing new structure"); - PlatformConfig::Configurator::Commit(&config); -} - -void configurator_load() { - struct stat fileInformation; - ESP_LOGI(TAG, "Loading system settings file"); - ESP_LOGD(TAG, "Checking if file %s exists", config_file_name); - bool found = get_file_info(&fileInformation, config_file_name); - if (!found || fileInformation.st_size == 0) { - ESP_LOGI(TAG, "Configuration file not found or is empty. "); - configurator_reset_configuration(); - } - configurator.InitLoadConfig(config_file_name); - ESP_LOGD(TAG, "Assigning global config pointer"); - platform = configurator.Root(); - configurator.LoadDecodeState(); - sys_state = configurator.RootState(); -} -bool configurator_lock() { return configurator.Lock(); } - -void configurator_unlock() { configurator.Unlock(); } -void configurator_raise_changed() { configurator.RaiseModified(); } -void configurator_raise_state_changed() { configurator.RaiseStateModified(); } - -bool configurator_has_changes() { return configurator.HasChanges(); } - -bool configurator_waitcommit() { return configurator.WaitForCommit(); } - -void* configurator_alloc_get_config(size_t* sz) { return configurator.AllocGetConfigBuffer(sz); } -bool configurator_parse_config(void* buffer, size_t buffer_size) { - // Load and decode buffer. The method also applies any overlay if needed. - return configurator.LoadDecodeBuffer(buffer, buffer_size); -} -pb_type_t configurator_get_field_type(const pb_msgdesc_t* desc, uint32_t tag) { - pb_field_iter_t iter; - if (pb_field_iter_begin(&iter, desc, NULL) && pb_field_iter_find(&iter, tag)) { - /* Found our field. */ - return iter.type; - } - return 0; -} -bool configurator_set_string( - const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value) { - pb_field_iter_t iter; - const char * newval = STR_OR_BLANK(value); - ESP_LOGD(TAG, "Setting value [%s] in message field tag %d",newval , field_tag); - if (pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { - if (iter.pData && !strcmp((char*)iter.pData, newval)) { - ESP_LOGW(TAG, "No change, from and to values are the same: [%s]", STR_OR_BLANK(newval)); - return false; - } - if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { - ESP_LOGD(TAG, "Field is a pointer. Freeing previous value if any"); - FREE_AND_NULL(iter.pData); - ESP_LOGD(TAG, "Field is a pointer. Setting new value "); - if(newval && strlen(newval)>0){ - iter.pData = strdup_psram(newval); - } - - } else if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { - ESP_LOGD(TAG, "Static string. Setting new value"); - memset(iter.pData,0x00,iter.data_size); - if(newval && strlen(newval)>0){ - strncpy((char*)iter.pData, newval, iter.data_size); - } - } - ESP_LOGD(TAG, "Done setting value "); - } - return true; -} \ No newline at end of file diff --git a/components/platform_config/Configurator.h b/components/platform_config/Configurator.h deleted file mode 100644 index 3ed9b34e..00000000 --- a/components/platform_config/Configurator.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include "State.pb.h" -#include "configuration.pb.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "freertos/semphr.h" -#include "freertos/timers.h" -#include "status.pb.h" -#include -#include "accessors.h" -#ifdef __cplusplus -#include -#include -#include - -extern "C" { -#endif -#define PLATFORM_GET_PTR(base, sname) \ - { \ - (base && (base)->##has_##(sname) ? &(base)->sname : NULL) -#define PLATFORM_DEVICES PLATFORM_GET_PTR(platform) -void configurator_load(); -bool configurator_waitcommit(); -bool configurator_has_changes(); -bool configurator_lock(); -void configurator_unlock(); -void configurator_raise_changed(); -void configurator_raise_state_changed(); -bool configurator_has_changes(); -bool configurator_waitcommit(); -void* configurator_alloc_get_config(size_t* sz); -bool configurator_parse_config(void* buffer, size_t buffer_size); -void configurator_reset_configuration(); -pb_type_t configurator_get_field_type(const pb_msgdesc_t* desc, uint32_t tag); -bool configurator_set_string( - const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value); -extern sys_Config* platform; -extern sys_State* sys_state; -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -namespace PlatformConfig { - -class Configurator { - private: - static const int MaxDelay; - static const int LockMaxWait; - - EXT_RAM_ATTR static TimerHandle_t _timer; - EXT_RAM_ATTR static SemaphoreHandle_t _mutex; - EXT_RAM_ATTR static SemaphoreHandle_t _state_mutex; - EXT_RAM_ATTR static EventGroupHandle_t _group; - bool SetGroupBit(int bit_num, bool flag); - void ResetModified(); - void ResetStateModified(); - sys_Config _root; - sys_State _sys_state; - - public: - sys_Config* Root() { return &_root; } - sys_State* RootState() { return &_sys_state; } - bool WaitForCommit(); - bool Lock(); - bool LockState(); - void Unlock(); - void UnlockState(); - - void* AllocGetConfigBuffer(size_t* sz); - static void* AllocGetConfigBuffer(size_t* sz, sys_Config* config); - static void ResetStructure(sys_Config* config); - bool LoadDecodeState(); - - void CommitChanges(); - bool Commit(); - static bool Commit(sys_Config* config); - - bool CommitState(); - static bool CommitState(sys_State* state); - sys_Config* AllocDefaultStruct(); - - static bool ApplyTargetSettings(sys_Config* conf_root); - bool ApplyTargetSettings(); - bool HasStateChanges(); - - bool LoadDecodeBuffer(void* buffer, size_t buffer_size); - void InitLoadConfig(const char* filename); - void InitLoadConfig(const char* filename, sys_Config* conf_root, bool noinit = false); - static bool LoadDecode( - void* buffer, size_t buffer_size, sys_Config* conf_root, bool noinit = false); - - Configurator() { - _mutex = xSemaphoreCreateMutex(); - _state_mutex = xSemaphoreCreateMutex(); - _group = xEventGroupCreate(); - } - void RaiseStateModified(); - void RaiseModified(); - bool HasChanges(); - ~Configurator() {} -}; -} // namespace PlatformConfig -extern PlatformConfig::Configurator configurator; -#endif diff --git a/components/platform_config/Locking.cpp b/components/platform_config/Locking.cpp new file mode 100644 index 00000000..078574d9 --- /dev/null +++ b/components/platform_config/Locking.cpp @@ -0,0 +1,45 @@ + +#include "Locking.h" +#include "esp_log.h" +#include "tools.h" +static const char* TAG = "Locking"; + +using namespace System; + +const int Locking::MaxDelay = 1000; +const int Locking::LockMaxWait = 20 * Locking::MaxDelay; + +// C++ methods +Locking* Locking::Create(std::string name) { return new Locking(name); } + +void Locking::Destroy(Locking* lock) { delete lock; } + +LockingHandle* Locking_Create(const char* name) { + return reinterpret_cast(Locking::Create(std::string(name))); +} + +void Locking_Destroy(LockingHandle* lock) { Locking::Destroy(reinterpret_cast(lock)); } + +bool Locking_Lock(LockingHandle* lock, TickType_t maxWait_ms) { + return reinterpret_cast(lock)->Lock(maxWait_ms); +} + +void Locking_Unlock(LockingHandle* lock) { reinterpret_cast(lock)->Unlock(); } + +bool Locking_IsLocked(LockingHandle* lock) { return reinterpret_cast(lock)->IsLocked(); } + +bool Locking::Lock(TickType_t maxWait_ms) { + assert(_mutex != nullptr); + ESP_LOGV(TAG, "Locking %s", _name.c_str()); + if (xSemaphoreTakeRecursive(_mutex, pdMS_TO_TICKS(maxWait_ms)) == pdTRUE) { + ESP_LOGV(TAG, "locked %s", _name.c_str()); + return true; + } else { + ESP_LOGE(TAG, "Unable to lock %s", _name.c_str()); + return false; + } +} +void Locking::Unlock() { + ESP_LOGV(TAG, "Unlocking %s", _name.c_str()); + xSemaphoreGiveRecursive(_mutex); +} diff --git a/components/platform_config/Locking.h b/components/platform_config/Locking.h new file mode 100644 index 00000000..5be78646 --- /dev/null +++ b/components/platform_config/Locking.h @@ -0,0 +1,71 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + +#pragma once +#include "esp_attr.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct LockingHandle LockingHandle; + +#ifdef __cplusplus +} // extern "C" + +#include +namespace System { +class Locking { + private: + SemaphoreHandle_t _mutex; + static const int MaxDelay; + static const int LockMaxWait; + std::string _name; + + public: + Locking(std::string name) : _mutex(xSemaphoreCreateRecursiveMutex()), _name(name) {} + bool Lock(TickType_t maxWait_ms = LockMaxWait); + void Unlock(); + bool IsLocked() { return xSemaphoreGetMutexHolder(_mutex) != nullptr; } + ~Locking() { vSemaphoreDelete(_mutex); } + static Locking* Create(std::string name); + static void Destroy(Locking* lock); +}; + +} // namespace PlatformConfig + +extern "C" { +#endif + +LockingHandle* Locking_Create(const char* name); +void Locking_Destroy(LockingHandle* lock); +bool Locking_Lock(LockingHandle* lock, TickType_t maxWait_ms); +void Locking_Unlock(LockingHandle* lock); +bool Locking_IsLocked(LockingHandle* lock); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/platform_config/PBW.cpp b/components/platform_config/PBW.cpp new file mode 100644 index 00000000..f31e45dd --- /dev/null +++ b/components/platform_config/PBW.cpp @@ -0,0 +1,272 @@ +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "Locking.h" +#include "cpp_tools.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" + +#include "PBW.h" +#include "accessors.h" +#include "esp_log.h" +#include "network_manager.h" +#include "pb.h" +#include "pb_decode.h" // Nanopb header for decoding (deserialization) +#include "pb_encode.h" // Nanopb header for encoding (serialization) +#include "tools.h" +#include +#include +#include + +namespace System { +const char* PBHelper::PROTOTAG = "PB"; + +void PBHelper::ResetModified() { + ESP_LOGD(PROTOTAG, "Resetting the global commit flag for %s.", name.c_str()); + SetGroupBit(Flags::COMMITTED, true); +} + +bool PBHelper::SetGroupBit(Flags flags, bool flag) { + bool result = true; + int bit_num = static_cast(flags); + int curFlags = xEventGroupGetBits(_group); + if ((curFlags & static_cast(Flags::LOAD)) && flags == Flags::COMMITTED) { + ESP_LOGD(PROTOTAG, "Loading %s, ignoring changes", name.c_str()); + result = false; + } + if (result) { + if ((curFlags & bit_num) == flag) { + ESP_LOGV(PROTOTAG, "Flag %d already %s", bit_num, flag ? "Set" : "Cleared"); + result = false; + } + } + if (result) { + ESP_LOGV(PROTOTAG, "%s Flag %d ", flag ? "Setting" : "Clearing", bit_num); + if (!flag) { + xEventGroupClearBits(_group, bit_num); + } else { + xEventGroupSetBits(_group, bit_num); + } + } + return result; +} + +void PBHelper::SyncCommit(void* protoWrapper) { + IPBBase* protoWrapperBase = reinterpret_cast(protoWrapper); + if (protoWrapperBase) { + protoWrapperBase->CommitChanges(); + } +} +std::vector PBHelper::EncodeData( + const pb_msgdesc_t* fields, const void* src_struct) { + size_t datasz; + ESP_LOGV(PROTOTAG, "EncodeData: getting size"); + if (!pb_get_encoded_size(&datasz, fields, src_struct)) { + throw std::runtime_error("Failed to get encoded size."); + } + ESP_LOGV(PROTOTAG, "EncodeData: size: %d. Encoding", datasz); + std::vector data(datasz); + pb_ostream_t stream = pb_ostream_from_buffer(data.data(), datasz); + if (!pb_encode(&stream, fields, src_struct)) { + throw std::runtime_error("Failed to encode data."); + } + ESP_LOGV(PROTOTAG, "EncodeData: Done"); + return data; +} + +void PBHelper::DecodeData( + std::vector data, const pb_msgdesc_t* fields, void* target, bool noinit) { + pb_istream_t stream = pb_istream_from_buffer((uint8_t*)data.data(), data.size()); + bool result = false; + + // Decode the Protocol Buffers message + if (noinit) { + ESP_LOGD(PROTOTAG, "Decoding WITHOUT initialization"); + result = pb_decode_noinit(&stream, fields, data.data()); + } else { + ESP_LOGD(PROTOTAG, "Decoding WITH initialization"); + result = pb_decode(&stream, fields, target); + } + if (!result) { + throw std::runtime_error( + std::string("Failed to decode settings: %s", PB_GET_ERROR(&stream))); + } + ESP_LOGD(PROTOTAG, "Data decoded"); +} +void PBHelper::CommitFile( + const std::string& filename, const pb_msgdesc_t* fields, const void* src_struct) { + size_t datasz = 0; + ESP_LOGD(PROTOTAG, "Committing data to file File %s", filename.c_str()); + + + if (!pb_get_encoded_size(&datasz, fields, src_struct)) { + throw std::runtime_error("Failed to get encoded size."); + } + + if (datasz == 0) { + ESP_LOGW(PROTOTAG, "File %s not written. Data size is zero", filename.c_str()); + return; + } + + ESP_LOGD(PROTOTAG, "Committing to file %s", filename.c_str()); + if (!src_struct) { + throw std::runtime_error("Null pointer received."); + } + FILE* file = fopen(filename.c_str(), "wb"); + if (file == nullptr) { + throw std::runtime_error(std::string("Error opening file ") + filename.c_str()); + } + pb_ostream_t filestream = PB_OSTREAM_SIZING; + filestream.callback = &out_file_binding; + filestream.state = file; + filestream.max_size = SIZE_MAX; + ESP_LOGD(PROTOTAG, "Starting file encode for %s", filename.c_str()); + if (!pb_encode(&filestream, fields, (void*)src_struct)) { + fclose(file); + throw std::runtime_error("Encoding file failed"); + } + ESP_LOGD(PROTOTAG, "Encoded size: %d", filestream.bytes_written); + if (filestream.bytes_written == 0) { + ESP_LOGW(PROTOTAG, "Empty structure for file %s", filename.c_str()); + } + fclose(file); +} + +bool PBHelper::IsDataDifferent( + const pb_msgdesc_t* fields, const void* src_struct, const void* other_struct) { + bool changed = false; + try { + ESP_LOGV(PROTOTAG, "Encoding Source data"); + auto src_data = EncodeData(fields, src_struct); + ESP_LOGV(PROTOTAG, "Encoding Compared data"); + auto other_data = EncodeData(fields, other_struct); + if (src_data.size() != other_data.size()) { + ESP_LOGD(PROTOTAG, "IsDataDifferent: source and target size different: [%d!=%d]", + src_data.size(), other_data.size()); + changed = true; + } else if (src_data != other_data) { + ESP_LOGD(PROTOTAG, "IsDataDifferent: source and target not the same"); + changed = true; + } + if (changed && esp_log_level_get(PROTOTAG) >= ESP_LOG_DEBUG) { + ESP_LOGD(PROTOTAG, "Source data: "); + dump_data((const uint8_t*)src_data.data(), src_data.size()); + ESP_LOGD(PROTOTAG, "Compared data: "); + dump_data((const uint8_t*)other_data.data(), src_data.size()); + } + } catch (const std::runtime_error& e) { + throw std::runtime_error(std::string("Comparison failed: ") + e.what()); + } + ESP_LOGD(PROTOTAG, "IsDataDifferent: %s", changed ? "TRUE" : "FALSE"); + return changed; +} + +void PBHelper::CopyStructure( + const void* src_data, const pb_msgdesc_t* fields, void* target_data) { + try { + auto src = EncodeData(fields, src_data); + ESP_LOGD(PROTOTAG, "Encoded structure to copy has %d bytes", src.size()); + DecodeData(src, fields, target_data, false); + } catch (const std::runtime_error& e) { + throw std::runtime_error(std::string("Copy failed: ") + e.what()); + } +} +void PBHelper::LoadFile( + const std::string& filename, const pb_msgdesc_t* fields, void* target_data, bool noinit) { + struct stat fileInformation; + if (!get_file_info(&fileInformation, filename.c_str()) || fileInformation.st_size == 0) { + throw FileNotFoundException("filename"); + } + + FILE* file = fopen(filename.c_str(), "rb"); + ESP_LOGI(PROTOTAG, "Loading file %s", filename.c_str()); + if (file == nullptr) { + int errNum = errno; + ESP_LOGE( + PROTOTAG, "Unable to open file: %s. Error: %s", filename.c_str(), strerror(errNum)); + throw std::runtime_error( + "Unable to open file: " + filename + ". Error: " + strerror(errNum)); + } + pb_istream_t filestream = PB_ISTREAM_EMPTY; + filestream.callback = &in_file_binding; + filestream.state = file; + filestream.bytes_left = fileInformation.st_size; + + ESP_LOGV(PROTOTAG, "Starting decode."); + bool result = false; + if (noinit) { + ESP_LOGV(PROTOTAG, "Decoding WITHOUT initialization"); + result = pb_decode_noinit(&filestream, fields, target_data); + } else { + ESP_LOGV(PROTOTAG, "Decoding WITH initialization"); + result = pb_decode(&filestream, fields, target_data); + } + fclose(file); + if (!result) { + throw System::DecodeError(PB_GET_ERROR(&filestream)); + } + ESP_LOGV(PROTOTAG, "Decode done."); +} + +bool PBHelper::FileExists(std::string filename) { + struct stat fileInformation; + ESP_LOGD(PROTOTAG, "Checking if file %s exists", filename.c_str()); + return get_file_info(&fileInformation, filename.c_str()) && fileInformation.st_size > 0; +} +bool PBHelper::FileExists() { return FileExists(filename); } +bool PBHelper::IsLoading() { return xEventGroupGetBits(_group) & static_cast(Flags::LOAD); } +void PBHelper::SetLoading(bool active) { SetGroupBit(Flags::LOAD, active); } + +bool PBHelper::WaitForCommit(uint8_t retries=2) { + auto remain= retries; + auto bits = xEventGroupGetBits(_group); + bool commit_pending = HasChanges(); + ESP_LOGD(PROTOTAG, "Entering WaitForCommit bits: %d, changes? %s", bits, + commit_pending ? "YES" : "NO"); + while (commit_pending && remain-->0) { + ESP_LOGD(PROTOTAG, "Waiting for config commit ..."); + auto bits = xEventGroupWaitBits( + _group, static_cast(Flags::COMMITTED), pdFALSE, pdTRUE, (MaxDelay * 2) / portTICK_PERIOD_MS); + commit_pending = !(bits & static_cast(Flags::COMMITTED)); + ESP_LOGD( + PROTOTAG, "WaitForCommit bits: %d, changes? %s", bits, commit_pending ? "YES" : "NO"); + if (commit_pending) { + ESP_LOGW(PROTOTAG, "Timeout waiting for config commit for [%s]", name.c_str()); + } else { + ESP_LOGI(PROTOTAG, "Changes to %s committed", name.c_str()); + } + } + return !commit_pending; +} + +void PBHelper::RaiseChangedAsync() { + if(_no_save){ + ESP_LOGD(PROTOTAG,"Ignoring changes for %s, as it is marked not to be saved", name.c_str()); + } + ESP_LOGI(PROTOTAG, "Changes made to %s", name.c_str()); + if (IsLoading()) { + ESP_LOGD(PROTOTAG, "Ignoring raise modified during load of %s", name.c_str()); + } else { + SetGroupBit(Flags::COMMITTED, false); + network_async_commit_protowrapper( + static_cast(static_cast(this))); + } +} +const std::string& PBHelper::GetFileName() { return filename; } +bool PBHelper::HasChanges() { return !(xEventGroupGetBits(_group) & static_cast(Flags::COMMITTED)); } +} // namespace PlatformConfig + +bool proto_load_file( + const char* filename, const pb_msgdesc_t* fields, void* target_data, bool noinit = false) { + try { + ESP_LOGI(System::PBHelper::PROTOTAG,"Loading file %s",filename); + System::PBHelper::LoadFile(std::string(filename), fields, target_data, noinit); + } catch (const std::exception& e) { + if(!noinit){ + // initialize the structure + pb_istream_t stream = pb_istream_from_buffer(nullptr, 0); + pb_decode(&stream, fields, target_data); + } + ESP_LOGE(System::PBHelper::PROTOTAG, "Error loading file %s: %s", filename, e.what()); + return false; + } + return true; +} diff --git a/components/platform_config/PBW.h b/components/platform_config/PBW.h new file mode 100644 index 00000000..7de4f268 --- /dev/null +++ b/components/platform_config/PBW.h @@ -0,0 +1,331 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ +#pragma once +#ifndef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif + +#include "Locking.h" +#include "MessageDefinition.pb.h" +#include "accessors.h" +#include "configuration.pb.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "network_manager.h" +#include "pb.h" +#include "pb_decode.h" // Nanopb header for decoding (deserialization) +#include "pb_encode.h" // Nanopb header for encoding (serialization) +#include "tools.h" +#include "tools_spiffs_utils.h" +#include "bootstate.h" +#include "State.pb.h" + +#ifdef __cplusplus +// #include +#include +#include + +namespace System { +template struct has_target_implementation : std::false_type {}; + +class FileNotFoundException : public std::runtime_error { + public: + explicit FileNotFoundException(const std::string& message) : std::runtime_error(message) {} +}; +class DecodeError : public std::runtime_error { + public: + explicit DecodeError(const std::string& message) : std::runtime_error(message) {} +}; +class IPBBase { + public: + virtual void CommitChanges() = 0; + virtual ~IPBBase() {} +}; +class PBHelper : public IPBBase { + + protected: + const pb_msgdesc_t* _fields; + EventGroupHandle_t _group; + std::string name; + std::string filename; + static const int MaxDelay = 1000; + Locking _lock; + size_t _datasize; + bool _no_save; + + public: + enum class Flags { COMMITTED = BIT0, LOAD = BIT1 }; + bool SetGroupBit(Flags flags, bool flag); + static const char* PROTOTAG; + std::string& GetName() { return name; } + const char* GetCName() { return name.c_str(); } + static std::string GetDefFileName(std::string name){ + return std::string(spiffs_base_path) + "/data/def_" + name + ".bin"; + } + std::string GetDefFileName(){ + return GetDefFileName(this->name); + } + size_t GetDataSize(){ + return _datasize; + } + PBHelper(std::string name, const pb_msgdesc_t* fields, size_t defn_size, size_t datasize, bool no_save = false) + : _fields(fields), _group(xEventGroupCreate()), name(std::move(name)), _lock(this->name),_datasize(datasize), _no_save(no_save) { + sys_message_def definition = sys_message_def_init_default; + bool savedef = false; + ESP_LOGD(PROTOTAG,"Getting definition file name"); + auto deffile = GetDefFileName(); + ESP_LOGD(PROTOTAG,"Instantiating with definition size %d and data size %d", defn_size,datasize); + + try { + PBHelper::LoadFile(deffile, &sys_message_def_msg, static_cast(&definition)); + if (definition.data->size != defn_size || definition.datasize != _datasize) { + ESP_LOGW(PROTOTAG, "Structure definition %s has changed", this->name.c_str()); + if (!is_recovery_running) { + savedef = true; + pb_release(&sys_message_def_msg, &definition); + } else { + ESP_LOGW(PROTOTAG, "Using existing definition for recovery"); + _fields = reinterpret_cast(definition.data->bytes); + _datasize = definition.datasize; + } + } + } catch (const FileNotFoundException& e) { + savedef = true; + } + + if (savedef) { + ESP_LOGW(PROTOTAG, "Saving definition for structure %s", this->name.c_str()); + auto data = (pb_bytes_array_t*)malloc_init_external(sizeof(pb_bytes_array_t)+defn_size); + memcpy(&data->bytes, fields, defn_size); + data->size = defn_size; + definition.data = data; + definition.datasize = _datasize; + ESP_LOGD(PROTOTAG,"Committing structure with %d bytes ",data->size); + PBHelper::CommitFile(deffile, &sys_message_def_msg, &definition); + ESP_LOGD(PROTOTAG,"Releasing memory"); + free(data); + } + } + void ResetModified(); + static void SyncCommit(void* protoWrapper); + static void CommitFile(const std::string& filename, const pb_msgdesc_t* fields, const void* src_struct); + static bool IsDataDifferent(const pb_msgdesc_t* fields, const void* src_struct, const void* other_struct); + + static void CopyStructure(const void* src_data, const pb_msgdesc_t* fields, void* target_data); + static void LoadFile(const std::string& filename, const pb_msgdesc_t* fields, void* target_data, bool noinit = false); + static std::vector EncodeData(const pb_msgdesc_t* fields, const void* src_struct); + static void DecodeData(std::vector data, const pb_msgdesc_t* fields, void* target, bool noinit = false); + bool FileExists(std::string filename); + bool FileExists(); + bool IsLoading(); + void SetLoading(bool active); + bool WaitForCommit(uint8_t retries ); + void RaiseChangedAsync(); + const std::string& GetFileName(); + bool HasChanges(); +}; +template class PB : public PBHelper { + private: + T *_root; + + // Generic _setTarget implementation + void _setTarget(std::string target, std::false_type) { ESP_LOGE(PROTOTAG, "Setting target not implemented for %s", name.c_str()); } + + // Special handling for sys_config + void _setTarget(std::string target, std::true_type) { + if (_root->target) { + free(_root->target); + } + _root->target = strdup_psram(target.c_str()); + } + std::string _getTargetName(std::false_type) { return ""; } + std::string _getTargetName(std::true_type) { return STR_OR_BLANK(_root->target); } + + public: + // Accessor for the underlying structure + T& Root() { return *_root; } + // Const accessor for the underlying structure + + const T& Root() const { return *_root; } + T* get() { return _root; } + const T* get() const { return (const T*)_root; } + + // Constructor + explicit PB(std::string name, const pb_msgdesc_t* fields, size_t defn_size, bool no_save = false) : + PBHelper(std::move(name), fields,defn_size, sizeof(T), no_save) { + ESP_LOGD(PROTOTAG, "Instantiating PB class for %s with data size %d", this->name.c_str(), sizeof(T)); + ResetModified(); + filename = std::string(spiffs_base_path) + "/data/" + this->name + ".bin"; + _root = (T*)(malloc_init_external(_datasize)); + memset(_root, 0x00, sizeof(_datasize)); + } + + std::string GetTargetName() { return _getTargetName(has_target_implementation{}); } + void SetTarget(std::string targetname, bool skip_commit = false) { + std::string newtarget = trim(targetname); + std::string currenttarget = trim(GetTargetName()); + ESP_LOGD(PROTOTAG, "SetTarget called with %s", newtarget.c_str()); + if (newtarget == currenttarget && !newtarget.empty()) { + ESP_LOGD(PROTOTAG, "Target name %s not changed for %s", currenttarget.c_str(), name.c_str()); + } else if (newtarget.empty() && !currenttarget.empty()) { + ESP_LOGW(PROTOTAG, "Target name %s was removed for %s ", currenttarget.c_str(), name.c_str()); + } + ESP_LOGI(PROTOTAG, "Setting target %s for %s", newtarget.c_str(), name.c_str()); + _setTarget(newtarget, has_target_implementation{}); + if (!skip_commit) { + ESP_LOGD(PROTOTAG, "Raising changed flag to commit new target name."); + RaiseChangedAsync(); + } else { + SetGroupBit(Flags::COMMITTED, false); + } + } + std::string GetTargetFileName() { + if (GetTargetName().empty()) { + return ""; + } + auto target_name = GetTargetName(); + return std::string(spiffs_base_path) + "/targets/" + toLowerStr(target_name) + "/" + name + ".bin"; + } + void Reinitialize(bool skip_target = false, bool commit = false, std::string target_name = "") { + ESP_LOGW(PROTOTAG, "Initializing %s", name.c_str()); + pb_istream_t stream = PB_ISTREAM_EMPTY; + // initialize blank structure by + // decoding a dummy stream + pb_decode(&stream, _fields, _root); + SetLoading(true); + try { + std::string fullpath = std::string(spiffs_base_path) + "/defaults/" + this->name + ".bin"; + ESP_LOGD(PROTOTAG, "Attempting to load defaults file for %s", fullpath.c_str()); + PBHelper::LoadFile(fullpath.c_str(), _fields, static_cast(_root), true); + } catch (FileNotFoundException&) { + ESP_LOGW(PROTOTAG, "No defaults found for %s", name.c_str()); + } catch (std::runtime_error& e) { + ESP_LOGE(PROTOTAG, "Error loading Target %s overrides file: %s", GetTargetName().c_str(), e.what()); + } + SetLoading(false); + if (!skip_target) { + if (!target_name.empty()) { + SetTarget(target_name, true); + } + LoadTargetValues(); + } + if (commit) { + CommitChanges(); + } + } + void LoadFile(bool skip_target = false, bool noinit = false) { + SetLoading(true); + PBHelper::LoadFile(filename, _fields, static_cast(_root), noinit); + SetLoading(false); + if (!skip_target) { + LoadTargetValues(); + } + } + void LoadTargetValues() { + ESP_LOGD(PROTOTAG, "Loading target %s values for %s", GetTargetName().c_str(), name.c_str()); + if (GetTargetFileName().empty()) { + ESP_LOGD(PROTOTAG, "No target file to load for %s", name.c_str()); + return; + } + try { + // T old; + // CopyTo(old); + ESP_LOGI(PROTOTAG, "Loading target %s values for %s", GetTargetName().c_str(), name.c_str()); + PBHelper::LoadFile(GetTargetFileName(), _fields, static_cast(_root), true); + // don't commit the values here, as it doesn't work well with + // repeated values + // if (*this != old) { + // ESP_LOGI(PROTOTAG, "Changes detected from target values."); + // RaiseChangedAsync(); + // } + SetGroupBit(Flags::COMMITTED, false); + + } catch (FileNotFoundException&) { + ESP_LOGD(PROTOTAG, "Target %s overrides file not found for %s", GetTargetName().c_str(), name.c_str()); + } catch (std::runtime_error& e) { + ESP_LOGE(PROTOTAG, "Error loading Target %s overrides file: %s", GetTargetName().c_str(), e.what()); + } + } + void CommitChanges() override { + ESP_LOGI(PROTOTAG, "Committing %s to flash.", name.c_str()); + if (!_lock.Lock()) { + ESP_LOGE(PROTOTAG, "Unable to lock config for commit "); + return; + } + ESP_LOGV(PROTOTAG, "Config Locked. Committing"); + try { + CommitFile(filename, _fields, _root); + } catch (...) { + } + ResetModified(); + _lock.Unlock(); + ESP_LOGI(PROTOTAG, "Done committing %s to flash.", name.c_str()); + } + bool Lock() { return _lock.Lock(); } + void Unlock() { return _lock.Unlock(); } + std::vector Encode() { + auto data = std::vector(); + if (!_lock.Lock()) { + throw std::runtime_error("Unable to lock object"); + } + data = EncodeData(_fields, this->_root); + _lock.Unlock(); + return data; + } + + void CopyTo(T& target_data) { + if (!_lock.Lock()) { + ESP_LOGE(PROTOTAG, "Lock failed for %s", name.c_str()); + throw std::runtime_error("Lock failed "); + } + CopyStructure(_root, _fields, &target_data); + _lock.Unlock(); + } + void CopyFrom(const T& source_data) { + if (!_lock.Lock()) { + ESP_LOGE(PROTOTAG, "Lock failed for %s", name.c_str()); + throw std::runtime_error("Lock failed "); + } + CopyStructure(&source_data, _fields, _root); + _lock.Unlock(); + } + + bool operator!=(const T& other) const { return IsDataDifferent(_fields, _root, &other); } + bool operator==(const T& other) const { return !IsDataDifferent(_fields, _root, &other); } + void DecodeData(const std::vector data, bool noinit = false) { PBHelper::DecodeData(data, _fields, (void*)_root, noinit); } + + ~PB() { vEventGroupDelete(_group); }; +}; +template <> struct has_target_implementation : std::true_type {}; + +template <> struct has_target_implementation : std::true_type {}; + +} // namespace PlatformConfig +extern "C" { +#endif +bool proto_load_file(const char* filename, const pb_msgdesc_t* fields, void* target_data, bool noinit); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/platform_config/WifiList.cpp b/components/platform_config/WifiList.cpp new file mode 100644 index 00000000..fd9edfdb --- /dev/null +++ b/components/platform_config/WifiList.cpp @@ -0,0 +1,845 @@ +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "WifiList.h" +#include "Config.h" +#include "esp_check.h" +#include "esp_log.h" +#include "esp_system.h" +#include + +static const char* TAG_CRED_MANAGER = "credentials_manager"; +bool sys_status_wifi_callback(pb_istream_t* istream, pb_ostream_t* ostream, const pb_field_iter_t* field) { + return sys_net_config_callback(istream, ostream, field); +} +bool sys_net_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const pb_field_iter_t* field) { + WifiList** managerPtr = static_cast(field->pData); + WifiList* manager = *managerPtr; + + if (istream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { + if (manager == nullptr) { + ESP_LOGE(TAG_CRED_MANAGER, "Invalid pointer to wifi list manager"); + return false; + } + ESP_LOGV(TAG_CRED_MANAGER, "Decoding credentials"); + sys_net_wifi_entry entry = sys_net_wifi_entry_init_default; + if (!pb_decode(istream, &sys_net_wifi_entry_msg, &entry)) return false; + printf("\nFound ssid %s, password %s\n", entry.ssid, entry.password); + try { + manager->AddUpdate(entry); // Add to the manager + } catch (const std::exception& e) { + ESP_LOGE(TAG_CRED_MANAGER, "decode exception: %s", e.what()); + return false; + } + ESP_LOGV(TAG_CRED_MANAGER, "Credentials decoding completed"); + } else if (ostream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { + if (manager == nullptr) { + ESP_LOGV(TAG_CRED_MANAGER, "No wifi entries manager instance. nothing to encode"); + return true; + } + ESP_LOGV(TAG_CRED_MANAGER, "Encoding %d access points", manager->GetCount()); + + for (int i = 0; i < manager->GetCount(); i++) { + ESP_LOGV(TAG_CRED_MANAGER, "Encoding credential #%d: SSID: %s, PASS: %s", i, manager->GetIndex(i)->ssid, manager->GetIndex(i)->password); + if (!pb_encode_tag_for_field(ostream, field)) { + return false; + } + if (!pb_encode_submessage(ostream, &sys_net_wifi_entry_msg, manager->GetIndex(i))) { + return false; + } + } + ESP_LOGV(TAG_CRED_MANAGER, "Credentials encoding completed"); + } + + return true; +} +std::string WifiList::GetBSSID(const wifi_event_sta_connected_t* evt) { + char buffer[18]={}; + FormatBSSID(buffer, sizeof(buffer), evt->bssid); + ESP_LOGD(TAG_CRED_MANAGER, "Formatted BSSID: %s", buffer); + return std::string(buffer); +} +bool WifiList::OffsetTimeStamp(google_protobuf_Timestamp* ts) { + timeval tts; + google_protobuf_Timestamp gts; + gettimeofday((struct timeval*)&tts, NULL); + gts.nanos = tts.tv_usec * 1000; + gts.seconds = tts.tv_sec; + if (tts.tv_sec < 1704143717) { + ESP_LOGE(TAG_CRED_MANAGER, "Error updating time stamp. Clock doesn't seem right"); + return false; + } + if (ts && ts->seconds < 1704143717) { + ESP_LOGV(TAG_CRED_MANAGER, "Updating time stamp based on new clock value"); + ts->seconds = gts.seconds - ts->seconds; + ts->nanos = gts.nanos - ts->nanos; + return true; + } + ESP_LOGD(TAG_CRED_MANAGER, "Time stamp already updated. Skipping"); + return false; +} +bool WifiList::UpdateTimeStamp(google_protobuf_Timestamp* ts, bool& has_flag_val) { + ESP_RETURN_ON_FALSE(ts != nullptr, false, TAG_CRED_MANAGER, "Null pointer!"); + bool changed = false; + timeval tts; + google_protobuf_Timestamp gts; + gettimeofday((struct timeval*)&tts, NULL); + gts.nanos = tts.tv_usec * 1000; + gts.seconds = tts.tv_sec; + if (!has_flag_val || gts.nanos != ts->nanos || gts.seconds != ts->seconds) { + ts->seconds = gts.seconds; + ts->nanos = gts.nanos; + has_flag_val = true; + changed = true; + } + return changed; +} + +bool WifiList::isEmpty(const char* str, size_t len) { + for (size_t i = 0; i < len; ++i) { + if (str[i] != '\0') { + return false; + } + } + return true; +} + +bool WifiList::Update(const wifi_ap_record_t* ap, bool connected) { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + auto existing = Get(ap); + if (!existing) { + return false; + } + auto updated = ToSTAEntry(ap); + updated.connected = connected; + bool changed = Update(*existing, updated); + Release(&updated); + Unlock(); + return changed; +} +bool WifiList::Update(sys_net_wifi_entry& existingEntry, sys_net_wifi_entry& updated) { + + // Check if any relevant fields have changed + bool hasChanged = false; + if (!isEmpty(updated.ssid, sizeof(updated.ssid)) && memcmp(existingEntry.ssid, updated.ssid, sizeof(existingEntry.ssid)) != 0) { + memcpy(existingEntry.ssid, updated.ssid, sizeof(existingEntry.ssid)); + hasChanged = true; + } + + // Check and copy BSSID if the compared BSSID is not empty + if (!isEmpty(updated.bssid, sizeof(updated.bssid)) && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && + memcmp(existingEntry.bssid, updated.bssid, sizeof(existingEntry.bssid)) != 0) { + memcpy(existingEntry.bssid, updated.bssid, sizeof(existingEntry.bssid)); + hasChanged = true; + } + + // Check and copy password if the compared password is not empty + if (!isEmpty(updated.password, sizeof(updated.password)) && + memcmp(existingEntry.password, updated.password, sizeof(existingEntry.password)) != 0) { + memcpy(existingEntry.password, updated.password, sizeof(existingEntry.password)); + hasChanged = true; + } + + if (existingEntry.channel != updated.channel && updated.channel > 0) { + existingEntry.channel = updated.channel; + hasChanged = true; + } + + if (existingEntry.auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { + existingEntry.auth_type = updated.auth_type; + hasChanged = true; + } + + if (areRadioTypesDifferent(existingEntry.radio_type, existingEntry.radio_type_count, updated.radio_type, updated.radio_type_count) && + updated.radio_type_count > 0 && updated.radio_type[0] != sys_net_radio_types_UNKNOWN) { + + if (existingEntry.radio_type != nullptr) { + // Free the old radio_type array if it exists + delete[] existingEntry.radio_type; + } + // Allocate new memory and copy the updated radio types + existingEntry.radio_type_count = updated.radio_type_count; + existingEntry.radio_type = new sys_net_radio_types[updated.radio_type_count]; + std::copy(updated.radio_type, updated.radio_type + updated.radio_type_count, existingEntry.radio_type); + hasChanged = true; + } + + if (updated.has_last_try) { + if (memcmp(&existingEntry.last_try, &updated.last_try, sizeof(existingEntry.last_try)) != 0) { + memcpy(&existingEntry.last_try, &updated.last_try, sizeof(existingEntry.last_try)); + hasChanged = true; + } + } + if (updated.has_last_seen) { + if (memcmp(&existingEntry.last_seen, &updated.last_seen, sizeof(existingEntry.last_seen)) != 0) { + memcpy(&existingEntry.last_seen, &updated.last_seen, sizeof(existingEntry.last_seen)); + hasChanged = true; + } + } + if (existingEntry.has_last_seen != updated.has_last_seen && updated.has_last_seen) { + existingEntry.has_last_seen = updated.has_last_seen; + hasChanged = true; + } + if (existingEntry.has_last_try != updated.has_last_try && updated.has_last_try) { + existingEntry.has_last_try = updated.has_last_try; + hasChanged = true; + } + + if (existingEntry.connected != updated.connected && updated.connected) { + existingEntry.connected = updated.connected; + hasChanged = true; + } + + if (existingEntry.rssi != updated.rssi && updated.rssi != 0) { + existingEntry.rssi = updated.rssi; + hasChanged = true; + } + + return hasChanged; +} + +std::string WifiList::formatRadioTypes(const sys_net_radio_types* radioTypes, pb_size_t count) { + std::string result; + + for (pb_size_t i = 0; i < count; ++i) { + switch (radioTypes[i]) { + case sys_net_radio_types_PHY_11B: + result += "B"; + break; + case sys_net_radio_types_PHY_11G: + result += "G"; + break; + case sys_net_radio_types_PHY_11N: + result += "N"; + break; + case sys_net_radio_types_LR: + result += "L"; + break; + case sys_net_radio_types_WPS: + result += "W"; + break; + case sys_net_radio_types_FTM_RESPONDER: + result += "FR"; + break; + case sys_net_radio_types_FTM_INITIATOR: + result += "FI"; + break; + case sys_net_radio_types_UNKNOWN: + default: + result += "U"; + break; + } + if (i < count - 1) { + result += ","; + } + } + + return result; +} + +bool WifiList::Update(const wifi_sta_config_t* sta, bool connected) { + if (!sta) { + return false; // Invalid input + } + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + sys_net_wifi_entry* existingEntry = Get(sta); + + // If the entry does not exist, nothing to update + if (!existingEntry) { + Unlock(); + return false; + } + auto updated = ToSTAEntry(sta); + // Check if any relevant fields have changed + bool hasChanged = false; + + if (strlen(updated.ssid) > 0 && memcmp(existingEntry->ssid, updated.ssid, sizeof(existingEntry->ssid)) != 0) { + memcpy(existingEntry->ssid, updated.ssid, sizeof(existingEntry->ssid)); + hasChanged = true; + } + + if (strlen(updated.bssid) > 0 && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && + memcmp(existingEntry->bssid, updated.bssid, sizeof(existingEntry->bssid)) != 0) { + memcpy(existingEntry->bssid, updated.bssid, sizeof(existingEntry->bssid)); + hasChanged = true; + } + + if (existingEntry->channel != updated.channel) { + existingEntry->channel = updated.channel; + hasChanged = true; + } + + if (existingEntry->auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { + existingEntry->auth_type = updated.auth_type; + hasChanged = true; + } + + if (areRadioTypesDifferent(existingEntry->radio_type, existingEntry->radio_type_count, updated.radio_type, updated.radio_type_count) && + updated.radio_type_count > 0 && updated.radio_type[0] != sys_net_radio_types_UNKNOWN) { + // Free the old radio_type array if it exists + delete[] existingEntry->radio_type; + + // Allocate new memory and copy the updated radio types + existingEntry->radio_type_count = updated.radio_type_count; + existingEntry->radio_type = new sys_net_radio_types[updated.radio_type_count]; + std::copy(updated.radio_type, updated.radio_type + updated.radio_type_count, existingEntry->radio_type); + + hasChanged = true; + } + + if (updated.has_last_try) { + if (memcmp(&existingEntry->last_try, &updated.last_try, sizeof(existingEntry->last_try)) != 0) { + memcpy(&existingEntry->last_try, &updated.last_try, sizeof(existingEntry->last_try)); + hasChanged = true; + } + } + + if (updated.has_last_seen) { + if (memcmp(&existingEntry->last_seen, &updated.last_seen, sizeof(existingEntry->last_seen)) != 0) { + memcpy(&existingEntry->last_seen, &updated.last_seen, sizeof(existingEntry->last_seen)); + hasChanged = true; + } + } + if (existingEntry->has_last_try != updated.has_last_try) { + existingEntry->has_last_try = updated.has_last_try; + hasChanged = true; + } + if (existingEntry->has_last_seen != updated.has_last_seen) { + existingEntry->has_last_seen = updated.has_last_seen; + hasChanged = true; + } + if (existingEntry->connected != (connected | updated.connected)) { + existingEntry->connected = connected | updated.connected; + hasChanged = true; + } + + if (strlen(updated.password) == 0 && strlen(existingEntry->password) > 0) { + ESP_LOGW(TAG_CRED_MANAGER, "Updated password is empty, while existing password is %s for %s. Ignoring.", existingEntry->password, + existingEntry->ssid); + } else { + if (memcmp(existingEntry->password, updated.password, sizeof(existingEntry->password)) != 0) { + memcpy(existingEntry->password, updated.password, sizeof(existingEntry->password)); + hasChanged = true; + } + } + + if (existingEntry->rssi != updated.rssi && updated.rssi != 0) { + existingEntry->rssi = updated.rssi; + hasChanged = true; + } + Release(&updated); + Unlock(); + return hasChanged; +} +sys_net_wifi_entry WifiList::ToSTAEntry(const sys_net_wifi_entry* sta) { + if (!sta) { + throw std::runtime_error("Null STA entry provided"); + } + sys_net_wifi_entry result = *sta; + if (result.radio_type_count > 0) { + std::unique_ptr newRadioTypes(new sys_net_radio_types[result.radio_type_count]); + if (!newRadioTypes) { + throw std::runtime_error("Failed to allocate memory for radio types"); + } + memcpy(newRadioTypes.get(), sta->radio_type, sizeof(sys_net_radio_types) * result.radio_type_count); + result.radio_type = newRadioTypes.release(); + } else { + result.radio_type = nullptr; + } + + ESP_LOGD(TAG_CRED_MANAGER, "ToSTAEntry: SSID: %s, PASS: %s", result.ssid, result.password); + return result; +} +sys_net_wifi_entry WifiList::ToSTAEntry(const wifi_sta_config_t* sta, sys_net_auth_types auth_type) { + return ToSTAEntry(sta, GetRadioTypes(nullptr), auth_type); +} +sys_net_wifi_entry WifiList::ToSTAEntry( + const wifi_sta_config_t* sta, const std::list& radio_types, sys_net_auth_types auth_type) { + sys_net_wifi_entry item = sys_net_wifi_entry_init_default; + ESP_LOGD(TAG_CRED_MANAGER,"%s (sta_config)","toSTAEntry"); + auto result = ToSTAEntry(sta, item, radio_types); + ESP_LOGV(TAG_CRED_MANAGER, "ToSTAEntry: SSID: %s, PASS: %s", result.ssid, result.password); + return result; +} +sys_net_wifi_entry& WifiList::ToSTAEntry(const wifi_ap_record_t* ap, sys_net_wifi_entry& item) { + if (ap) { + auto radioTypes = GetRadioTypes(ap); + item.radio_type_count=radioTypes.size(); + item.radio_type = new sys_net_radio_types[item.radio_type_count]; + int i = 0; + for (const auto& type : radioTypes) { + item.radio_type[i++] = type; + } + item.auth_type = GetAuthType(ap); + FormatBSSID(ap, item); + item.channel = ap->primary; + item.rssi = ap->rssi; + strncpy(item.ssid, GetSSID(ap).c_str(), sizeof(item.ssid)); + } + return item; +} +sys_net_wifi_entry WifiList::ToSTAEntry(const wifi_ap_record_t* ap) { + sys_net_wifi_entry item = sys_net_wifi_entry_init_default; + return ToSTAEntry(ap, item); +} +sys_net_wifi_entry& WifiList::ToSTAEntry( + const wifi_sta_config_t* sta, sys_net_wifi_entry& item, const std::list& radio_types, sys_net_auth_types auth_type) { + if (!sta) { + ESP_LOGE(TAG_CRED_MANAGER, "Invalid access point entry"); + return item; + } + + std::string ssid = GetSSID(sta); // Convert SSID to std::string + std::string password = GetPassword(sta); // Convert password to std::string + + if (ssid.empty()) { + ESP_LOGE(TAG_CRED_MANAGER, "Invalid access point ssid"); + return item; + } + memset(item.ssid, 0x00, sizeof(item.ssid)); + memset(item.password, 0x00, sizeof(item.password)); + strncpy(item.ssid, ssid.c_str(), sizeof(item.ssid)); // Copy SSID + strncpy(item.password, password.c_str(), sizeof(item.password)); // Copy password + if (LOG_LOCAL_LEVEL > ESP_LOG_DEBUG) { + WifiList::FormatBSSID(item.bssid, sizeof(item.bssid), sta->bssid); // Format BSSID + } + item.channel = sta->channel; + + item.auth_type = auth_type; + + // Handle the radio_type array + if (item.radio_type != nullptr) { + delete[] item.radio_type; // Free existing array if any + item.radio_type_count = 0; + } + item.radio_type_count = radio_types.size(); + item.radio_type = new sys_net_radio_types[item.radio_type_count]; + int i = 0; + for (const auto& type : radio_types) { + item.radio_type[i++] = type; + } + + ESP_LOGV(TAG_CRED_MANAGER, "ToSTAEntry wifi : %s, password: %s", item.ssid, item.password); + return item; +} +bool WifiList::RemoveCredential(const wifi_sta_config_t* sta) { return RemoveCredential(GetSSID(sta)); } +bool WifiList::RemoveCredential(const std::string& ssid) { + auto it = credentials_.find(ssid); + if (it != credentials_.end()) { + // Release any dynamically allocated fields in the structure + Release(&it->second); + // Erase the entry from the map + credentials_.erase(it); + return true; + } + return false; +} + +void WifiList::Clear() { + if (Lock()) { + for (auto& e : credentials_) { + Release( &e.second); + } + credentials_.clear(); + Unlock(); + } +} +bool WifiList::ResetRSSI() { + if (!Lock()) { + ESP_LOGE(TAG_CRED_MANAGER, "Unable to lock structure %s", name_.c_str()); + return false; + } + for (auto& e : credentials_) { + e.second.rssi = 0; + } + Unlock(); + return true; +} +bool WifiList::ResetConnected() { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + for (auto& e : credentials_) { + e.second.connected = false; + } + Unlock(); + return true; +} +sys_net_wifi_entry* WifiList::Get(const std::string& ssid) { + auto it = credentials_.find(ssid); + if (it != credentials_.end()) { + return &(it->second); + } + return nullptr; +} +const sys_net_wifi_entry* WifiList::GetConnected() { + if (!Lock()) { + ESP_LOGE(TAG_CRED_MANAGER, "Unable to lock structure %s", name_.c_str()); + return nullptr; + } + for (auto& e : credentials_) { + if (e.second.connected) { + return &e.second; + } + } + Unlock(); + return nullptr; +} +bool WifiList::SetConnected(const wifi_event_sta_connected_t* evt, bool connected) { + auto ssid = GetSSID(evt); + auto bssid = GetBSSID(evt); + auto existing = Get(ssid); + if (existing) { + if (bssid != existing->bssid || existing->connected != connected || existing->auth_type != GetAuthType(evt->authmode) || + existing->channel != evt->channel) { + ResetConnected(); + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + strncpy(existing->bssid, bssid.c_str(), sizeof(existing->bssid)); + existing->connected = connected; + existing->auth_type = GetAuthType(evt->authmode); + existing->channel = evt->channel; + config_raise_changed(false); + Unlock(); + return true; + } + } else { + ESP_LOGE(TAG_CRED_MANAGER, "Cannot set unknown ssid %s as connected", ssid.c_str()); + } + return false; +} + + + +sys_net_wifi_entry& WifiList::AddUpdate(const wifi_sta_config_t* sta, sys_net_auth_types auth_type) { + return AddUpdate(sta, GetRadioTypes(nullptr), auth_type); +} +sys_net_wifi_entry& WifiList::AddUpdate( + const wifi_sta_config_t* sta, const std::list& radio_types, sys_net_auth_types auth_type) { + auto ssid = GetSSID(sta); + + if (!Exists(sta)) { + auto entry = ToSTAEntry(sta, radio_types, auth_type); + ESP_LOGD(TAG_CRED_MANAGER, "Added new entry %s to list %s", ssid.c_str(), name_.c_str()); + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + credentials_[ssid] = entry; + Unlock(); + } else { + Update(sta); + } + ESP_LOGV(TAG_CRED_MANAGER, "AddUpdate: SSID: %s, PASS: %s", ssid.c_str(), credentials_[ssid].password); + return credentials_[ssid]; +} +bool WifiList::UpdateFromClock() { + bool changed = false; + if (Lock()) { + + for (auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { + bool entrychanged = false; + if (iter->second.has_last_seen) { + entrychanged |= OffsetTimeStamp(&iter->second.last_seen); + } + if (iter->second.has_last_try) { + entrychanged |= OffsetTimeStamp(&iter->second.last_try); + } + if (entrychanged) { + ESP_LOGD(TAG_CRED_MANAGER, "Updated from clock"); + PrintWifiSTAEntry(iter->second); + } + changed |= entrychanged; + } + + Unlock(); + } + return changed; +} +void WifiList::PrintTimeStamp(const google_protobuf_Timestamp* timestamp) { + if (timestamp == NULL) { + printf("Timestamp is NULL\n"); + return; + } + + char buffer[80]; + + // Check for special case of time == 0 + if (timestamp->seconds == 0) { + if (timestamp->nanos != 0) { + printf("nanos not empty!"); + } + snprintf(buffer, sizeof(buffer), "%-26s", "N/A"); + } + // Check for timestamps less than 1704143717 (2024-01-01) + else if (timestamp->seconds > 0 && timestamp->seconds < 1704143717) { + // Convert seconds to time_t for use with localtime + time_t rawtime = (time_t)timestamp->seconds; + struct tm* timeinfo = localtime(&rawtime); + + strftime(buffer, sizeof(buffer), "%H:%M:%S", timeinfo); + } else { + // Convert seconds to time_t for use with localtime + time_t rawtime = (time_t)timestamp->seconds; + struct tm* timeinfo = localtime(&rawtime); + + strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", timeinfo); + } + + printf("%-26s", buffer); +} +bool WifiList::UpdateLastTry(const std::string ssid) { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + auto entry = Get(ssid); + ESP_RETURN_ON_FALSE(entry != nullptr, false, TAG_CRED_MANAGER, "Unknown ssid %s", ssid.c_str()); + ESP_RETURN_ON_FALSE(entry->ssid != nullptr, false, TAG_CRED_MANAGER, "Invalid pointer!"); + bool changed = UpdateLastTry(entry); + Unlock(); + return changed; +} +bool WifiList::UpdateLastTry(sys_net_wifi_entry* entry) { + ESP_RETURN_ON_FALSE(entry != nullptr, false, TAG_CRED_MANAGER, "Invalid pointer!"); + ESP_RETURN_ON_FALSE(entry->ssid != nullptr, false, TAG_CRED_MANAGER, "Invalid pointer!"); + ESP_LOGV(TAG_CRED_MANAGER, "Updating last try for %s", entry->ssid); + return UpdateTimeStamp(&entry->last_try, entry->has_last_try); +} +bool WifiList::UpdateLastTry(const wifi_sta_config_t* sta) { return UpdateLastTry(GetSSID(sta)); } +bool WifiList::UpdateLastTry(const wifi_ap_record_t* ap) { return UpdateLastTry(GetSSID(ap)); } +bool WifiList::UpdateLastSeen(const wifi_sta_config_t* sta) { return UpdateLastSeen(GetSSID(sta)); } +bool WifiList::UpdateLastSeen(const wifi_ap_record_t* ap) { return UpdateLastSeen(GetSSID(ap)); } +bool WifiList::UpdateLastSeen(const std::string ssid) { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + auto entry = Get(ssid); + bool changed = false; + if (entry != nullptr) { + changed = UpdateLastSeen(entry); + } + Unlock(); + return changed; +} +bool WifiList::UpdateLastSeen(sys_net_wifi_entry* entry) { + ESP_RETURN_ON_FALSE(entry != nullptr, false, TAG_CRED_MANAGER, "Invalid pointer!"); + ESP_LOGV(TAG_CRED_MANAGER, "Updating last seen for %s", entry->ssid); + return UpdateTimeStamp(&entry->last_seen, entry->has_last_seen); +} +sys_net_wifi_entry& WifiList::AddUpdate(const wifi_ap_record_t* scan_rec) { + auto ssid = GetSSID(scan_rec); + if (!Exists(scan_rec)) { + ESP_LOGV(TAG_CRED_MANAGER, "Added new entry %s to list %s", ssid.c_str(), name_.c_str()); + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + credentials_[ssid] = ToSTAEntry(scan_rec); + Unlock(); + } else { + Update(scan_rec); + } + return credentials_[ssid]; +} +sys_net_wifi_entry& WifiList::AddUpdate(const char* ssid, const char* password) { + if (ssid == nullptr || password == nullptr) { + throw std::invalid_argument("SSID and password cannot be null"); + } + // Ensure that the SSID and password are not too long + if (std::strlen(ssid) >= sizeof(sys_net_wifi_entry::ssid) || std::strlen(password) >= sizeof(sys_net_wifi_entry::password)) { + throw std::length_error("SSID or password is too long"); + } + if (!Exists(ssid)) { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + sys_net_wifi_entry newEntry = sys_net_wifi_entry_init_default; + // Copy the SSID and password into the new entry, ensuring null termination + std::strncpy(newEntry.ssid, ssid, sizeof(newEntry.ssid) - 1); + newEntry.ssid[sizeof(newEntry.ssid) - 1] = '\0'; + std::strncpy(newEntry.password, password, sizeof(newEntry.password) - 1); + newEntry.password[sizeof(newEntry.password) - 1] = '\0'; + ESP_LOGV(TAG_CRED_MANAGER, "Added new entry %s to list %s", ssid, name_.c_str()); + credentials_[ssid] = newEntry; + Unlock(); + } else { + auto existing = Get(ssid); + if (strncmp(existing->password, password, sizeof(existing->password)) != 0) { + strncpy(existing->password, password, sizeof(existing->password)); + existing->password[sizeof(existing->password) - 1] = '\0'; + } + } + return credentials_[ssid]; +} +sys_net_wifi_entry& WifiList::AddUpdate(const sys_net_wifi_entry* sta, const char* password) { + if (sta == nullptr) { + throw std::invalid_argument("Entry pointer cannot be null"); + } + auto converted = ToSTAEntry(sta); + strncpy(converted.password, password, sizeof(converted.password)); + if (!Exists(sta->ssid)) { + ESP_LOGD(TAG_CRED_MANAGER, "Added new entry %s to list %s", sta->ssid, name_.c_str()); + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + credentials_[sta->ssid] = converted; + Unlock(); + } else { + auto existing = Get(sta->ssid); + Update(*existing, converted); + // release the converted structure now + Release(&converted); + } + return credentials_[sta->ssid]; +} +void WifiList::PrintString(const char* pData, size_t length, const char* format) { + std::string buffer; + for (size_t i = 0; i < length && pData[i]; i++) { + if (isprint((char)pData[i])) { + buffer += (char)pData[i]; // Print as a character + } else { + buffer += '?'; + } + } + printf(format, buffer.c_str()); +} +void WifiList::PrintWifiSTAEntryTitle() { + printf("-----------------------------------------------------------------------------------------------------------------------------------------" + "--------------------\n"); + printf("CONN SSID PASSWORD BSSID RSSI CHAN AUTH RADIO LAST TRY LAST " + "SEEN\n"); + printf("-----------------------------------------------------------------------------------------------------------------------------------------" + "--------------------\n"); +} + +void WifiList::PrintWifiSTAEntry(const sys_net_wifi_entry& entry) { + google_protobuf_Timestamp gts = google_protobuf_Timestamp_init_default; + printf("%-5c", entry.connected ? 'X' : ' '); + printf("%-20s", entry.ssid); + PrintString(entry.password, sizeof(entry.password), "%-25s"); + PrintString(entry.bssid, sizeof(entry.bssid), "%-20s"); + printf("%-4ddB", entry.rssi); + printf("%3u ", static_cast(entry.channel)); + printf("%-14s", sys_net_auth_types_name(entry.auth_type)); + printf("%-9s", formatRadioTypes(entry.radio_type, entry.radio_type_count).c_str()); + if (entry.has_last_try) { + PrintTimeStamp(&entry.last_try); + } else { + PrintTimeStamp(>s); + } + if (entry.has_last_seen) { + PrintTimeStamp(&entry.last_seen); + } else { + PrintTimeStamp(>s); + } + printf("\n"); +} +sys_net_wifi_entry* WifiList::GetIndex(size_t index) { + if (index >= credentials_.size()) { + return nullptr; + } + auto it = credentials_.begin(); + std::advance(it, index); + return &(it->second); +} +sys_net_wifi_entry& WifiList::GetStrongestSTA() { + if (credentials_.empty()) { + throw std::runtime_error("No credentials available"); + } + + auto strongestIter = credentials_.begin(); + for (auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { + if (iter->second.rssi > strongestIter->second.rssi) { + strongestIter = iter; + } + } + + return strongestIter->second; +} + +std::list WifiList::GetRadioTypes(const wifi_ap_record_t* sta) { + std::list result; + if (sta == nullptr) { + result.push_back(sys_net_radio_types_UNKNOWN); + } else { + + // Check each bit field and return the corresponding enum value + if (sta->phy_11b) { + result.push_back(sys_net_radio_types_PHY_11B); + } + if (sta->phy_11g) { + result.push_back(sys_net_radio_types_PHY_11G); + } + if (sta->phy_11n) { + result.push_back(sys_net_radio_types_PHY_11N); + } + if (sta->phy_lr) { + result.push_back(sys_net_radio_types_LR); + } + if (sta->wps) { + result.push_back(sys_net_radio_types_WPS); + } + if (sta->ftm_responder) { + result.push_back(sys_net_radio_types_FTM_RESPONDER); + } + if (sta->ftm_initiator) { + result.push_back(sys_net_radio_types_FTM_INITIATOR); + } + } + return result; +} + +wifi_auth_mode_t WifiList::GetESPAuthMode(sys_net_auth_types auth_type) { + switch (auth_type) { + case sys_net_auth_types_OPEN: + return WIFI_AUTH_OPEN; + case sys_net_auth_types_WEP: + return WIFI_AUTH_WEP; + case sys_net_auth_types_WPA_PSK: + return WIFI_AUTH_WPA_PSK; + case sys_net_auth_types_WPA2_PSK: + return WIFI_AUTH_WPA2_PSK; + case sys_net_auth_types_WPA_WPA2_PSK: + return WIFI_AUTH_WPA_WPA2_PSK; + case sys_net_auth_types_WPA2_ENTERPRISE: + return WIFI_AUTH_WPA2_ENTERPRISE; + case sys_net_auth_types_WPA3_PSK: + return WIFI_AUTH_WPA3_PSK; + case sys_net_auth_types_WPA2_WPA3_PSK: + return WIFI_AUTH_WPA2_WPA3_PSK; + case sys_net_auth_types_WAPI_PSK: + return WIFI_AUTH_WAPI_PSK; + default: + return WIFI_AUTH_OPEN; // Default case + } +} +sys_net_auth_types WifiList::GetAuthType(const wifi_ap_record_t* ap) { + return ap ? GetAuthType(ap->authmode) : sys_net_auth_types_AUTH_UNKNOWN; +} +sys_net_auth_types WifiList::GetAuthType(const wifi_auth_mode_t mode) { + + switch (mode) { + case WIFI_AUTH_OPEN: + return sys_net_auth_types_OPEN; + case WIFI_AUTH_WEP: + return sys_net_auth_types_WEP; + case WIFI_AUTH_WPA_PSK: + return sys_net_auth_types_WPA_PSK; + case WIFI_AUTH_WPA2_PSK: + return sys_net_auth_types_WPA2_PSK; + case WIFI_AUTH_WPA_WPA2_PSK: + return sys_net_auth_types_WPA_WPA2_PSK; + case WIFI_AUTH_WPA2_ENTERPRISE: + return sys_net_auth_types_WPA2_ENTERPRISE; + case WIFI_AUTH_WPA3_PSK: + return sys_net_auth_types_WPA3_PSK; + case WIFI_AUTH_WPA2_WPA3_PSK: + return sys_net_auth_types_WPA2_WPA3_PSK; + case WIFI_AUTH_WAPI_PSK: + return sys_net_auth_types_WAPI_PSK; + case WIFI_AUTH_MAX: + return sys_net_auth_types_OPEN; + } + return sys_net_auth_types_AUTH_UNKNOWN; +} diff --git a/components/platform_config/WifiList.h b/components/platform_config/WifiList.h new file mode 100644 index 00000000..ea8ffa89 --- /dev/null +++ b/components/platform_config/WifiList.h @@ -0,0 +1,185 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ +#pragma once +#include "Network.pb.h" +#include "Status.pb.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "PBW.h" +#include "pb_decode.h" +#include "pb_encode.h" +#ifdef __cplusplus +#include "Locking.h" +#include +#include +#include +#include + +class WifiList : public System::Locking { + public: + WifiList(std::string name) : System::Locking(name), name_(name) {} + ~WifiList(){ + Clear(); + } + static std::string toString(const uint8_t* data, size_t max_length) { + // Find the actual length of the string up to max_length + size_t length = strnlen(reinterpret_cast(data), max_length); + // Construct a std::string using the data and its length + auto p = std::string(reinterpret_cast(data), length); + return p; + } + static void Release(sys_net_wifi_entry& entry){ + Release(&entry); + } + static void Release(sys_net_wifi_entry* entry){ + pb_release(&sys_net_wifi_entry_msg,entry); + } + static std::list GetRadioTypes(const wifi_ap_record_t* sta); + static wifi_auth_mode_t GetESPAuthMode(sys_net_auth_types auth_type); + static sys_net_auth_types GetAuthType(const wifi_ap_record_t* ap); + static sys_net_auth_types GetAuthType(const wifi_auth_mode_t mode); + static bool areRadioTypesDifferent(const sys_net_radio_types* types1, pb_size_t count1, const sys_net_radio_types* types2, pb_size_t count2) { + if (count1 != count2) { + return true; + } + + for (pb_size_t i = 0; i < count1; ++i) { + if (types1[i] != types2[i]) { + return true; + } + } + + return false; + } + static std::string GetPassword(const wifi_sta_config_t* config) { + auto p = toString(config->password, sizeof(config->password)); + return p; + } + + static std::string GetSSID(const wifi_event_sta_connected_t* evt) { return toString(evt->ssid, sizeof(evt->ssid)); } + static std::string GetSSID(const wifi_sta_config_t* config) { return toString(config->ssid, sizeof(config->ssid)); } + static std::string GetSSID(const wifi_ap_record_t* ap) { return toString(ap->ssid, sizeof(ap->ssid)); } + static void FormatBSSID(char* buffer, size_t len, const uint8_t* bssid) { + memset(buffer,0x00,len); + snprintf(buffer, len, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + static void FormatBSSID(const wifi_ap_record_t* ap, sys_net_wifi_entry& entry) { + memset(entry.bssid,0x00,sizeof(entry.bssid)); + if (!ap) return; + FormatBSSID(entry.bssid, sizeof(entry.bssid), ap->bssid); + } + static std::string GetBSSID(const wifi_event_sta_connected_t* evt); + static bool isEmpty(const char* str, size_t len); + static void PrintString(const char* pData, size_t length, const char* format); + static void PrintWifiSTAEntryTitle(); + + sys_net_wifi_entry& GetStrongestSTA(); + bool RemoveCredential(const std::string& ssid); + bool RemoveCredential(const wifi_sta_config_t* sta); + void Clear(); + + static sys_net_wifi_entry ToSTAEntry(const sys_net_wifi_entry* sta); + static sys_net_wifi_entry ToSTAEntry(const wifi_sta_config_t* sta, const std::list& radio_types, + sys_net_auth_types auth_type = sys_net_auth_types_AUTH_UNKNOWN); + static sys_net_wifi_entry ToSTAEntry(const wifi_sta_config_t* sta, sys_net_auth_types auth_type = sys_net_auth_types_AUTH_UNKNOWN); + static sys_net_wifi_entry& ToSTAEntry(const wifi_ap_record_t* ap, sys_net_wifi_entry& item); + static sys_net_wifi_entry ToSTAEntry(const wifi_ap_record_t* ap); + static sys_net_wifi_entry& ToSTAEntry(const wifi_sta_config_t* sta, sys_net_wifi_entry& item, const std::list& radio_types, + sys_net_auth_types auth_type = sys_net_auth_types_AUTH_UNKNOWN); + + static void PrintTimeStamp(const google_protobuf_Timestamp* timestamp); + static void PrintWifiSTAEntry(const sys_net_wifi_entry& entry); + static std::string formatRadioTypes(const sys_net_radio_types* radioTypes, pb_size_t count); + + static bool OffsetTimeStamp(google_protobuf_Timestamp * ts); + static bool UpdateTimeStamp(google_protobuf_Timestamp* ts, bool& has_flag_val); + + bool ResetRSSI(); + bool ResetConnected(); + const sys_net_wifi_entry* GetConnected(); + + bool SetConnected(const wifi_event_sta_connected_t* evt, bool connected = true); + size_t GetCount() const { return credentials_.size(); } + sys_net_wifi_entry* GetIndex(size_t index); + + bool Exists(const std::string& ssid) { return Get(ssid) != nullptr; } + bool Exists(const char* ssid) { return Get(ssid) != nullptr; } + bool Exists(const wifi_ap_record_t* ap) { return ap != nullptr && Get(GetSSID(ap)) != nullptr; } + bool Exists(const wifi_sta_config_t* sta) { return Exists(GetSSID(sta)); } + + bool Update(const wifi_sta_config_t* sta, bool connected = false); + bool Update(const wifi_ap_record_t* ap, bool connected = false); + static bool Update(sys_net_wifi_entry& existingEntry, sys_net_wifi_entry& compared); + + sys_net_wifi_entry* Get(const wifi_sta_config_t* sta) { return Get(GetSSID(sta)); } + sys_net_wifi_entry* Get(const wifi_ap_record_t* ap) { return Get(GetSSID(ap)); } + sys_net_wifi_entry* Get(const char* ssid) { return Get(std::string(ssid)); } + sys_net_wifi_entry* Get(const std::string& ssid); + + bool UpdateFromClock(); + bool UpdateLastTry(const wifi_sta_config_t* sta); + bool UpdateLastTry(const wifi_ap_record_t* ap); + bool UpdateLastTry(const std::string ssid); + bool UpdateLastTry(sys_net_wifi_entry* entry); + bool UpdateLastSeen(const wifi_sta_config_t* sta); + bool UpdateLastSeen(const wifi_ap_record_t* ap); + bool UpdateLastSeen(const std::string ssid); + bool UpdateLastSeen(sys_net_wifi_entry* entry); + sys_net_wifi_entry& AddUpdate(const wifi_sta_config_t* sta, sys_net_auth_types auth_type = sys_net_auth_types_AUTH_UNKNOWN); + sys_net_wifi_entry& AddUpdate(const wifi_sta_config_t* sta, const std::list& radio_types, + sys_net_auth_types auth_type = sys_net_auth_types_AUTH_UNKNOWN); + sys_net_wifi_entry& AddUpdate(const wifi_ap_record_t* scan_rec); + sys_net_wifi_entry& AddUpdate(const char* ssid = "", const char* password = ""); + sys_net_wifi_entry& AddUpdate(const sys_net_wifi_entry* existing, const char* password = ""); + // this one below is used by pb_decode + void AddUpdate(const sys_net_wifi_entry& entry) { + if (!Lock()) { + throw std::runtime_error("Lock failed"); + } + credentials_[entry.ssid] = entry; + Unlock(); + } + using Iterator = std::map::iterator; + using ConstIterator = std::map::const_iterator; + Iterator begin() { return credentials_.begin(); } + ConstIterator begin() const { return credentials_.begin(); } + Iterator end() { return credentials_.end(); } + ConstIterator end() const { return credentials_.end(); } + + private: + static std::string FormatTimestamp(const google_protobuf_Timestamp& timestamp) { + // Format the timestamp as needed + // This is a placeholder implementation. + return std::to_string(timestamp.seconds) + "s"; + } + std::map credentials_; + std::string name_; // Name of the WifiCredentialsManager +}; + +extern "C" { +#endif +typedef struct WifiList WifiList; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/platform_config/test/CMakeLists.txt b/components/platform_config/test/CMakeLists.txt new file mode 100644 index 00000000..5e6edc93 --- /dev/null +++ b/components/platform_config/test/CMakeLists.txt @@ -0,0 +1,20 @@ +idf_component_register(SRC_DIRS . + INCLUDE_DIRS "." + REQUIRES tools platform_config unity ) +# target_compile_options(__idf_platform_config PRIVATE --coverage) +target_include_directories(${COMPONENT_LIB} PUBLIC SYSTEM ${CMAKE_SOURCE_DIR}/test_main) + +message(STATUS "** PLATFORM PROTOBUF") +include(../../../tools/protoc_utils/protobuf_utils.cmake) +configure_env() +file(GLOB PROTO_FILES *.proto) +set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}" "-I${PROJECT_ROOT_DIR}/protobuf/proto") +nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTO_FILES}) + + +# Create a custom target to generate the proto files +set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRUE) +add_custom_target(generate_test_proto ALL DEPENDS ${PROTO_SRCS} ${PROTO_HDRS}) +target_sources(${COMPONENT_LIB} PRIVATE ${PROTO_SRCS}) +add_dependencies(${COMPONENT_LIB} generate_test_proto) +target_include_directories(${COMPONENT_LIB} PUBLIC "include" ${CMAKE_CURRENT_BINARY_DIR} ${NANOPB_INCLUDE_DIRS} ${EXTRA_INCLUDES}) diff --git a/components/platform_config/test/DAC_test_extra.proto b/components/platform_config/test/DAC_test_extra.proto new file mode 100644 index 00000000..a2fb4fe0 --- /dev/null +++ b/components/platform_config/test/DAC_test_extra.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package sys.dac.extra; +import "DAC.proto"; +import "GPIO.proto"; +import "I2CBus.proto"; +import "DacControlSet.proto"; +import "customoptions.proto"; +import "nanopb.proto"; +option (nanopb_fileopt).enum_to_string = true; + +message config { + option (nanopb_msgopt).packed_struct = true; + option (nanopb_msgopt).msgid = 80008; + int32 bck = 1 [(cust_field).v_int32=-1]; + int32 ws = 2 [(cust_field).v_int32=-1]; + int32 dout = 3 [(cust_field).v_int32=-1]; + MCK mck = 4; + gpio.pinmute = 5 [(cust_field).v_msg='{"pin":-1,"level":"LOW"}']; + Models model = 6; + I2CBus i2c = 7; + dac.control.Set daccontrolset = 8; + bool jack_mutes_amp = 9; + uint32 addr = 10; + int32 din = 11 [(cust_field).v_int32=-1]; + int32 dummy1 = 20; + int64 dummy2 = 21; + gpio.pindummy3 = 22; +} \ No newline at end of file diff --git a/components/platform_config/test/DAC_test_extra2.proto b/components/platform_config/test/DAC_test_extra2.proto new file mode 100644 index 00000000..d0a1a362 --- /dev/null +++ b/components/platform_config/test/DAC_test_extra2.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package sys.dac.extra2; +import "DAC.proto"; +import "GPIO.proto"; +import "I2CBus.proto"; +import "DacControlSet.proto"; +import "customoptions.proto"; +import "nanopb.proto"; +option (nanopb_fileopt).enum_to_string = true; + +message config { + option (nanopb_msgopt).packed_struct = true; + option (nanopb_msgopt).msgid = 90008; + int32 bck = 1 [(cust_field).v_int32=-1]; + int32 ws = 2 [(cust_field).v_int32=-1]; + int32 dout = 3 [(cust_field).v_int32=-1]; + MCK mck = 4; + gpio.config mute = 5 [(cust_field).v_msg='{"pin":-1,"level":"LOW"}']; + Models model = 6; + I2CBus i2c = 7; + dac.control.Set daccontrolset = 8; + bool jack_mutes_amp = 9; + uint32 addr = 10; + int32 din = 11 [(cust_field).v_int32=-1]; + int32 dummy1 = 20; + int64 dummy2 = 21; + gpio.config dummy3 = 22; + gpio.config dummy4 = 23; +} \ No newline at end of file diff --git a/components/platform_config/test/test_platform_config.cpp b/components/platform_config/test/test_platform_config.cpp new file mode 100644 index 00000000..7b17dec5 --- /dev/null +++ b/components/platform_config/test/test_platform_config.cpp @@ -0,0 +1,956 @@ + +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#include "Config.h" +#include "DAC.pb.h" +#include "DAC_test_extra.pb.h" +#include "DAC_test_extra2.pb.h" +#include "Locking.h" +#include "PBW.h" +#include "State.pb.h" +#include "WifiList.h" +#include "configuration.pb.h" +#include "esp_log.h" +#include "test_common_init.h" +#include "tools.h" +#include "unity.h" + +using namespace System; + +// Helper macro to stringify the expanded value of a macro +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +// Use the helper macro to stringify LOG_LOCAL_LEVEL +#pragma message("The current log local level value is " TOSTRING(LOG_LOCAL_LEVEL)) +#define AUTH_MODE_INDEX(i) ((start_auth_mode + i) % WIFI_AUTH_MAX == 0 ? (wifi_auth_mode_t)1 : (wifi_auth_mode_t)(start_auth_mode + i)) +static const char* config_file_name = "settings.bin"; + +static const uint8_t bssid[6] = {0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56}; +uint8_t fill_last = 0x56; +uint8_t start_rssi = 70; +uint8_t start_channel = 2; +auto start_auth_mode = WIFI_AUTH_WEP; +uint8_t fill_bssid[6] = {0xAB, 0xCD, 0xEF, 0x12, 0x34, fill_last}; +static const char* char_bssid = "AB:CD:EF:12:34:56"; +static const char* TAG = "test_platform_config"; +const char* password = "TestPassword"; +bool HasMemoryUsageIncreased(int round) { + static const size_t thresholdInternal = 500; // Example threshold for internal memory + static const size_t thresholdSPIRAM = 1000; // Example threshold for SPI RAM + size_t postTestFreeInternal = 0; + size_t postTestFreeSPIRAM = 0; + static size_t initialFreeInternal = 0; + static size_t initialFreeSPIRAM = 0; + auto minFreeInternal = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); + auto minFreeSPIRAM = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); + if (round > 0) { + postTestFreeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + postTestFreeSPIRAM = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); + minFreeInternal = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); + minFreeSPIRAM = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); + + printf("Memory usage summary (after round %d): " + "Internal: %zu->%zu bytes. Min free: %zu. Increase: %d bytes. " + "SPIRAM: %zu->%zu bytes. Min free: %zu. Increase: %d bytes\n", + round, initialFreeInternal, postTestFreeInternal, minFreeInternal, initialFreeInternal - postTestFreeInternal, initialFreeSPIRAM, + postTestFreeSPIRAM, minFreeSPIRAM, initialFreeSPIRAM - postTestFreeSPIRAM); + int32_t diffInternal = initialFreeInternal > postTestFreeInternal ? initialFreeInternal - postTestFreeInternal : 0; + int32_t diffSPIRAM = initialFreeSPIRAM > postTestFreeSPIRAM ? initialFreeSPIRAM - postTestFreeSPIRAM : 0; + if (diffSPIRAM > 0 || diffInternal > 0) { + ESP_LOGW(TAG, "Internal increase: %d, SPIRAM: %d", diffInternal, diffSPIRAM); + return true; + } + } else { + initialFreeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + initialFreeSPIRAM = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); + printf("Memory usage at start: " + "Internal: %zu bytes. Min free: %zu. " + "SPIRAM: %zu bytes. Min free: %zu.\n", + initialFreeInternal, minFreeInternal, initialFreeSPIRAM, minFreeSPIRAM); + } + return false; +} +void advanceTime(int seconds) { + struct timeval tv; + gettimeofday(&tv, NULL); + tv.tv_sec += seconds; + tv.tv_usec += seconds * 100; + settimeofday((const timeval*)&tv, 0); +} +wifi_event_sta_connected_t getMockConnectedEvent(int i = 0) { + wifi_event_sta_connected_t mock = {}; + mock.authmode = WIFI_AUTH_WPA3_PSK; + memset(mock.ssid, 0x00, sizeof(mock.ssid)); + memset(mock.bssid, 0x00, sizeof(mock.bssid)); + snprintf((char*)mock.ssid, sizeof(mock.ssid), "SSID_%d", i); + fill_bssid[5] = fill_last + i; + memcpy(mock.bssid, fill_bssid, sizeof(mock.bssid)); + mock.channel = 6 + i; + mock.ssid_len = strlen((char*)mock.ssid); + return mock; +} +wifi_ap_record_t getMockAPRec(int i = 0) { + wifi_ap_record_t mock = {}; + mock.primary = start_channel + i; // Set some channel + mock.rssi = start_rssi + i; // Set some RSSI value + memset(mock.ssid, 0x00, sizeof(mock.ssid)); + memset(mock.bssid, 0x00, sizeof(mock.bssid)); + snprintf((char*)mock.ssid, sizeof(mock.ssid), "SSID_%d", i); + fill_bssid[5] = fill_last + i; + memcpy(mock.bssid, fill_bssid, sizeof(mock.bssid)); + mock.second = WIFI_SECOND_CHAN_ABOVE; + mock.authmode = AUTH_MODE_INDEX(i); /**< authmode of AP */ + mock.pairwise_cipher = WIFI_CIPHER_TYPE_AES_GMAC128; /**< pairwise cipher of AP */ + mock.group_cipher = WIFI_CIPHER_TYPE_TKIP_CCMP; /**< group cipher of AP */ + mock.ant = WIFI_ANT_ANT1; /**< antenna used to receive beacon from AP */ + mock.phy_11b = 1; /**< bit: 0 flag to identify if 11b mode is enabled or not */ + mock.phy_11g = 0; /**< bit: 1 flag to identify if 11g mode is enabled or not */ + mock.phy_11n = 1; /**< bit: 2 flag to identify if 11n mode is enabled or not */ + mock.phy_lr = 0; /**< bit: 3 flag to identify if low rate is enabled or not */ + mock.wps = 1; /**< bit: 4 flag to identify if WPS is supported or not */ + mock.ftm_responder = 0; /**< bit: 5 flag to identify if FTM is supported in responder mode */ + mock.ftm_initiator = 1; /**< bit: 6 flag to identify if FTM is supported in initiator mode */ + return mock; +} +wifi_sta_config_t getMockSTA(int i = 0) { + wifi_sta_config_t mock = {}; + memset(mock.ssid, 0x00, sizeof(mock.ssid)); + memset(mock.bssid, 0x00, sizeof(mock.bssid)); + snprintf((char*)mock.password, sizeof(mock.password), "Password_%d", i); + snprintf((char*)mock.ssid, sizeof(mock.ssid), "SSID_%d", i); + fill_bssid[5] = fill_last + i; + memcpy(mock.bssid, fill_bssid, sizeof(mock.bssid)); + mock.channel = start_channel + i; + mock.failure_retry_cnt = 2 + i; + mock.listen_interval = 4 + i; + mock.mbo_enabled = 1; + mock.scan_method = WIFI_ALL_CHANNEL_SCAN; + return mock; +} +sys_net_wifi_entry getMockEntry(int i = 0) { + sys_net_wifi_entry mock = sys_net_wifi_entry_init_default; + mock.auth_type = WifiList::GetAuthType(AUTH_MODE_INDEX(i)); + snprintf((char*)mock.password, sizeof(mock.password), "Password_%d", i); + snprintf((char*)mock.ssid, sizeof(mock.ssid), "SSID_%d", i); + fill_bssid[5] = fill_last + i; + WifiList::FormatBSSID(mock.bssid, sizeof(mock.bssid), fill_bssid); + mock.channel = start_channel + i; + mock.connected = false; + mock.has_last_seen = false; + mock.has_last_try = false; + mock.radio_type_count = 3; + mock.radio_type = new sys_net_radio_types[mock.radio_type_count]; + mock.radio_type[0] = sys_net_radio_types_PHY_11B; + mock.radio_type[1] = sys_net_radio_types_PHY_11G; + mock.radio_type[2] = sys_net_radio_types_PHY_11N; + mock.rssi = start_rssi + i; + return mock; +} + +void FillSSIDs(WifiList& manager, int count, int start=1) { + for (int i = start; i <= count; i++) { + auto mock = getMockSTA(i); + auto& entry = manager.AddUpdate(&mock); + entry.rssi = 70 + i; + entry.connected = true; + } +} +void FillSSIDFromAPRec(WifiList& manager, int count, int start=1) { + for (int i = start; i <= count; i++) { + auto mock = getMockAPRec(i); + auto& entry = manager.AddUpdate(&mock); + entry.rssi = 70 + i; + entry.connected = true; + } +} +void FillSSIDFromMockEntry(WifiList& manager, int count, int start=1) { + for (int i = start; i <= count; i++) { + auto mock = getMockEntry(i); + auto& entry = manager.AddUpdate(&mock); + entry.rssi = 70 + i; + entry.connected = true; + WifiList::Release(mock); + } +} +void eraseConfigFile() { + PB wrapper(std::string("config"), &sys_config_msg, sizeof(sys_config_msg), false); + erase_path(wrapper.GetFileName().c_str(), false); +} + +TEST_CASE("Test empty target settings empty", "[platform_config]") { + PB wrapper(std::string("Config"), &sys_config_msg, sizeof(sys_config_msg), false); + sys_config* conf = wrapper.get(); + assert(conf != nullptr); + conf->target = strdup_psram(""); +#ifdef CONFIG_FW_PLATFORM_NAME + system_set_string(&sys_config_msg, sys_config_target_tag, conf, CONFIG_FW_PLATFORM_NAME); + TEST_ASSERT_TRUE(strcmp(conf->target, CONFIG_FW_PLATFORM_NAME) == 0); +#endif +} + +TEST_CASE("Test init from default config", "[platform_config]") { + struct stat fileInformation; + PB wrapper(std::string("config"), &sys_config_msg, sizeof(sys_config_msg), false); + sys_config* confprt = wrapper.get(); + auto filename = wrapper.GetFileName(); + erase_path(filename.c_str(), false); + TEST_ASSERT_FALSE(get_file_info(&fileInformation, config_file_name)); + TEST_ASSERT_TRUE(strlen(STR_OR_BLANK(confprt->target)) == 0); + TEST_ASSERT_FALSE(confprt->has_dev); +} +const sys_config* GetTestConfig() { + static sys_config test_config; + memset(&test_config, 0x00, sizeof(test_config)); + + // Assuming test_config is an instance of sys_config or a similar structure + test_config.has_dev = true; + test_config.dev.has_spi = true; + test_config.dev.spi.mosi = 4; + test_config.dev.spi.clk = 5; + test_config.dev.spi.dc = 18; + test_config.dev.spi.host = sys_dev_common_hosts_Host1; + + test_config.dev.has_dac = true; + test_config.dev.dac.bck = 25; + test_config.dev.dac.ws = 26; + test_config.dev.dac.dout = 33; + test_config.dev.dac.model = sys_dac_models_WM8978; + + test_config.dev.has_display = true; + test_config.dev.display.has_common = true; + test_config.dev.display.common.width = 256; + test_config.dev.display.common.height = 64; + test_config.dev.display.common.HFlip = false; + test_config.dev.display.common.VFlip = false; + test_config.dev.display.common.rotate = false; + test_config.dev.display.common.driver = sys_display_drivers_SSD1322; + test_config.dev.display.common.reset = 21; + test_config.dev.display.which_dispType = sys_display_config_spi_tag; + test_config.dev.display.dispType.spi.cs = 19; + test_config.dev.display.dispType.spi.speed = 8000000; + test_config.dev.has_rotary = true; + + test_config.dev.rotary.A = 23; + test_config.dev.rotary.B = 22; + test_config.dev.rotary.SW = 34; + + test_config.dev.rotary.volume = true; + test_config.dev.rotary.longpress = true; + test_config.has_names = true; + strcpy(test_config.names.device, "test_name"); + if (!test_config.target) { + test_config.target = strdup_psram("test_target"); + } + return &test_config; +} +void check_sys_config_structure(sys_config* config) { + auto check = GetTestConfig(); + // Test SPI configuration + TEST_ASSERT_EQUAL(check->dev.has_spi, config->dev.has_spi); + TEST_ASSERT_EQUAL(check->dev.spi.mosi, config->dev.spi.mosi); + TEST_ASSERT_EQUAL(check->dev.spi.clk, config->dev.spi.clk); + TEST_ASSERT_EQUAL(check->dev.spi.dc, config->dev.spi.dc); + TEST_ASSERT_EQUAL(check->dev.spi.host, config->dev.spi.host); + TEST_ASSERT_EQUAL(check->dev.has_dac, config->dev.has_dac); + TEST_ASSERT_EQUAL(check->dev.dac.bck, config->dev.dac.bck); + TEST_ASSERT_EQUAL(check->dev.dac.ws, config->dev.dac.ws); + TEST_ASSERT_EQUAL(check->dev.dac.dout, config->dev.dac.dout); + TEST_ASSERT_EQUAL(check->dev.dac.model, config->dev.dac.model); + TEST_ASSERT_EQUAL(check->dev.has_display, config->dev.has_display); + TEST_ASSERT_EQUAL(check->dev.display.common.width, config->dev.display.common.width); + TEST_ASSERT_EQUAL(check->dev.display.common.height, config->dev.display.common.height); + TEST_ASSERT_EQUAL(check->dev.display.common.HFlip, config->dev.display.common.HFlip); + TEST_ASSERT_EQUAL(check->dev.display.common.VFlip, config->dev.display.common.VFlip); + TEST_ASSERT_EQUAL(check->dev.display.common.rotate, config->dev.display.common.rotate); + TEST_ASSERT_EQUAL(check->dev.display.common.driver, config->dev.display.common.driver); + TEST_ASSERT_EQUAL(check->dev.display.common.reset, config->dev.display.common.reset); + TEST_ASSERT_EQUAL(check->dev.display.which_dispType, config->dev.display.which_dispType); + TEST_ASSERT_EQUAL(check->dev.display.dispType.spi.cs, config->dev.display.dispType.spi.cs); + TEST_ASSERT_EQUAL(check->dev.display.dispType.spi.speed, config->dev.display.dispType.spi.speed); + TEST_ASSERT_EQUAL(check->dev.has_rotary, config->dev.has_rotary); + TEST_ASSERT_EQUAL(check->dev.rotary.A, config->dev.rotary.A); + TEST_ASSERT_EQUAL(check->dev.rotary.B, config->dev.rotary.B); + TEST_ASSERT_EQUAL(check->dev.rotary.SW, config->dev.rotary.SW); + TEST_ASSERT_EQUAL(check->dev.rotary.volume, config->dev.rotary.volume); + TEST_ASSERT_EQUAL(check->dev.rotary.longpress, config->dev.rotary.longpress); + TEST_ASSERT_EQUAL_STRING(check->names.device, config->names.device); + TEST_ASSERT_EQUAL_STRING(check->target, config->target); +} +TEST_CASE("Test change platform", "[platform_config]") { + struct stat fileInformation; + eraseConfigFile(); + std::stringstream test_target_file; + test_target_file << spiffs_base_path << "/targets/" << GetTestConfig()->target << "/config.bin"; + PlatformConfig::ProtoWrapperHelper::CommitFile(test_target_file.str().c_str(), &sys_config_msg, GetTestConfig()); + + // first ensure that the target state file exists. + TEST_ASSERT_TRUE(get_file_info(&fileInformation, test_target_file.str().c_str())); + TEST_ASSERT_TRUE(fileInformation.st_size > 0); + platform = nullptr; + + // here we must use the configurator object + // since we're testing some config_ functions + std::string expectedTarget = "ESP32"; + TEST_ASSERT_NULL(platform); + config_load(); + TEST_ASSERT_NOT_NULL(platform); + TEST_ASSERT_NOT_NULL(platform->target) + TEST_ASSERT_EQUAL_STRING(expectedTarget.c_str(), platform->target); + config_set_target_reset(GetTestConfig()->target); + check_sys_config_structure(platform); + TEST_ASSERT_EQUAL_STRING(platform->target, GetTestConfig()->target); + TEST_ASSERT_TRUE(erase_path(test_target_file.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInformation, test_target_file.str().c_str())); +} + +// TEST_CASE("Test load state", "[platform_config]") { +// eraseConfigFile(); +// const char* urlvalue = "http://somerandomurl"; +// config_load(); +// system_set_string(&sys_state_data_msg, sys_state_data_ota_url_tag, sys_state, urlvalue); +// TEST_ASSERT_EQUAL_STRING(urlvalue, sys_state->ota_url); +// ESP_LOGI(TAG, "Raising state change"); +// config_raise_state_changed(); + +// // create an async timer lambda to trigger the commit after 1 second so +// //we can test waitcommit +// config_commit_config + +// TEST_CASE("Test Raise State Change", "[platform_config]") { +// // config_load(); +// ESP_LOGI(TAG, "Raising state change"); +// TEST_ASSERT_FALSE(configurator.HasStateChanges()); +// TEST_ASSERT_FALSE(configurator.HasChanges()); +// config_raise_state_changed(); +// TEST_ASSERT_TRUE(configurator.HasStateChanges()); +// TEST_ASSERT_FALSE(configurator.HasChanges()); +// configurator.ResetStateModified(); +// TEST_ASSERT_FALSE(configurator.HasStateChanges()); +// TEST_ASSERT_FALSE(configurator.HasChanges()); +// } +// TEST_CASE("Test Raise Change", "[platform_config]") { +// // config_load(); +// ESP_LOGI(TAG, "Raising change"); +// PlatformConfig::PB wrapper = +// PlatformConfig::PB("config", "", &sys_config_msg, Init_sys_config); +// TEST_ASSERT_FALSE(configurator.HasStateChanges()); +// TEST_ASSERT_FALSE(configurator.HasChanges()); +// config_raise_changed(); +// TEST_ASSERT_TRUE(configurator.HasChanges()); +// TEST_ASSERT_FALSE(configurator.HasStateChanges()); +// configurator.ResetModified(); +// TEST_ASSERT_FALSE(configurator.HasChanges()); +// TEST_ASSERT_FALSE(configurator.HasStateChanges()); +// } + +TEST_CASE("Test Lock Unlock", "[platform_config]") { + auto lock = PlatformConfig::Locking("test"); + TEST_ASSERT_FALSE(lock.IsLocked()); + TEST_ASSERT_TRUE(lock.Lock()); + TEST_ASSERT_TRUE(lock.Lock()); + TEST_ASSERT_TRUE(lock.IsLocked()); + lock.Unlock(); + TEST_ASSERT_TRUE(lock.IsLocked()); + lock.Unlock(); + TEST_ASSERT_FALSE(lock.IsLocked()); +} + +TEST_CASE("Recovery not updating message definition", "[platform_config]") { + is_recovery_running = false; + auto name = std::string("extra"); + struct stat struct_info_extra; + struct stat struct_info_reco; + // create instance with fresh definition + erase_path(PBHelper::GetDefFileName(name).c_str(), false); + PB wrapper_extra(name.c_str(), &sys_dac_extra_config_msg, sizeof(sys_dac_extra_config_msg)); + TEST_ASSERT_TRUE(get_file_info(&struct_info_extra, wrapper_extra.GetDefFileName().c_str())); + TEST_ASSERT_TRUE(struct_info_extra.st_size > 0); + auto& extra = wrapper_extra.Root(); + extra.dummy1 = 20; + extra.dummy2 = 30; + extra.has_dummy3 = true; + extra.dummy3.level = sys_gpio_lvl_HIGH; + extra.dummy3.pin = 22; + wrapper_extra.CommitChanges(); + + is_recovery_running = true; + PB wrapper(name, &sys_dac_config_msg, sizeof(sys_dac_config_msg)); + TEST_ASSERT_TRUE(get_file_info(&struct_info_reco, wrapper.GetDefFileName().c_str())); + TEST_ASSERT_TRUE(struct_info_reco.st_size == struct_info_extra.st_size); + TEST_ASSERT_EQUAL(wrapper_extra.GetDataSize(), wrapper.GetDataSize()); + wrapper.LoadFile(true); + + sys_dac_extra_config* config = reinterpret_cast(wrapper.get()); + TEST_ASSERT_EQUAL(config->dummy1, extra.dummy1); + TEST_ASSERT_EQUAL(config->dummy2, extra.dummy2); + TEST_ASSERT_EQUAL(config->has_dummy3, extra.has_dummy3); + TEST_ASSERT_EQUAL(config->dummy3.level, extra.dummy3.level); + TEST_ASSERT_EQUAL(config->dummy3.pin, extra.dummy3.pin); + + config->bck = 55; + wrapper.CommitChanges(); + PB check_structure(name.c_str(), &sys_dac_extra_config_msg, sizeof(sys_dac_extra_config_msg)); + check_structure.LoadFile(true); + auto config_check = check_structure.get(); + TEST_ASSERT_EQUAL(config->bck, check_structure.get()->bck); + TEST_ASSERT_EQUAL(config_check->dummy1, extra.dummy1); + TEST_ASSERT_EQUAL(config_check->dummy2, extra.dummy2); + TEST_ASSERT_EQUAL(config_check->has_dummy3, extra.has_dummy3); + TEST_ASSERT_EQUAL(config_check->dummy3.level, extra.dummy3.level); + TEST_ASSERT_EQUAL(config_check->dummy3.pin, extra.dummy3.pin); + + // not simulate an update + is_recovery_running = false; + PB extra2(name.c_str(), &sys_dac_extra2_config_msg, sizeof(sys_dac_extra2_config_msg)); + extra2.LoadFile(true); + auto config_extra2 = extra2.get(); + config_extra2->has_dummy4 = true; + config_extra2->dummy4.pin = 99; + extra2.CommitChanges(); + is_recovery_running = true; + PB wrapper2(name, &sys_dac_config_msg, sizeof(sys_dac_config_msg)); + + wrapper2.LoadFile(true); + wrapper2.Root().bck = 88; + wrapper2.CommitChanges(); + + is_recovery_running = false; + extra2.LoadFile(true); + TEST_ASSERT_EQUAL(config_extra2->bck, 88); + TEST_ASSERT_TRUE(config_extra2->has_dummy4); + TEST_ASSERT_EQUAL(config_extra2->dummy4.pin, 99); +} +TEST_CASE("String conversion from uint8_t array", "[WifiCredentialsManager]") { + // Prepare test data + const uint8_t testData[] = {'T', 'e', 's', 't', '\0', 'D', 'a', 't', 'a'}; + const size_t testDataLength = 9; // Including '\0' + + // Call the method + std::string result = WifiList::toString(testData, testDataLength); + + // Assert expectations + TEST_ASSERT_EQUAL_STRING_LEN("Test", result.c_str(), result.length()); +} +TEST_CASE("Get SSID from wifi_sta_config_t", "[WifiCredentialsManager]") { + // Prepare test data + wifi_sta_config_t testConfig = getMockSTA(1); + // Call the method + std::string result = WifiList::GetSSID(&testConfig); + TEST_ASSERT_EQUAL_STRING("SSID_1", result.c_str()); +} +TEST_CASE("Get SSID from wifi_event_sta_connected_t", "[WifiCredentialsManager]") { + wifi_event_sta_connected_t testEvent = {}; + const char* ssid = "EventSSID"; + memcpy(testEvent.ssid, ssid, strlen(ssid) + 1); // Including '\0' + + std::string result = WifiList::GetSSID(&testEvent); + TEST_ASSERT_EQUAL_STRING(ssid, result.c_str()); +} +TEST_CASE("Get SSID from wifi_ap_record_t", "[WifiCredentialsManager]") { + wifi_ap_record_t testRecord = {}; + const char* ssid = "RecordSSID"; + memcpy(testRecord.ssid, ssid, strlen(ssid) + 1); // Including '\0' + + std::string result = WifiList::GetSSID(&testRecord); + TEST_ASSERT_EQUAL_STRING(ssid, result.c_str()); +} +TEST_CASE("Get Password from wifi_sta_config_t", "[WifiCredentialsManager]") { + wifi_sta_config_t testConfig = {}; + memcpy(testConfig.password, password, strlen(password) + 1); // Including '\0' + + std::string result = WifiList::GetPassword(&testConfig); + TEST_ASSERT_EQUAL_STRING(password, result.c_str()); +} +TEST_CASE("Get BSSID from wifi_event_sta_connected_t", "[WifiCredentialsManager]") { + wifi_event_sta_connected_t testEvent = {}; + memcpy(testEvent.bssid, bssid, sizeof(testEvent.bssid)); + std::string result = WifiCredentialsManager::GetBSSID(&testEvent); + TEST_ASSERT_EQUAL_STRING(char_bssid, result.c_str()); +} +TEST_CASE("Format BSSID from uint8_t array", "[WifiCredentialsManager]") { + char buffer[18] = {0}; + WifiCredentialsManager::FormatBSSID(buffer, sizeof(buffer), bssid); + TEST_ASSERT_EQUAL_STRING(char_bssid, buffer); +} + +TEST_CASE("Update timestamp", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + + // Test with a non-null timestamp and an uninitialized flag + google_protobuf_Timestamp ts = {0, 0}; + bool has_flag = false; + + bool result = manager.UpdateTimeStamp(&ts, has_flag); + + TEST_ASSERT_TRUE(result); // Check if the method returns true for change + TEST_ASSERT_TRUE(has_flag); // Check if the flag is set to true + TEST_ASSERT_NOT_EQUAL(0, ts.seconds); // Assuming gettimeofday() gives a non-zero time + TEST_ASSERT_NOT_EQUAL(0, ts.nanos); + + // Store the updated values for comparison + long prev_seconds = ts.seconds; + long prev_nanos = ts.nanos; + advanceTime(2); + + // Call the method again with the same timestamp + result = manager.UpdateTimeStamp(&ts, has_flag); + + // Since the timestamp should be updated, check if the new values are different + TEST_ASSERT_TRUE(result); + TEST_ASSERT_TRUE(has_flag); + TEST_ASSERT_NOT_EQUAL(prev_seconds, ts.seconds); + TEST_ASSERT_NOT_EQUAL(prev_nanos, ts.nanos); + + // Test with a null timestamp + result = manager.UpdateTimeStamp(nullptr, has_flag); + + // The method should return false, and the flag should remain unchanged + TEST_ASSERT_FALSE(result); + TEST_ASSERT_TRUE(has_flag); // Flag remains unchanged + advanceTime(-2); +} + +TEST_CASE("Update wifi entry", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + + sys_net_wifi_entry existingEntry = getMockEntry(); + sys_net_wifi_entry updatedEntry = getMockEntry(); + + // Modify updatedEntry with different values + strcpy(updatedEntry.password, "NewPassword"); + updatedEntry.channel = 5; + updatedEntry.auth_type = sys_net_auth_types_WPA2_PSK; + delete[] updatedEntry.radio_type; + updatedEntry.radio_type_count = 1; + updatedEntry.radio_type = new sys_net_radio_types[updatedEntry.radio_type_count]; // Dynamic allocation for radio_type + updatedEntry.radio_type[0] = sys_net_radio_types_PHY_11N; + + updatedEntry.rssi = 42; + updatedEntry.connected = true; + + // Call the Update method + bool result = manager.Update(existingEntry, updatedEntry); + + // Assert that the Update method returns true + TEST_ASSERT_TRUE(result); + + // Assert that the existingEntry is updated correctly + TEST_ASSERT_EQUAL_STRING("NewPassword", existingEntry.password); + TEST_ASSERT_EQUAL(updatedEntry.channel, existingEntry.channel); + TEST_ASSERT_EQUAL(sys_net_auth_types_WPA2_PSK, existingEntry.auth_type); + TEST_ASSERT_EQUAL(sys_net_radio_types_PHY_11N, existingEntry.radio_type[0]); + TEST_ASSERT_EQUAL(updatedEntry.radio_type_count, existingEntry.radio_type_count); + TEST_ASSERT_EQUAL(updatedEntry.rssi, existingEntry.rssi); + TEST_ASSERT_TRUE(existingEntry.connected); + + // Clean up dynamically allocated memory + delete[] updatedEntry.radio_type; + delete[] existingEntry.radio_type; +} + +TEST_CASE("Update wifi entry from AP record", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + + // Create a mock wifi_ap_record_t + wifi_ap_record_t mockAP = {}; + // Initialize mockAP with test data + // ... + + // Add the initial entry + sys_net_wifi_entry initialEntry = manager.ToSTAEntry(&mockAP); + initialEntry.connected = false; // Initially not connected + manager.AddUpdate(initialEntry); + + // Now call the update with the same AP but with 'connected' status + bool result = manager.Update(&mockAP, true); + + // Assert that the update was successful + TEST_ASSERT_TRUE(result); + + // Retrieve the entry and check if it's updated + auto updatedEntry = manager.Get(&mockAP); + TEST_ASSERT_NOT_NULL(updatedEntry); + TEST_ASSERT_TRUE(updatedEntry->connected); // Check if connected is now true + manager.Clear(); +} + +TEST_CASE("Format radio types", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + + // Create an array of radio types for testing + sys_net_radio_types radioTypes[] = {sys_net_radio_types_PHY_11B, sys_net_radio_types_PHY_11G, sys_net_radio_types_PHY_11N, sys_net_radio_types_LR, + sys_net_radio_types_WPS, sys_net_radio_types_FTM_RESPONDER, sys_net_radio_types_FTM_INITIATOR, sys_net_radio_types_UNKNOWN}; + pb_size_t count = sizeof(radioTypes) / sizeof(radioTypes[0]); + + // Call the formatRadioTypes method + std::string formattedString = manager.formatRadioTypes(radioTypes, count); + + // Define the expected result + std::string expectedResult = "B,G,N,L,W,FR,FI,U"; + + // Assert that the formatted string is as expected + TEST_ASSERT_EQUAL_STRING(expectedResult.c_str(), formattedString.c_str()); + manager.Clear(); +} + +TEST_CASE("Update wifi entry from STA config", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + + // Create a mock wifi_sta_config_t + wifi_sta_config_t mockSTA = getMockSTA(); + + // Create and add an initial entry + sys_net_wifi_entry initialEntry = manager.ToSTAEntry(&mockSTA); + initialEntry.connected = false; // Initially not connected + manager.AddUpdate(initialEntry); + + // Modify the mockSTA for the update + mockSTA.channel = 6; // Change the channel + + // Now call the update with the modified mockSTA and 'connected' status + bool result = manager.Update(&mockSTA, true); + + // Assert that the update was successful + TEST_ASSERT_TRUE(result); + + // Retrieve the updated entry and check if it's correctly updated + auto updatedEntry = manager.Get(&mockSTA); + TEST_ASSERT_NOT_NULL(updatedEntry); + TEST_ASSERT_EQUAL(mockSTA.channel, updatedEntry->channel); + TEST_ASSERT_TRUE(updatedEntry->connected); // Check if connected is now true + manager.Clear(); +} + +TEST_CASE("Convert AP record to STA entry", "[WifiCredentialsManager]") { + int testindex = 1; + WifiCredentialsManager manager("test_manager"); + + // Create a mock wifi_ap_record_t + wifi_ap_record_t mockAP = getMockAPRec(testindex); + + sys_net_wifi_entry entry; // Create an entry to be populated + + // Call ToSTAEntry + sys_net_wifi_entry& resultEntry = manager.ToSTAEntry(&mockAP, entry); + + // Assert that the entry is populated correctly + TEST_ASSERT_EQUAL_STRING("SSID_1", resultEntry.ssid); + TEST_ASSERT_EQUAL(start_channel + testindex, resultEntry.channel); + TEST_ASSERT_EQUAL(start_rssi + testindex, resultEntry.rssi); + TEST_ASSERT_EQUAL(WifiList::GetAuthType(AUTH_MODE_INDEX(testindex)), resultEntry.auth_type); + TEST_ASSERT_EQUAL(4, resultEntry.radio_type_count); + std::string formattedString = manager.formatRadioTypes(resultEntry.radio_type, resultEntry.radio_type_count); + // Define the expected result + std::string expectedResult = "B,N,W,FI"; + TEST_ASSERT_EQUAL_STRING(expectedResult.c_str(), formattedString.c_str()); + char bssid_buffer[20] = {}; + WifiList::FormatBSSID(bssid_buffer, sizeof(bssid_buffer), mockAP.bssid); + TEST_ASSERT_EQUAL_STRING((char*)bssid_buffer, resultEntry.bssid); + + manager.Clear(); +} + +TEST_CASE("Remove entries from manager instance", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + FillSSIDs(manager, 4); + TEST_ASSERT_EQUAL(4, manager.GetCount()); + TEST_ASSERT_TRUE(manager.RemoveCredential("SSID_1")); + TEST_ASSERT_EQUAL(3, manager.GetCount()); + TEST_ASSERT_FALSE(manager.RemoveCredential("SSID_1")); + TEST_ASSERT_EQUAL(3, manager.GetCount()); + manager.Clear(); + TEST_ASSERT_EQUAL(0, manager.GetCount()); + + FillSSIDs(manager, 4); + TEST_ASSERT_EQUAL(4, manager.GetCount()); + TEST_ASSERT_TRUE(manager.RemoveCredential(std::string("SSID_1"))); + TEST_ASSERT_FALSE(manager.RemoveCredential(std::string("SSID_1"))); + TEST_ASSERT_TRUE(manager.RemoveCredential("SSID_2")); + TEST_ASSERT_FALSE(manager.RemoveCredential(std::string("SSID_2"))); + TEST_ASSERT_EQUAL(2, manager.GetCount()); + manager.Clear(); + TEST_ASSERT_EQUAL(0, manager.GetCount()); +} +TEST_CASE("Reset all entries", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + FillSSIDs(manager, 4); + for (auto& e : manager) { + TEST_ASSERT_TRUE(e.second.rssi > 0); + TEST_ASSERT_TRUE(e.second.connected); + } + manager.ResetRSSI(); + for (auto& e : manager) { + TEST_ASSERT_TRUE(e.second.rssi == 0); + TEST_ASSERT_TRUE(e.second.connected); + } + manager.Clear(); + FillSSIDs(manager, 4); + manager.ResetConnected(); + for (auto& e : manager) { + TEST_ASSERT_TRUE(e.second.rssi > 0); + TEST_ASSERT_FALSE(e.second.connected); + } +} + +TEST_CASE("Getting/setting Connected", "[WifiCredentialsManager]") { + WifiCredentialsManager manager("test_manager"); + auto conn_mock_4 = getMockConnectedEvent(4); + auto conn_mock_5 = getMockConnectedEvent(5); + auto entry_5 = getMockEntry(5); + char bssid_buffer[20] = {}; + FillSSIDs(manager, 4); + for (auto& e : manager) { + if (strcmp(e.second.ssid, "SSID_3") != 0) { + e.second.connected = false; + } + } + auto entry = manager.GetConnected(); + TEST_ASSERT_EQUAL_STRING("SSID_3", entry->ssid); + TEST_ASSERT_FALSE(manager.SetConnected(&conn_mock_5, true)); + manager.AddUpdate(&entry_5); + WifiCredentialsManager::Release(entry_5); + TEST_ASSERT_TRUE(manager.SetConnected(&conn_mock_5, true)); + entry = manager.GetConnected(); + TEST_ASSERT_EQUAL_STRING_LEN((char*)conn_mock_5.ssid, entry->ssid, conn_mock_5.ssid_len); + WifiCredentialsManager::FormatBSSID(bssid_buffer, sizeof(bssid_buffer), conn_mock_5.bssid); + TEST_ASSERT_EQUAL_STRING((char*)bssid_buffer, entry->bssid); + TEST_ASSERT_EQUAL(WifiList::GetAuthType(conn_mock_5.authmode), entry->auth_type); + TEST_ASSERT_EQUAL(conn_mock_5.channel, entry->channel); + TEST_ASSERT_TRUE(manager.SetConnected(&conn_mock_4, true)); + entry = manager.GetConnected(); + TEST_ASSERT_EQUAL_STRING_LEN((char*)conn_mock_4.ssid, entry->ssid, conn_mock_5.ssid_len); + WifiList::FormatBSSID(bssid_buffer, sizeof(bssid_buffer), conn_mock_4.bssid); + TEST_ASSERT_EQUAL_STRING((char*)bssid_buffer, entry->bssid); + TEST_ASSERT_EQUAL(WifiList::GetAuthType(conn_mock_4.authmode), entry->auth_type); + TEST_ASSERT_EQUAL(conn_mock_4.channel, entry->channel); + manager.ResetConnected(); + TEST_ASSERT_NULL(manager.GetConnected()); + manager.Clear(); +} + +TEST_CASE("Getting by index/by name", "[WifiCredentialsManager]") { + char buffer[25] = {}; + WifiCredentialsManager manager("test_manager"); + FillSSIDs(manager, 4); + for (int i = 0; i < manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i + 1); + auto mockap = getMockAPRec(i + 1); + auto mockSTA = getMockSTA(i + 1); + auto entry = manager.GetIndex(i); + TEST_ASSERT_EQUAL_STRING(buffer, entry->ssid); + auto pEntry = manager.Get(std::string(buffer)); + TEST_ASSERT_EQUAL_STRING(buffer, pEntry->ssid); + pEntry = manager.Get(buffer); + TEST_ASSERT_EQUAL_STRING(buffer, pEntry->ssid); + pEntry = manager.Get(&mockap); + TEST_ASSERT_EQUAL_STRING(buffer, pEntry->ssid); + pEntry = manager.Get(&mockSTA); + TEST_ASSERT_EQUAL_STRING(buffer, pEntry->ssid); + } + auto entry = manager.GetStrongestSTA(); + TEST_ASSERT_EQUAL_STRING("SSID_4", entry.ssid); + manager.Clear(); +} + +TEST_CASE("Update last try", "[WifiCredentialsManager]") { + char buffer[25] = {}; + google_protobuf_Timestamp ts; + bool flag; + WifiCredentialsManager::UpdateTimeStamp(&ts, flag); + + // now advance the time to ensure tests are a success + advanceTime(2); + + WifiList manager("test_manager"); + FillSSIDs(manager, 4); + for (int i = 0; i < manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i + 1); + auto mockap = getMockAPRec(i + 1); + auto mockSTA = getMockSTA(i + 1); + auto entry = manager.GetIndex(i); + entry->has_last_try = false; + memset(&entry->last_try, 0x00, sizeof(entry->last_try)); + manager.UpdateLastTry(entry); + TEST_ASSERT_TRUE(entry->has_last_try); + TEST_ASSERT_TRUE(entry->last_try.seconds >= ts.seconds); + entry->has_last_try = false; + memset(&entry->last_try, 0x00, sizeof(entry->last_try)); + manager.UpdateLastTry(std::string(buffer)); + TEST_ASSERT_TRUE(entry->has_last_try); + TEST_ASSERT_TRUE(entry->last_try.seconds >= ts.seconds); + entry->has_last_try = false; + memset(&entry->last_try, 0x00, sizeof(entry->last_try)); + manager.UpdateLastTry(&mockap); + TEST_ASSERT_TRUE(entry->has_last_try); + TEST_ASSERT_TRUE(entry->last_try.seconds >= ts.seconds); + entry->has_last_try = false; + memset(&entry->last_try, 0x00, sizeof(entry->last_try)); + manager.UpdateLastTry(&mockSTA); + TEST_ASSERT_TRUE(entry->has_last_try); + TEST_ASSERT_TRUE(entry->last_try.seconds >= ts.seconds); + } + auto entry = manager.GetStrongestSTA(); + TEST_ASSERT_EQUAL_STRING("SSID_4", entry.ssid); + manager.Clear(); + advanceTime(-2); +} + +TEST_CASE("Update last seen", "[WifiCredentialsManager]") { + char buffer[25] = {}; + google_protobuf_Timestamp ts; + bool flag; + WifiCredentialsManager::UpdateTimeStamp(&ts, flag); + + // now advance the time to ensure tests are a success + advanceTime(2); + + WifiList manager("test_manager"); + FillSSIDs(manager, 4); + for (int i = 0; i < manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i + 1); + auto mockap = getMockAPRec(i + 1); + auto mockSTA = getMockSTA(i + 1); + auto entry = manager.GetIndex(i); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(entry); + TEST_ASSERT_TRUE(entry->has_last_seen); + TEST_ASSERT_TRUE(entry->last_seen.seconds >= ts.seconds); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(std::string(buffer)); + TEST_ASSERT_TRUE(entry->has_last_seen); + TEST_ASSERT_TRUE(entry->last_seen.seconds >= ts.seconds); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockap); + TEST_ASSERT_TRUE(entry->has_last_seen); + TEST_ASSERT_TRUE(entry->last_seen.seconds >= ts.seconds); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockSTA); + TEST_ASSERT_TRUE(entry->has_last_seen); + TEST_ASSERT_TRUE(entry->last_seen.seconds >= ts.seconds); + } + + manager.Clear(); + advanceTime(-2); +} + +TEST_CASE("Memory leak test", "[WifiCredentialsManager]") { + char buffer[25] = {}; + char err_buffer[55] = {}; + int fillqty=20; + google_protobuf_Timestamp ts; + bool flag; + + WifiCredentialsManager::UpdateTimeStamp(&ts, flag); + + // now advance the time to ensure tests are a success + advanceTime(2); + HasMemoryUsageIncreased(0); + + for (int runs = 0; runs < 100; runs++) { + WifiCredentialsManager manager("test_manager"); + FillSSIDs(manager, fillqty); + for (int i = 1; i <= manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i); + sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + auto mockap = getMockAPRec(i); + auto mockSTA = getMockSTA(i); + auto entry = manager.Get(buffer); + TEST_ASSERT_EQUAL_STRING(buffer,entry->ssid); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(entry); + TEST_ASSERT_TRUE(entry->has_last_seen); + TEST_ASSERT_TRUE(entry->last_seen.seconds >= ts.seconds); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(std::string(buffer)); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockap); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockSTA); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + } + manager.Clear(); + } + TEST_ASSERT_FALSE(HasMemoryUsageIncreased(1)); + + for (int runs = 0; runs < 100; runs++) { + WifiCredentialsManager manager("test_manager"); + FillSSIDFromAPRec(manager, fillqty); + for (int i = 1; i <= manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i); + sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + auto mockap = getMockAPRec(i); + auto mockSTA = getMockSTA(i); + auto entry = manager.GetIndex(i-1); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(entry); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(std::string(buffer)); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockap); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockSTA); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + } + manager.Clear(); + } + TEST_ASSERT_FALSE(HasMemoryUsageIncreased(2)); + + for (int runs = 0; runs < 100; runs++) { + WifiCredentialsManager manager("test_manager"); + FillSSIDFromMockEntry(manager, fillqty); + for (int i = 1; i <= manager.GetCount(); i++) { + sprintf(buffer, "SSID_%d", i); + sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + auto mockap = getMockAPRec(i); + auto mockSTA = getMockSTA(i); + auto entry = manager.GetIndex(i-1); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(entry); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(std::string(buffer)); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockap); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + entry->has_last_seen = false; + memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); + manager.UpdateLastSeen(&mockSTA); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + } + manager.Clear(); + } + advanceTime(-2); + TEST_ASSERT_FALSE(HasMemoryUsageIncreased(3)); +} \ No newline at end of file diff --git a/components/platform_console/CMakeLists.txt b/components/platform_console/CMakeLists.txt index e3d0d08d..f072cb1d 100644 --- a/components/platform_console/CMakeLists.txt +++ b/components/platform_console/CMakeLists.txt @@ -7,7 +7,7 @@ idf_component_register( SRCS cmd_config.c INCLUDE_DIRS . REQUIRES nvs_flash - PRIV_REQUIRES console app_update tools services spi_flash platform_config vfs pthread wifi-manager platform_config newlib telnet display squeezelite tools metrics) + PRIV_REQUIRES console app_update tools services spi_flash tools platform_config vfs pthread wifi-manager newlib telnet display squeezelite metrics) set_source_files_properties(cmd_config.c PROPERTIES COMPILE_FLAGS diff --git a/components/platform_console/app_squeezelite/CMakeLists.txt b/components/platform_console/app_squeezelite/CMakeLists.txt index 9fdf664d..82bc90b0 100644 --- a/components/platform_console/app_squeezelite/CMakeLists.txt +++ b/components/platform_console/app_squeezelite/CMakeLists.txt @@ -1,7 +1,7 @@ idf_build_get_property(idf_path IDF_PATH) idf_component_register( SRCS cmd_squeezelite.c INCLUDE_DIRS . - PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display tools services) + PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display services) target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=feof") diff --git a/components/platform_console/app_squeezelite/cmd_squeezelite.c b/components/platform_console/app_squeezelite/cmd_squeezelite.c index b6cc3aac..d4a158ec 100644 --- a/components/platform_console/app_squeezelite/cmd_squeezelite.c +++ b/components/platform_console/app_squeezelite/cmd_squeezelite.c @@ -1,23 +1,27 @@ -#include -#include -#include "application_name.h" -#include "esp_log.h" -#include "esp_console.h" #include "../cmd_system.h" +#include "Config.h" +#include "application_name.h" #include "argtable3/argtable3.h" +#include "esp_app_format.h" +#include "esp_console.h" +#include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" -#include "pthread.h" -#include "platform_esp32.h" -#include "Configurator.h" -#include "esp_app_format.h" -#include "tools.h" #include "messaging.h" -extern esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length); -extern int squeezelite_main_start(); +#include "platform_esp32.h" +#include "pthread.h" +#include "tools.h" +#include +#include +#include "bootstate.h" -static const char * TAG = "squeezelite_cmd"; -#define SQUEEZELITE_THREAD_STACK_SIZE (8*1024) +extern esp_err_t process_recovery_ota(const char* bin_url, char* bin_buffer, uint32_t length); +extern int squeezelite_main_start(); +extern sys_dac_default_sets* default_dac_sets; + + +static const char* TAG = "squeezelite_cmd"; +#define SQUEEZELITE_THREAD_STACK_SIZE (8 * 1024) #define ADDITIONAL_SQUEEZELITE_ARGS 5 const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { @@ -45,112 +49,91 @@ const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { extern void register_audio_config(void); // extern void register_rotary_config(void); extern void register_nvs(); -extern cJSON * get_gpio_list_handler(bool refresh); -cJSON * get_gpio_list(bool refresh){ -#if CONFIG_WITH_CONFIG_UI - return get_gpio_list_handler(refresh); +extern cJSON* get_gpio_list_handler(bool refresh); +cJSON* get_gpio_list(bool refresh) { +#if CONFIG_WITH_CONFIG_UI + return get_gpio_list_handler(refresh); #else - return cJSON_CreateArray(); + return cJSON_CreateArray(); #endif } void register_optional_cmd(void) { -// #if CONFIG_WITH_CONFIG_UI -// register_rotary_config(); -// #endif + // #if CONFIG_WITH_CONFIG_UI + // register_rotary_config(); + // #endif register_audio_config(); - // register_ledvu_config(); - + // register_ledvu_config(); } -/** Arguments used by 'squeezelite' function */ static struct { - struct arg_str *parameters; - struct arg_end *end; -} squeezelite_args; -static struct { - int argc; - char ** argv; -} thread_parms ; + int argc; + char** argv; +} thread_parms; -static void squeezelite_thread(void *arg){ - ESP_LOGV(TAG ,"Number of args received: %u",thread_parms.argc ); - ESP_LOGV(TAG ,"Values:"); - for(int i = 0;i 1 ? MESSAGING_ERROR : MESSAGING_WARNING,"squeezelite exited with error code %d\n", ret); +static void squeezelite_thread(void* arg) { + ESP_LOGI(TAG, "Calling squeezelite"); + int wait = 60; + int ret = squeezelite_main_start(); - if (ret <= 1) { - int wait = 60; - // wait_for_commit(); - // TODO: Add support for the commented code - cmd_send_messaging("cfg-audio-tmpl",MESSAGING_ERROR,"Rebooting in %d sec\n", wait); - vTaskDelay( pdMS_TO_TICKS(wait * 1000)); - esp_restart(); + if (ret == -2) { + cmd_send_messaging("cfg-audio-tmpl", MESSAGING_ERROR, + "Squeezelite not configured. Rebooting to factory in %d sec\n", wait); + vTaskDelay(pdMS_TO_TICKS(wait * 1000)); + guided_factory(); } else { - cmd_send_messaging("cfg-audio-tmpl",MESSAGING_ERROR,"Correct command line and reboot\n"); - vTaskSuspend(NULL); + cmd_send_messaging("cfg-audio-tmpl", ret > 1 ? MESSAGING_ERROR : MESSAGING_WARNING, + "squeezelite exited with error code %d\n", ret); + if (ret <= 1) { + + cmd_send_messaging( + "cfg-audio-tmpl", MESSAGING_ERROR, "Rebooting to factory in %d sec\n", wait); + vTaskDelay(pdMS_TO_TICKS(wait * 1000)); + guided_factory(); + } else { + + cmd_send_messaging( + "cfg-audio-tmpl", MESSAGING_ERROR, "Correct command line and reboot\n"); + vTaskSuspend(NULL); + } } - ESP_LOGV(TAG, "Exited from squeezelite's main(). Freeing argv structure."); + ESP_LOGV(TAG, "Exited from squeezelite's main(). Freeing argv structure."); - for(int i=0;i", "command line for squeezelite. -h for help, --defaults to launch with default values."); -// squeezelite_args.end = arg_end(1); -// const esp_console_cmd_t launch_squeezelite = { -// .command = "squeezelite", -// .help = "Starts squeezelite", +// squeezelite_args.parameters = arg_str0(NULL, NULL, "", "command line for squeezelite. -h +// for help, --defaults to launch with default values."); squeezelite_args.end = arg_end(1); const +// esp_console_cmd_t launch_squeezelite = { .command = "squeezelite", .help = "Starts squeezelite", // .hint = NULL, // .func = &launchsqueezelite, // .argtable = &squeezelite_args @@ -158,19 +141,19 @@ void start_squeezelite(){ // ESP_ERROR_CHECK( esp_console_cmd_register(&launch_squeezelite) ); // } -esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length) { - if(!bin_url || strlen(bin_url)==0){ - ESP_LOGE(TAG,"missing URL parameter. Unable to start OTA"); - return ESP_ERR_INVALID_ARG; - } - ESP_LOGW(TAG, "Called to update the firmware from url: %s",bin_url); - configurator_set_string(&sys_State_msg,sys_State_ota_url_tag,sys_state,bin_url); - configurator_raise_state_changed(); +esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length) { + if (!bin_url || strlen(bin_url) == 0) { + ESP_LOGE(TAG, "missing URL parameter. Unable to start OTA"); + return ESP_ERR_INVALID_ARG; + } + ESP_LOGW(TAG, "Called to update the firmware from url: %s", bin_url); + system_set_string(&sys_state_data_msg, sys_state_data_ota_url_tag, sys_state, bin_url); + config_raise_state_changed(); - if(!configurator_waitcommit()){ - ESP_LOGW(TAG,"Unable to commit configuration. "); - } - ESP_LOGW(TAG, "Rebooting to recovery to complete the installation"); - return guided_factory(); - return ESP_OK; + if (!config_waitcommit()) { + ESP_LOGW(TAG, "Unable to commit configuration. "); + } + ESP_LOGW(TAG, "Rebooting to recovery to complete the installation"); + return guided_factory(); + return ESP_OK; } diff --git a/components/platform_console/cmd_config.c b/components/platform_console/cmd_config.c index b664c975..f23f6eba 100644 --- a/components/platform_console/cmd_config.c +++ b/components/platform_console/cmd_config.c @@ -6,57 +6,58 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -#include #include "cmd_config.h" -#include "argtable3/argtable3.h" -#include "platform_console.h" -#include "esp_log.h" -#include "string.h" -#include "stdio.h" -#include "Configurator.h" -#include "messaging.h" +#include "Config.h" #include "accessors.h" #include "adac.h" -#include "tools.h" +#include "argtable3/argtable3.h" #include "cJSON.h" #include "cmd_i2ctools.h" +#include "esp_log.h" +#include "messaging.h" +#include "platform_console.h" +#include "stdio.h" +#include "string.h" +#include "tools.h" +#include #if defined(CONFIG_WITH_METRICS) #include "metrics.h" #endif #include "cmd_system.h" #include "network_manager.h" -const char * desc_squeezelite ="Squeezelite Options"; -const char * desc_wifi ="Wifi Operations"; -const char * desc_dac= "DAC Options"; -const char * desc_cspotc= "Spotify (cSpot) Options"; -const char * desc_preset= "Preset Options"; -const char * desc_spdif= "SPDIF Options"; -const char * desc_audio= "General Audio Options"; -const char * desc_bt_source= "Bluetooth Audio Output Options"; -const char * desc_rotary= "Rotary Control"; -const char * desc_ledvu= "Led Strip Options"; +#include "network_wifi.h" +const char* desc_squeezelite = "Squeezelite Options"; +const char* desc_wifi = "Wifi Operations"; +const char* desc_dac = "DAC Options"; +const char* desc_cspotc = "Spotify (cSpot) Options"; +const char* desc_preset = "Preset Options"; +const char* desc_spdif = "SPDIF Options"; +const char* desc_audio = "General Audio Options"; +const char* desc_bt_source = "Bluetooth Audio Output Options"; +const char* desc_rotary = "Rotary Control"; +const char* desc_ledvu = "Led Strip Options"; -extern const struct adac_s *dac_set[]; +extern const struct adac_s* dac_set[]; extern void equalizer_set_loudness(uint8_t); extern void register_optional_cmd(void); #define CODECS_BASE "flac|pcm|mp3|ogg" #if NO_FAAD -#define CODECS_AAC "" +#define CODECS_AAC "" #else -#define CODECS_AAC "|aac" +#define CODECS_AAC "|aac" #endif #if FFMPEG -#define CODECS_FF "|wma|alac" +#define CODECS_FF "|wma|alac" #else -#define CODECS_FF "" +#define CODECS_FF "" #endif #if DSD -#define CODECS_DSD "|dsd" +#define CODECS_DSD "|dsd" #else -#define CODECS_DSD "" +#define CODECS_DSD "" #endif -#define CODECS_MP3 "|mad|mpg" +#define CODECS_MP3 "|mad|mpg" #if !defined(MODEL_NAME) #define MODEL_NAME SqueezeLite @@ -64,13 +65,12 @@ extern void register_optional_cmd(void); #ifndef QUOTE #define QUOTE(name) #name -#define STR(macro) QUOTE(macro) +#define STR(macro) QUOTE(macro) #endif #ifndef MODEL_NAME_STRING #define MODEL_NAME_STRING STR(MODEL_NAME) #endif - #define CODECS CODECS_BASE CODECS_AAC CODECS_FF CODECS_DSD CODECS_MP3 #define NOT_OUTPUT "has input capabilities only" #define NOT_GPIO "is not a GPIO" @@ -82,428 +82,478 @@ typedef enum { SEARCHING_FOR_BT_CMD_END, FINISHING } parse_state_t; -static const char *TAG = "cmd_config"; -extern struct arg_end *getParmsEnd(struct arg_hdr * * argtable); -//bck=,ws=,do=[,mute=[:0|1][,model=TAS57xx|TAS5713|AC101|WM8978|I2S][,sda=,scl=gpio[,i2c=]] -static struct { - struct arg_str *model_name; - struct arg_int *clock; - struct arg_int *wordselect; - struct arg_int *data; - struct arg_int *mute_gpio; - struct arg_lit *mute_level; - struct arg_int *dac_sda; - struct arg_int *dac_scl; - struct arg_int *dac_i2c; - struct arg_lit *clear; - struct arg_end *end; +static const char* TAG = "cmd_config"; +extern struct arg_end* getParmsEnd(struct arg_hdr** argtable); +// bck=,ws=,do=[,mute=[:0|1][,model=TAS57xx|TAS5713|AC101|WM8978|I2S][,sda=,scl=gpio[,i2c=]] +static EXT_RAM_ATTR struct { + struct arg_str* model_name; + struct arg_int* clock; + struct arg_int* wordselect; + struct arg_int* data; + struct arg_int* mute_gpio; + struct arg_lit* mute_level; + struct arg_int* dac_sda; + struct arg_int* dac_scl; + struct arg_int* dac_i2c; + struct arg_lit* clear; + struct arg_end* end; } i2s_args; -static struct { - struct arg_str *model_config; - struct arg_end *end; +static EXT_RAM_ATTR struct { + struct arg_str* model_config; + struct arg_end* end; } known_model_args; -static struct { - struct arg_rem * rem; - struct arg_int * A; - struct arg_int * B; - struct arg_int * SW; - struct arg_lit * volume_lock; - struct arg_lit * longpress; - struct arg_lit * knobonly; - struct arg_int * timer; - struct arg_lit * clear; - struct arg_lit * raw_mode; - struct arg_end * end; +static EXT_RAM_ATTR struct { + struct arg_rem* rem; + struct arg_int* A; + struct arg_int* B; + struct arg_int* SW; + struct arg_lit* volume_lock; + struct arg_lit* longpress; + struct arg_lit* knobonly; + struct arg_int* timer; + struct arg_lit* clear; + struct arg_lit* raw_mode; + struct arg_end* end; } rotary_args; -//config_rotary_get +// config_rotary_get static struct { - struct arg_str * type; - struct arg_int * length; - struct arg_int * gpio; - struct arg_lit * clear; - struct arg_end * end; + struct arg_str* type; + struct arg_int* length; + struct arg_int* gpio; + struct arg_lit* clear; + struct arg_end* end; } ledvu_args; -static struct{ - struct arg_str *ap_name; - struct arg_str *password; - struct arg_lit *conn; +// Argument structures for different subcommands +static EXT_RAM_ATTR struct { + struct arg_str* ap_name; + struct arg_str* password; + struct arg_end* end; +} wifi_join_args; - struct arg_end *end; -} wifi_ap_args; -static struct{ - struct arg_str *sink_name; - struct arg_str *pin_code; -// struct arg_dbl *connect_timeout_delay; -// struct arg_dbl *control_delay; - struct arg_end *end; +static EXT_RAM_ATTR struct { + struct arg_str* ap_name; + struct arg_end* end; +} wifi_delete_args; +static EXT_RAM_ATTR struct { + struct arg_str* ap_name; + struct arg_str* password; + struct arg_end* end; +} wifi_add_args; +static EXT_RAM_ATTR struct { + struct arg_end* end; +} wifi_scan_args, wifi_status_args, wifi_reset_args; + +static EXT_RAM_ATTR struct { + struct arg_str* sink_name; + struct arg_str* pin_code; + // struct arg_dbl *connect_timeout_delay; + // struct arg_dbl *control_delay; + struct arg_end* end; } bt_source_args; -static struct { - struct arg_str *deviceName; -// struct arg_int *volume; - struct arg_int *bitrate; - struct arg_int *zeroConf; - struct arg_end *end; +static EXT_RAM_ATTR struct { + struct arg_str* deviceName; + // struct arg_int *volume; + struct arg_int* bitrate; + struct arg_int* zeroConf; + struct arg_end* end; } cspot_args; -static struct { - struct arg_int *clock; - struct arg_int *wordselect; - struct arg_int *data; - struct arg_lit *clear; - struct arg_end *end; +static EXT_RAM_ATTR struct { + struct arg_int* clock; + struct arg_int* wordselect; + struct arg_int* data; + struct arg_lit* clear; + struct arg_end* end; } spdif_args; static struct { - struct arg_str *jack_behavior; - struct arg_int *loudness; - struct arg_end *end; + struct arg_str* jack_behavior; + struct arg_int* loudness; + struct arg_end* end; } audio_args; static struct { - struct arg_str * output_device; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" - struct arg_str * name;// " -n \t\tSet the player name\n" - struct arg_str * server; // -s [:]\tConnect to specified server, otherwise uses autodiscovery to find server\n" - struct arg_str * buffers;// " -b :\tSpecify internal Stream and Output buffer sizes in Kbytes\n" - struct arg_str * codecs;// " -c ,\tRestrict codecs to those specified, otherwise load all available codecs; known codecs: " CODECS "\n" - struct arg_int * timeout;// " -C \t\tClose output device when idle after timeout seconds, default is to keep it open while player is 'on'\n" - struct arg_str * log_level; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" - // struct arg_str * log_level_all; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" - // struct arg_str * log_level_slimproto; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" - // struct arg_str * log_level_stream; - // struct arg_str * log_level_decode; - // struct arg_str * log_level_output; - #if IR - struct arg_str * log_level_ir; - #endif - // " -e ,\tExplicitly exclude native support of one or more codecs; known codecs: " CODECS "\n" - // " -f \t\tWrite debug to logfile\n" - // #if IR - // " -i []\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n" - // #endif - struct arg_str * mac_addr; // " -m \t\tSet mac address, format: ab:cd:ef:12:34:56\n" - struct arg_str * model_name;// " -M \tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n" - struct arg_lit * header_format;// " -W\t\t\tRead wave and aiff format from header, ignore server parameters\n" - struct arg_str * rates; // " -r [:]\tSample rates supported, allows output to be off when squeezelite is started; rates = |-|,,; delay = optional delay switching rates in ms\n" - #if RESAMPLE - struct arg_lit * resample; - struct arg_str * resample_parms; //" -R -u [params]\tResample, params = ::::::,\n" - #endif - #if RESAMPLE16 - struct arg_lit * resample; - struct arg_str * resample_parms; //" -R -u [params]\tResample, params = (b|l|m)[:i],\n" - // " \t\t\t b = basic linear interpolation, l = 13 taps, m = 21 taps, i = interpolate filter coefficients\n" - #endif - struct arg_int * rate;// " -Z \t\tReport rate to server in helo as the maximum sample rate we can support\n" - struct arg_end *end; + struct arg_str* output_device; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" + struct arg_str* name; // " -n \t\tSet the player name\n" + struct arg_str* server; // -s [:]\tConnect to specified server, otherwise uses autodiscovery to find server\n" + struct arg_str* buffers; // " -b :\tSpecify internal Stream and Output buffer sizes in Kbytes\n" + struct arg_str* codecs; // " -c ,\tRestrict codecs to those specified, otherwise load all available codecs; known + //codecs: " CODECS "\n" + struct arg_int* timeout; // " -C \t\tClose output device when idle after timeout seconds, default is to keep it open while + //player is 'on'\n" + struct arg_str* log_level; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" +// struct arg_str * log_level_all; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" +// struct arg_str * log_level_slimproto; // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: +// info|debug|sdebug\n" struct arg_str * log_level_stream; struct arg_str * log_level_decode; struct arg_str * log_level_output; +#if IR + struct arg_str* log_level_ir; +#endif + // " -e ,\tExplicitly exclude native support of one or more codecs; known codecs: " CODECS "\n" + // " -f \t\tWrite debug to logfile\n" + // #if IR + // " -i []\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n" + // #endif + struct arg_str* mac_addr; // " -m \t\tSet mac address, format: ab:cd:ef:12:34:56\n" + struct arg_str* + model_name; // " -M \tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n" + struct arg_lit* header_format; // " -W\t\t\tRead wave and aiff format from header, ignore server parameters\n" + struct arg_str* rates; // " -r [:]\tSample rates supported, allows output to be off when squeezelite is started; rates + //= |-|,,; delay = optional delay switching rates in ms\n" +#if RESAMPLE + struct arg_lit* resample; + struct arg_str* resample_parms; //" -R -u [params]\tResample, params = + //::::::,\n" +#endif +#if RESAMPLE16 + struct arg_lit* resample; + struct arg_str* resample_parms; //" -R -u [params]\tResample, params = (b|l|m)[:i],\n" +// " \t\t\t b = basic linear interpolation, l = 13 taps, m = 21 taps, i = interpolate filter coefficients\n" +#endif + struct arg_int* rate; // " -Z \t\tReport rate to server in helo as the maximum sample rate we can support\n" + struct arg_end* end; } squeezelite_args; -int is_gpio(struct arg_int * gpio, FILE * f, int * gpio_out, bool mandatory, bool output){ - int res = 0; - const char * name = gpio->hdr.longopts?gpio->hdr.longopts:gpio->hdr.glossary; - *gpio_out=-1; - int t_gpio=gpio->ival[0]; - if(gpio->count==0){ - if(mandatory){ - fprintf(f,"Missing: %s\n", name); - res++; - } - } else if((output && !GPIO_IS_VALID_OUTPUT_GPIO(t_gpio)) || (!GPIO_IS_VALID_GPIO(t_gpio))){ - fprintf(f,"Invalid %s gpio: [%d] %s\n",name, t_gpio, GPIO_IS_VALID_GPIO(t_gpio)?NOT_OUTPUT:NOT_GPIO ); - res++; - } - else{ - *gpio_out = t_gpio; - } - return res; +int is_gpio(struct arg_int* gpio, FILE* f, int* gpio_out, bool mandatory, bool output) { + int res = 0; + const char* name = gpio->hdr.longopts ? gpio->hdr.longopts : gpio->hdr.glossary; + *gpio_out = -1; + int t_gpio = gpio->ival[0]; + if (gpio->count == 0) { + if (mandatory) { + fprintf(f, "Missing: %s\n", name); + res++; + } + } else if ((output && !GPIO_IS_VALID_OUTPUT_GPIO(t_gpio)) || (!GPIO_IS_VALID_GPIO(t_gpio))) { + fprintf(f, "Invalid %s gpio: [%d] %s\n", name, t_gpio, GPIO_IS_VALID_GPIO(t_gpio) ? NOT_OUTPUT : NOT_GPIO); + res++; + } else { + *gpio_out = t_gpio; + } + return res; } -int is_output_gpio(struct arg_int * gpio, FILE * f, int * gpio_out, bool mandatory){ - return is_gpio(gpio,f,gpio_out,mandatory,true); +int is_output_gpio(struct arg_int* gpio, FILE* f, int* gpio_out, bool mandatory) { return is_gpio(gpio, f, gpio_out, mandatory, true); } +int check_missing_parm(struct arg_int* int_parm, FILE* f) { + int res = 0; + const char* name = int_parm->hdr.longopts ? int_parm->hdr.longopts : int_parm->hdr.glossary; + if (int_parm->count == 0) { + fprintf(f, "Missing: %s\n", name); + res++; + } + return res; } -int check_missing_parm(struct arg_int * int_parm, FILE * f){ - int res=0; - const char * name = int_parm->hdr.longopts?int_parm->hdr.longopts:int_parm->hdr.glossary; - if(int_parm->count==0){ - fprintf(f,"Missing: %s\n", name); - res++; - } - return res; -} -char * strip_bt_name(char * opt_str) -{ - if(!opt_str || strlen(opt_str)==0){ - ESP_LOGW(TAG,"strip_bt_name: opt_str is NULL"); - return NULL; - } - char *result = malloc_init_external(strlen(opt_str)+1); - char *str = strdup_psram(opt_str); - const char * output_marker=" -o"; - - if(!result ){ - ESP_LOGE(TAG,"Error allocating memory for result."); +char* strip_bt_name(char* opt_str) { + if (!opt_str || strlen(opt_str) == 0) { + ESP_LOGW(TAG, "strip_bt_name: opt_str is NULL"); + return NULL; + } + char* result = malloc_init_external(strlen(opt_str) + 1); + char* str = strdup_psram(opt_str); + const char* output_marker = " -o"; + + if (!result) { + ESP_LOGE(TAG, "Error allocating memory for result."); return opt_str; } - if(!str){ - ESP_LOGE(TAG,"Error duplicating command line string."); + if (!str) { + ESP_LOGE(TAG, "Error duplicating command line string."); return opt_str; - } - bool quoted=false; + } + bool quoted = false; parse_state_t state = SEARCHING_FOR_BT; - char *start = strstr(str, output_marker); - if (start) - { - ESP_LOGV(TAG,"Found output option : %s\n",start); - start+=strlen(output_marker); + char* start = strstr(str, output_marker); + if (start) { + ESP_LOGV(TAG, "Found output option : %s\n", start); + start += strlen(output_marker); strncpy(result, str, (size_t)(start - str)); - char * pch=strtok(start," "); - while(pch){ - ESP_LOGV(TAG,"Current output: %s\n[%s]",result,pch); - switch (state) - { - case SEARCHING_FOR_BT: - if (strcasestr(pch, "BT") ) - { - state = SEARCHING_FOR_NAME; - quoted=strcasestr(pch, "BT")!=NULL; - ESP_LOGV(TAG," - fount BT Start %s", quoted?"quoted":""); - } - else - { - ESP_LOGV(TAG," - Searching for BT, Ignoring"); - } - strcat(result, " "); - strcat(result, pch); - break; - case SEARCHING_FOR_NAME: - if (strcasestr(pch, "name") || strcasestr(pch, "n")) - { - ESP_LOGV(TAG," - Found name tag"); - state = SEARCHING_FOR_NAME_START; - } - else - { - strcat(result, " "); - strcat(result, pch); - ESP_LOGV(TAG," - Searching for name - added ");; - } - break; - case SEARCHING_FOR_NAME_START: - ESP_LOGV(TAG," - Name start"); - state = SEARCHING_FOR_NAME_END; + char* pch = strtok(start, " "); + while (pch) { + ESP_LOGV(TAG, "Current output: %s\n[%s]", result, pch); + switch (state) { + case SEARCHING_FOR_BT: + if (strcasestr(pch, "BT")) { + state = SEARCHING_FOR_NAME; + quoted = strcasestr(pch, "BT") != NULL; + ESP_LOGV(TAG, " - fount BT Start %s", quoted ? "quoted" : ""); + } else { + ESP_LOGV(TAG, " - Searching for BT, Ignoring"); + } + strcat(result, " "); + strcat(result, pch); break; - case SEARCHING_FOR_NAME_END: - if (strcasestr(pch, "\"")){ - ESP_LOGV(TAG," - got quoted string"); - state = FINISHING; - } - else if(pch[0]== '-'){ - strcat(result, " "); - strcat(result, pch); - ESP_LOGV(TAG," - got parameter marker"); - state = quoted?SEARCHING_FOR_BT_CMD_END:FINISHING; - } - else { - ESP_LOGV(TAG," - name continued"); - } - break; - case SEARCHING_FOR_BT_CMD_END: - ESP_LOGV(TAG," - looking for quoted BT cmd end"); - if (strcasestr(pch, "\"")){ - ESP_LOGV(TAG," - got quote termination"); - state = FINISHING; - } + case SEARCHING_FOR_NAME: + if (strcasestr(pch, "name") || strcasestr(pch, "n")) { + ESP_LOGV(TAG, " - Found name tag"); + state = SEARCHING_FOR_NAME_START; + } else { strcat(result, " "); strcat(result, pch); - break; - case FINISHING: + ESP_LOGV(TAG, " - Searching for name - added "); + ; + } + break; + case SEARCHING_FOR_NAME_START: + ESP_LOGV(TAG, " - Name start"); + state = SEARCHING_FOR_NAME_END; + break; + case SEARCHING_FOR_NAME_END: + if (strcasestr(pch, "\"")) { + ESP_LOGV(TAG, " - got quoted string"); + state = FINISHING; + } else if (pch[0] == '-') { strcat(result, " "); strcat(result, pch); - break; - default: - - break; + ESP_LOGV(TAG, " - got parameter marker"); + state = quoted ? SEARCHING_FOR_BT_CMD_END : FINISHING; + } else { + ESP_LOGV(TAG, " - name continued"); + } + break; + case SEARCHING_FOR_BT_CMD_END: + ESP_LOGV(TAG, " - looking for quoted BT cmd end"); + if (strcasestr(pch, "\"")) { + ESP_LOGV(TAG, " - got quote termination"); + state = FINISHING; + } + strcat(result, " "); + strcat(result, pch); + break; + case FINISHING: + strcat(result, " "); + strcat(result, pch); + break; + default: + + break; } pch = strtok(NULL, " "); - ESP_LOGV(TAG,"\n"); + ESP_LOGV(TAG, "\n"); } - } - else - { - ESP_LOGE(TAG,"output option not found in %s\n",str); - strcpy(result,str); + } else { + ESP_LOGE(TAG, "output option not found in %s\n", str); + strcpy(result, str); } - ESP_LOGV(TAG,"Result commmand : %s\n", result); + ESP_LOGV(TAG, "Result commmand : %s\n", result); free(str); return result; } -static int do_bt_source_cmd(int argc, char **argv){ - esp_err_t err=ESP_OK; - int nerrors = arg_parse(argc, argv,(void **)&bt_source_args); - char *buf = NULL; - size_t buf_size = 0; -// char value[100] ={0}; - FILE *f = system_open_memstream(argv[0],&buf, &buf_size); - if (f == NULL) { - return 1; - } - if(nerrors >0){ - arg_print_errors(f,bt_source_args.end,desc_bt_source); - fclose(f); - return 1; - } +static int do_bt_source_cmd(int argc, char** argv) { + esp_err_t err = ESP_OK; + int nerrors = arg_parse(argc, argv, (void**)&bt_source_args); + char* buf = NULL; + size_t buf_size = 0; + // char value[100] ={0}; + FILE* f = system_open_memstream(argv[0], &buf, &buf_size); + if (f == NULL) { + return 1; + } + if (nerrors > 0) { + arg_print_errors(f, bt_source_args.end, desc_bt_source); + fclose(f); + return 1; + } - if(bt_source_args.sink_name->count >0){ - // err = config_set_value(NVS_TYPE_STR, "a2dp_sink_name", bt_source_args.sink_name->sval[0]); - // if(err!=ESP_OK){ + if (bt_source_args.sink_name->count > 0) { + // err = config_set_value(NVS_TYPE_STR, "a2dp_sink_name", bt_source_args.sink_name->sval[0]); + // if(err!=ESP_OK){ // nerrors++; // fprintf(f,"Error setting Bluetooth audio device name %s. %s\n",bt_source_args.sink_name->sval[0], esp_err_to_name(err)); // } // else { // fprintf(f,"Bluetooth audio device name changed to %s\n",bt_source_args.sink_name->sval[0]); - // } - - // char * squeezelite_cmd = config_alloc_get_default(NVS_TYPE_STR, "autoexec1", NULL, 0); - // if( squeezelite_cmd && strstr(squeezelite_cmd," -o ") ){ - // char * new_cmd = strip_bt_name(squeezelite_cmd); - // if(strcmp(new_cmd,squeezelite_cmd)!=0){ - // fprintf(f,"Replacing old squeezelite command [%s] with [%s].\n",squeezelite_cmd,new_cmd); - // config_set_value(NVS_TYPE_STR, "autoexec1", new_cmd); - // if(err!=ESP_OK){ - // nerrors++; - // fprintf(f,"Error updating squeezelite command line options . %s\n", esp_err_to_name(err)); - // } - // } - // free(squeezelite_cmd); - // free(new_cmd); - // } - // TODO: Add support for the commented code + // } - } - if(bt_source_args.pin_code->count >0){ - const char * v=bt_source_args.pin_code->sval[0]; - bool bInvalid=false; - for(int i=0;i'9'){ - bInvalid=true; - } - } - if(bInvalid || strlen(bt_source_args.pin_code->sval[0])>16 || strlen(bt_source_args.pin_code->sval[0])<4){ - nerrors++; - fprintf(f,"Pin code %s invalid. Should be numbers only with length between 4 and 16 characters. \n",bt_source_args.pin_code->sval[0]); - } - else { - // err = config_set_value(NVS_TYPE_STR, "a2dp_spin", bt_source_args.pin_code->sval[0]); - // if(err!=ESP_OK){ - // nerrors++; - // fprintf(f,"Error setting Bluetooth source pin to %s. %s\n",bt_source_args.pin_code->sval[0], esp_err_to_name(err)); - // } - // else { - // fprintf(f,"Bluetooth source pin changed to %s\n",bt_source_args.pin_code->sval[0]); - // } - // TODO: Add support for the commented code - } - } - // if(bt_source_args.connect_timeout_delay->count >0){ - - // snprintf(value,sizeof(value),"%d",(int)(bt_source_args.connect_timeout_delay->dval[0]*1000.0)); - // if(bt_source_args.connect_timeout_delay->dval[0] <0.5 || bt_source_args.connect_timeout_delay->dval[0] >5.0){ - // nerrors++; - // fprintf(f,"Invalid connection timeout %0.0f (%s milliseconds). Value must be between 0.5 sec and 5 sec.\n", bt_source_args.connect_timeout_delay->dval[0], value ); - // } - // else { - // err = config_set_value(NVS_TYPE_STR, "a2dp_ctmt", value); - // if(err!=ESP_OK){ - // nerrors++; - // fprintf(f,"Error setting connection timeout %0.0f sec (%s milliseconds). %s\n", bt_source_args.connect_timeout_delay->dval[0],value, esp_err_to_name(err)); - // } - // else { - // fprintf(f,"Connection timeout changed to %0.0f sec (%s milliseconds)\n",bt_source_args.connect_timeout_delay->dval[0],value); - // } - // } - // } - - // if(bt_source_args.control_delay->count >0){ - // snprintf(value,sizeof(value),"%d",(int)(bt_source_args.control_delay->dval[0]*1000.0)); - // if(bt_source_args.control_delay->dval[0] <0.1 || bt_source_args.control_delay->dval[0] >2.0){ - // nerrors++; - // fprintf(f,"Invalid control delay %0.0f (%s milliseconds). Value must be between 0.1s and 2s.\n", bt_source_args.control_delay->dval[0], value ); - // } - // else { - // err = config_set_value(NVS_TYPE_STR, "a2dp_ctrld", value); - // if(err!=ESP_OK){ - // nerrors++; - // fprintf(f,"Error setting control delay to %0.0f sec (%s milliseconds). %s\n",bt_source_args.control_delay->dval[0],value, esp_err_to_name(err)); - // } - // else { - // fprintf(f,"Control delay changed to %0.0f sec (%s milliseconds)\n",bt_source_args.control_delay->dval[0],value); - // } - // } - // } - - if(!nerrors ){ - fprintf(f,"Done.\n"); - } - fflush (f); - cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); - fclose(f); - FREE_AND_NULL(buf); - return (nerrors==0 && err==ESP_OK)?0:1; - -} -static void do_wifi_ops(int argc, char **argv){ - esp_err_t err=ESP_OK; - int nerrors = arg_parse(argc, argv,(void **)&wifi_ap_args); - if(nerrors >0){ - return 1; - } - if(wifi_ap_args.conn->count >0){ - network_async_connect(wifi_ap_args.ap_name->sval[0],wifi_ap_args.password->sval[0]); - } - - -} -static int do_audio_cmd(int argc, char **argv){ - esp_err_t err=ESP_OK; - int nerrors = arg_parse(argc, argv,(void **)&audio_args); - char *buf = NULL; - size_t buf_size = 0; - FILE *f = system_open_memstream(argv[0],&buf, &buf_size); - if (f == NULL) { - return 1; - } - if(nerrors >0){ - arg_print_errors(f,audio_args.end,desc_audio); - fclose(f); - return 1; - } - - err = ESP_OK; // suppress any error code that might have happened in a previous step - - if(audio_args.loudness->count>0){ - char p[4]={0}; - int loudness_val = audio_args.loudness->ival[0]; - if( loudness_val < 0 || loudness_val>10){ - nerrors++; - fprintf(f,"Invalid loudness value %d. Valid values are between 0 and 10.\n",loudness_val); - } - // it's not necessary to store loudness in NVS as set_loudness does it, but it does not hurt - else { - itoa(loudness_val,p,10); - // err = config_set_value(NVS_TYPE_STR, "loudness", p); - // TODO: Add support for the commented code - } - if(err!=ESP_OK){ - nerrors++; - fprintf(f,"Error setting Loudness value %s. %s\n",p, esp_err_to_name(err)); + // char * squeezelite_cmd = config_alloc_get_default(NVS_TYPE_STR, "autoexec1", NULL, 0); + // if( squeezelite_cmd && strstr(squeezelite_cmd," -o ") ){ + // char * new_cmd = strip_bt_name(squeezelite_cmd); + // if(strcmp(new_cmd,squeezelite_cmd)!=0){ + // fprintf(f,"Replacing old squeezelite command [%s] with [%s].\n",squeezelite_cmd,new_cmd); + // config_set_value(NVS_TYPE_STR, "autoexec1", new_cmd); + // if(err!=ESP_OK){ + // nerrors++; + // fprintf(f,"Error updating squeezelite command line options . %s\n", esp_err_to_name(err)); + // } + // } + // free(squeezelite_cmd); + // free(new_cmd); + // } + // TODO: Add support for the commented code + } + if (bt_source_args.pin_code->count > 0) { + const char* v = bt_source_args.pin_code->sval[0]; + bool bInvalid = false; + for (int i = 0; i < strlen(v) && !bInvalid; i++) { + if (v[i] < '0' || v[i] > '9') { + bInvalid = true; + } } - else { - fprintf(f,"Loudness changed to %s\n",p); - equalizer_set_loudness(loudness_val); - } + if (bInvalid || strlen(bt_source_args.pin_code->sval[0]) > 16 || strlen(bt_source_args.pin_code->sval[0]) < 4) { + nerrors++; + fprintf(f, "Pin code %s invalid. Should be numbers only with length between 4 and 16 characters. \n", bt_source_args.pin_code->sval[0]); + } else { + // err = config_set_value(NVS_TYPE_STR, "a2dp_spin", bt_source_args.pin_code->sval[0]); + // if(err!=ESP_OK){ + // nerrors++; + // fprintf(f,"Error setting Bluetooth source pin to %s. %s\n",bt_source_args.pin_code->sval[0], esp_err_to_name(err)); + // } + // else { + // fprintf(f,"Bluetooth source pin changed to %s\n",bt_source_args.pin_code->sval[0]); + // } + // TODO: Add support for the commented code + } + } + // if(bt_source_args.connect_timeout_delay->count >0){ + + // snprintf(value,sizeof(value),"%d",(int)(bt_source_args.connect_timeout_delay->dval[0]*1000.0)); + // if(bt_source_args.connect_timeout_delay->dval[0] <0.5 || bt_source_args.connect_timeout_delay->dval[0] >5.0){ + // nerrors++; + // fprintf(f,"Invalid connection timeout %0.0f (%s milliseconds). Value must be between 0.5 sec and 5 sec.\n", + // bt_source_args.connect_timeout_delay->dval[0], value ); + // } + // else { + // err = config_set_value(NVS_TYPE_STR, "a2dp_ctmt", value); + // if(err!=ESP_OK){ + // nerrors++; + // fprintf(f,"Error setting connection timeout %0.0f sec (%s milliseconds). %s\n", bt_source_args.connect_timeout_delay->dval[0],value, + // esp_err_to_name(err)); + // } + // else { + // fprintf(f,"Connection timeout changed to %0.0f sec (%s milliseconds)\n",bt_source_args.connect_timeout_delay->dval[0],value); + // } + // } + // } + + // if(bt_source_args.control_delay->count >0){ + // snprintf(value,sizeof(value),"%d",(int)(bt_source_args.control_delay->dval[0]*1000.0)); + // if(bt_source_args.control_delay->dval[0] <0.1 || bt_source_args.control_delay->dval[0] >2.0){ + // nerrors++; + // fprintf(f,"Invalid control delay %0.0f (%s milliseconds). Value must be between 0.1s and 2s.\n", bt_source_args.control_delay->dval[0], + // value ); + // } + // else { + // err = config_set_value(NVS_TYPE_STR, "a2dp_ctrld", value); + // if(err!=ESP_OK){ + // nerrors++; + // fprintf(f,"Error setting control delay to %0.0f sec (%s milliseconds). %s\n",bt_source_args.control_delay->dval[0],value, + // esp_err_to_name(err)); + // } + // else { + // fprintf(f,"Control delay changed to %0.0f sec (%s milliseconds)\n",bt_source_args.control_delay->dval[0],value); + // } + // } + // } + + if (!nerrors) { + fprintf(f, "Done.\n"); + } + fflush(f); + cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); + fclose(f); + FREE_AND_NULL(buf); + return (nerrors == 0 && err == ESP_OK) ? 0 : 1; +} +static int do_wifi_join(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_join_args); + if (nerrors > 0) { + return 1; } - if(audio_args.jack_behavior->count>0){ + network_async_connect(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); + return 0; +} +static int do_wifi_add(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_join_args); + if (nerrors > 0) { + return 1; + } + + network_async_add(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); + return 0; +} +static int do_wifi_delete(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_delete_args); + if (nerrors > 0) { + return 1; + } + network_async_delete_connection(wifi_delete_args.ap_name->sval[0]); + return 0; +} +// Function to handle WiFi scan +static int do_wifi_scan(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**) &wifi_scan_args); + if (nerrors > 0) { + arg_print_errors(stderr, wifi_scan_args.end, argv[0]); + return 1; + } + network_async_scan(); + return 0; +} + +// Function to handle WiFi status +static int do_wifi_status(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**) &wifi_status_args); + if (nerrors > 0) { + arg_print_errors(stderr, wifi_status_args.end, argv[0]); + return 1; + } + network_wifi_get_status(); + return 0; +} + +// Function to handle WiFi reset +static int do_wifi_reset(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**) &wifi_reset_args); + if (nerrors > 0) { + arg_print_errors(stderr, wifi_reset_args.end, argv[0]); + return 1; + } + // Add implementation for resetting WiFi settings + // ... + return 0; +} + + +static int do_audio_cmd(int argc, char** argv) { + esp_err_t err = ESP_OK; + int nerrors = arg_parse(argc, argv, (void**)&audio_args); + char* buf = NULL; + size_t buf_size = 0; + FILE* f = system_open_memstream(argv[0], &buf, &buf_size); + if (f == NULL) { + return 1; + } + if (nerrors > 0) { + arg_print_errors(f, audio_args.end, desc_audio); + fclose(f); + return 1; + } + + err = ESP_OK; // suppress any error code that might have happened in a previous step + + if (audio_args.loudness->count > 0) { + char p[4] = {0}; + int loudness_val = audio_args.loudness->ival[0]; + if (loudness_val < 0 || loudness_val > 10) { + nerrors++; + fprintf(f, "Invalid loudness value %d. Valid values are between 0 and 10.\n", loudness_val); + } + // it's not necessary to store loudness in NVS as set_loudness does it, but it does not hurt + else { + itoa(loudness_val, p, 10); + // err = config_set_value(NVS_TYPE_STR, "loudness", p); + // TODO: Add support for the commented code + } + if (err != ESP_OK) { + nerrors++; + fprintf(f, "Error setting Loudness value %s. %s\n", p, esp_err_to_name(err)); + } else { + fprintf(f, "Loudness changed to %s\n", p); + equalizer_set_loudness(loudness_val); + } + } + + if (audio_args.jack_behavior->count > 0) { err = ESP_OK; // suppress any error code that might have happened in a previous step - // TODO: Add support for the commented code + // TODO: Add support for the commented code // if(strcasecmp(audio_args.jack_behavior->sval[0],"Headphones")==0){ // err = config_set_value(NVS_TYPE_STR, "jack_mutes_amp", "y"); // } @@ -515,23 +565,22 @@ static int do_audio_cmd(int argc, char **argv){ // fprintf(f,"Unknown Audio Jack Behavior %s.\n",audio_args.jack_behavior->sval[0]); // } - if(err!=ESP_OK){ + if (err != ESP_OK) { nerrors++; - fprintf(f,"Error setting Audio Jack Behavior %s. %s\n",audio_args.jack_behavior->sval[0], esp_err_to_name(err)); + fprintf(f, "Error setting Audio Jack Behavior %s. %s\n", audio_args.jack_behavior->sval[0], esp_err_to_name(err)); + } else { + fprintf(f, "Audio Jack Behavior changed to %s\n", audio_args.jack_behavior->sval[0]); } - else { - fprintf(f,"Audio Jack Behavior changed to %s\n",audio_args.jack_behavior->sval[0]); - } } - if(!nerrors ){ - fprintf(f,"Done.\n"); - } - fflush (f); - cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); - fclose(f); - FREE_AND_NULL(buf); - return (nerrors==0 && err==ESP_OK)?0:1; + if (!nerrors) { + fprintf(f, "Done.\n"); + } + fflush(f); + cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); + fclose(f); + FREE_AND_NULL(buf); + return (nerrors == 0 && err == ESP_OK) ? 0 : 1; } // static int do_spdif_cmd(int argc, char **argv){ // i2s_platform_config_t i2s_dac_pin = { @@ -609,7 +658,6 @@ static int do_audio_cmd(int argc, char **argv){ // nerrors+=is_gpio(rotary_args.B, f, &rotary.B, true,false); // nerrors+=is_gpio(rotary_args.SW, f, &rotary.SW,false,false); - // if(rotary_args.knobonly->count>0 && (rotary_args.volume_lock->count>0 || rotary_args.longpress->count>0)){ // fprintf(f,"error: Cannot use volume lock or longpress option when knob only option selected\n"); // nerrors++; @@ -635,7 +683,7 @@ static int do_audio_cmd(int argc, char **argv){ // if(nerrors>0){ // fprintf(f,"error: Unable to store raw mode parameter.\n"); // } -// } +// } // if(!nerrors ){ // fprintf(f,"Done.\n"); // } @@ -645,72 +693,72 @@ static int do_audio_cmd(int argc, char **argv){ // FREE_AND_NULL(buf); // return (nerrors==0 && err==ESP_OK)?0:1; // } -static int is_valid_gpio_number(int gpio, const char * name, FILE *f, bool mandatory, struct arg_int * target, bool output){ - bool invalid = (!GPIO_IS_VALID_GPIO(gpio) ||(output && !GPIO_IS_VALID_OUTPUT_GPIO(gpio))) ; - if(invalid && mandatory && gpio!=-1){ - fprintf(f,"Error: Invalid mandatory gpio %d for %s\n",gpio,name); - return 1; - } - if(target && !invalid){ - target->count=1; - target->ival[0]=gpio; - } - return 0; +static int is_valid_gpio_number(int gpio, const char* name, FILE* f, bool mandatory, struct arg_int* target, bool output) { + bool invalid = (!GPIO_IS_VALID_GPIO(gpio) || (output && !GPIO_IS_VALID_OUTPUT_GPIO(gpio))); + if (invalid && mandatory && gpio != -1) { + fprintf(f, "Error: Invalid mandatory gpio %d for %s\n", gpio, name); + return 1; + } + if (target && !invalid) { + target->count = 1; + target->ival[0] = gpio; + } + return 0; } #ifdef CONFIG_CSPOT_SINK -static int do_cspot_config(int argc, char **argv){ - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&cspot_args); +static int do_cspot_config(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&cspot_args); if (nerrors != 0) { return 1; } - char *buf = NULL; - size_t buf_size = 0; - FILE *f = system_open_memstream(argv[0],&buf, &buf_size); - if (f == NULL) { - return 1; - } + char* buf = NULL; + size_t buf_size = 0; + FILE* f = system_open_memstream(argv[0], &buf, &buf_size); + if (f == NULL) { + return 1; + } - // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); - // if(!cspot_config){ - // nerrors++; - // fprintf(f,"error: Unable to get default cspot config.\n"); - // } - // if(cspot_args.deviceName->count>0){ - // cjson_update_string(&cspot_config,cspot_args.deviceName->hdr.longopts,cspot_args.deviceName->sval[0]); - // } - // if(cspot_args.bitrate->count>0){ - // cjson_update_number(&cspot_config,cspot_args.bitrate->hdr.longopts,cspot_args.bitrate->ival[0]); - // } + // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); + // if(!cspot_config){ + // nerrors++; + // fprintf(f,"error: Unable to get default cspot config.\n"); + // } + // if(cspot_args.deviceName->count>0){ + // cjson_update_string(&cspot_config,cspot_args.deviceName->hdr.longopts,cspot_args.deviceName->sval[0]); + // } + // if(cspot_args.bitrate->count>0){ + // cjson_update_number(&cspot_config,cspot_args.bitrate->hdr.longopts,cspot_args.bitrate->ival[0]); + // } // if(cspot_args.zeroConf->count>0){ - // cjson_update_number(&cspot_config,cspot_args.zeroConf->hdr.longopts,cspot_args.zeroConf->ival[0]); - // } - - // if(!nerrors ){ - // fprintf(f,"Storing cspot parameters.\n"); - // nerrors+=(config_set_cjson_str_and_free("cspot_config",cspot_config) !=ESP_OK); - // } - // if(nerrors==0 ){ - // if(cspot_args.deviceName->count>0){ - // fprintf(f,"Device name changed to %s\n",cspot_args.deviceName->sval[0]); - // } - // if(cspot_args.bitrate->count>0){ - // fprintf(f,"Bitrate changed to %u\n",cspot_args.bitrate->ival[0]); - // } + // cjson_update_number(&cspot_config,cspot_args.zeroConf->hdr.longopts,cspot_args.zeroConf->ival[0]); + // } + + // if(!nerrors ){ + // fprintf(f,"Storing cspot parameters.\n"); + // nerrors+=(config_set_cjson_str_and_free("cspot_config",cspot_config) !=ESP_OK); + // } + // if(nerrors==0 ){ + // if(cspot_args.deviceName->count>0){ + // fprintf(f,"Device name changed to %s\n",cspot_args.deviceName->sval[0]); + // } + // if(cspot_args.bitrate->count>0){ + // fprintf(f,"Bitrate changed to %u\n",cspot_args.bitrate->ival[0]); + // } // if(cspot_args.zeroConf->count>0){ - // fprintf(f,"ZeroConf changed to %u\n",cspot_args.zeroConf->ival[0]); - // } - // } - // if(!nerrors ){ - // fprintf(f,"Done.\n"); - // } - // TODO: Add support for the commented code - fflush (f); - cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); - fclose(f); - FREE_AND_NULL(buf); - return nerrors; + // fprintf(f,"ZeroConf changed to %u\n",cspot_args.zeroConf->ival[0]); + // } + // } + // if(!nerrors ){ + // fprintf(f,"Done.\n"); + // } + // TODO: Add support for the commented code + fflush(f); + cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); + fclose(f); + FREE_AND_NULL(buf); + return nerrors; } #endif @@ -737,7 +785,7 @@ static int do_cspot_config(int argc, char **argv){ // } // nerrors+=is_output_gpio(ledvu_args.gpio, f, &ledvu.gpio, true); - + // if(ledvu_args.length->count==0 || ledvu_args.length->ival[0]<1 || ledvu_args.length->ival[0]>255){ // fprintf(f,"error: strip length must be greater than 0 and no more than 255\n"); // nerrors++; @@ -745,7 +793,7 @@ static int do_cspot_config(int argc, char **argv){ // else { // ledvu.length = ledvu_args.length->count>0?ledvu_args.length->ival[0]:0; // } - + // if(!nerrors ){ // fprintf(f,"Storing ledvu parameters.\n"); // nerrors+=(config_ledvu_set(&ledvu )!=ESP_OK); @@ -828,69 +876,69 @@ static int do_cspot_config(int argc, char **argv){ // return (nerrors==0 && err==ESP_OK)?0:1; // } -cJSON * example_cb(){ - cJSON * values = cJSON_CreateObject(); -// int i2c_port; -// const i2c_config_t * i2c= config_i2c_get(&i2c_port); -// if(i2c->scl_io_num>0) { -// cJSON_AddNumberToObject(values,"scl",i2c->scl_io_num); -// } -// if(i2c->sda_io_num>0) { -// cJSON_AddNumberToObject(values,"sda",i2c->sda_io_num); -// } -// if(i2c->master.clk_speed>0) { -// cJSON_AddNumberToObject(values,"freq",i2c->master.clk_speed); -// } -// if(i2c_port>0) { -// cJSON_AddNumberToObject(values,"port",i2c_port); -// } - return values; +cJSON* example_cb() { + cJSON* values = cJSON_CreateObject(); + // int i2c_port; + // const i2c_config_t * i2c= config_i2c_get(&i2c_port); + // if(i2c->scl_io_num>0) { + // cJSON_AddNumberToObject(values,"scl",i2c->scl_io_num); + // } + // if(i2c->sda_io_num>0) { + // cJSON_AddNumberToObject(values,"sda",i2c->sda_io_num); + // } + // if(i2c->master.clk_speed>0) { + // cJSON_AddNumberToObject(values,"freq",i2c->master.clk_speed); + // } + // if(i2c_port>0) { + // cJSON_AddNumberToObject(values,"port",i2c_port); + // } + return values; } -cJSON * known_model_cb(){ - cJSON * values = cJSON_CreateObject(); - // if(!values){ - // ESP_LOGE(TAG,"known_model_cb: Failed to create JSON object"); - // return NULL; - // } - // char * name = config_alloc_get_default(NVS_TYPE_STR,known_model_args.model_config->hdr.longopts,"",0); - // if(!name){ - // ESP_LOGE(TAG,"Failed to get board model from nvs key %s ",known_model_args.model_config->hdr.longopts); - // } - // else { - // cJSON_AddStringToObject(values,known_model_args.model_config->hdr.longopts,name); - // } - // TODO: Add support for the commented code - return values; +cJSON* known_model_cb() { + cJSON* values = cJSON_CreateObject(); + // if(!values){ + // ESP_LOGE(TAG,"known_model_cb: Failed to create JSON object"); + // return NULL; + // } + // char * name = config_alloc_get_default(NVS_TYPE_STR,known_model_args.model_config->hdr.longopts,"",0); + // if(!name){ + // ESP_LOGE(TAG,"Failed to get board model from nvs key %s ",known_model_args.model_config->hdr.longopts); + // } + // else { + // cJSON_AddStringToObject(values,known_model_args.model_config->hdr.longopts,name); + // } + // TODO: Add support for the commented code + return values; } #ifdef CONFIG_CSPOT_SINK -cJSON * cspot_cb(){ - cJSON * values = cJSON_CreateObject(); - if(!values){ - ESP_LOGE(TAG,"cspot_cb: Failed to create JSON object"); - return NULL; - } - // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); - // if(!cspot_config){ - // ESP_LOGE(TAG,"cspot_cb: Failed to get cspot config"); - // return NULL; - // } - // cJSON * cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.deviceName->hdr.longopts); - // if(cspot_values){ - // cJSON_AddStringToObject(values,cspot_args.deviceName->hdr.longopts,cJSON_GetStringValue(cspot_values)); - // } - // cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.bitrate->hdr.longopts); - // if(cspot_values){ - // cJSON_AddNumberToObject(values,cspot_args.bitrate->hdr.longopts,cJSON_GetNumberValue(cspot_values)); - // } +cJSON* cspot_cb() { + cJSON* values = cJSON_CreateObject(); + if (!values) { + ESP_LOGE(TAG, "cspot_cb: Failed to create JSON object"); + return NULL; + } + // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); + // if(!cspot_config){ + // ESP_LOGE(TAG,"cspot_cb: Failed to get cspot config"); + // return NULL; + // } + // cJSON * cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.deviceName->hdr.longopts); + // if(cspot_values){ + // cJSON_AddStringToObject(values,cspot_args.deviceName->hdr.longopts,cJSON_GetStringValue(cspot_values)); + // } + // cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.bitrate->hdr.longopts); + // if(cspot_values){ + // cJSON_AddNumberToObject(values,cspot_args.bitrate->hdr.longopts,cJSON_GetNumberValue(cspot_values)); + // } // cspot_values = cJSON_GetObjectItem(cspot_config,cspot_args.zeroConf->hdr.longopts); - // if(cspot_values){ - // cJSON_AddNumberToObject(values,cspot_args.zeroConf->hdr.longopts,cJSON_GetNumberValue(cspot_values)); - // } + // if(cspot_values){ + // cJSON_AddNumberToObject(values,cspot_args.zeroConf->hdr.longopts,cJSON_GetNumberValue(cspot_values)); + // } - // cJSON_Delete(cspot_config); - // TODO: Add support for the commented code - return values; + // cJSON_Delete(cspot_config); + // TODO: Add support for the commented code + return values; } #endif // cJSON * i2s_cb(){ @@ -899,7 +947,7 @@ cJSON * cspot_cb(){ // const i2s_platform_config_t * i2s_conf= config_dac_get( ); // #if defined(CONFIG_WITH_METRICS) // metrics_add_feature("i2s",i2s_conf->pin.data_out_num>=0); -// #endif +// #endif // if(i2s_conf->pin.bck_io_num>0 ) { // cJSON_AddNumberToObject(values,i2s_args.clock->hdr.longopts,i2s_conf->pin.bck_io_num); // } @@ -914,30 +962,30 @@ cJSON * cspot_cb(){ // } // if(i2s_conf->scl>=0 ) { // cJSON_AddNumberToObject(values,i2s_args.dac_scl->hdr.longopts,i2s_conf->scl); -// } +// } // if(i2s_conf->i2c_addr>=0 ) { // cJSON_AddNumberToObject(values,i2s_args.dac_i2c->hdr.longopts,i2s_conf->i2c_addr); -// } +// } // if(i2s_conf->mute_gpio>=0 ) { // cJSON_AddNumberToObject(values,i2s_args.mute_gpio->hdr.longopts,i2s_conf->mute_gpio); -// } +// } // if(i2s_conf->mute_level>=0 ) { // cJSON_AddBoolToObject(values,i2s_args.mute_level->hdr.longopts,i2s_conf->mute_level>0); -// } +// } // if(strlen(i2s_conf->model)>0){ // cJSON_AddStringToObject(values,i2s_args.model_name->hdr.longopts,i2s_conf->model); // } // else { // cJSON_AddStringToObject(values,i2s_args.model_name->hdr.longopts,"I2S"); // } - + // return values; // } // cJSON * spdif_cb(){ // cJSON * values = cJSON_CreateObject(); // const i2s_platform_config_t * spdif_conf= config_spdif_get( ); // if(spdif_conf->pin.data_out_num>=0) { -// #if defined(CONFIG_WITH_METRICS) +// #if defined(CONFIG_WITH_METRICS) // metrics_add_feature("spdif","enabled"); // #endif // } @@ -950,16 +998,16 @@ cJSON * cspot_cb(){ // if(spdif_conf->pin.data_out_num>=0 ) { // cJSON_AddNumberToObject(values,"data",spdif_conf->pin.data_out_num); // } - + // return values; // } // cJSON * rotary_cb(){ // cJSON * values = cJSON_CreateObject(); - // char *p = config_alloc_get_default(NVS_TYPE_STR, "lms_ctrls_raw", "n", 0); - // bool raw_mode = p && (*p == '1' || *p == 'Y' || *p == 'y'); - // free(p); +// char *p = config_alloc_get_default(NVS_TYPE_STR, "lms_ctrls_raw", "n", 0); +// bool raw_mode = p && (*p == '1' || *p == 'Y' || *p == 'y'); +// free(p); // const rotary_struct_t *rotary= config_rotary_get(); -// #if defined(CONFIG_WITH_METRICS) +// #if defined(CONFIG_WITH_METRICS) // metrics_add_feature("rotary",GPIO_IS_VALID_GPIO(rotary->A )); // #endif // if(GPIO_IS_VALID_GPIO(rotary->A ) && rotary->A>=0 && GPIO_IS_VALID_GPIO(rotary->B) && rotary->B>=0){ @@ -974,7 +1022,7 @@ cJSON * cspot_cb(){ // cJSON_AddNumberToObject(values,rotary_args.timer->hdr.longopts,rotary->timer); // cJSON_AddNumberToObject(values,rotary_args.raw_mode->hdr.longopts,raw_mode); // } - // TODO: Add support for the commented code +// TODO: Add support for the commented code // return values; // } @@ -999,164 +1047,162 @@ cJSON * cspot_cb(){ // return values; // } -cJSON * audio_cb(){ - cJSON * values = cJSON_CreateObject(); -// char * p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0); -// cJSON_AddStringToObject(values,"jack_behavior",(strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0)?"Headphones":"Subwoofer"); -// #if defined(CONFIG_WITH_METRICS) -// metrics_add_feature("jack_mute",atoi(p)>=0); -// #endif -// FREE_AND_NULL(p); -// p = config_alloc_get_default(NVS_TYPE_STR, "loudness", "0", 0); -// #if defined(CONFIG_WITH_METRICS) -// metrics_add_feature("loudness",atoi(p)>=0); -// #endif -// cJSON_AddStringToObject(values,"loudness",p); -// FREE_AND_NULL(p); - // TODO: Add support for the commented code - return values; +cJSON* audio_cb() { + cJSON* values = cJSON_CreateObject(); + // char * p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0); + // cJSON_AddStringToObject(values,"jack_behavior",(strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0)?"Headphones":"Subwoofer"); + // #if defined(CONFIG_WITH_METRICS) + // metrics_add_feature("jack_mute",atoi(p)>=0); + // #endif + // FREE_AND_NULL(p); + // p = config_alloc_get_default(NVS_TYPE_STR, "loudness", "0", 0); + // #if defined(CONFIG_WITH_METRICS) + // metrics_add_feature("loudness",atoi(p)>=0); + // #endif + // cJSON_AddStringToObject(values,"loudness",p); + // FREE_AND_NULL(p); + // TODO: Add support for the commented code + return values; } -cJSON * bt_source_cb(){ - cJSON * values = cJSON_CreateObject(); - // TODO: Add support for the commented code -// char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_sink_name", NULL, 0); -// if(p){ -// cJSON_AddStringToObject(values,"sink_name",p); -// #if defined(CONFIG_WITH_METRICS) -// metrics_add_feature("btsource",strlen(p)>0); -// #endif -// } -// FREE_AND_NULL(p); +cJSON* bt_source_cb() { + cJSON* values = cJSON_CreateObject(); + // TODO: Add support for the commented code + // char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_sink_name", NULL, 0); + // if(p){ + // cJSON_AddStringToObject(values,"sink_name",p); + // #if defined(CONFIG_WITH_METRICS) + // metrics_add_feature("btsource",strlen(p)>0); + // #endif + // } + // FREE_AND_NULL(p); -// p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_spin", "0000", 0); -// if(p){ -// cJSON_AddStringToObject(values,"pin_code",p); -// } -// FREE_AND_NULL(p); + // p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_spin", "0000", 0); + // if(p){ + // cJSON_AddStringToObject(values,"pin_code",p); + // } + // FREE_AND_NULL(p); - return values; + return values; } - -void get_str_parm_json(struct arg_str * parm, cJSON * entry){ - const char * name = parm->hdr.longopts?parm->hdr.longopts:parm->hdr.glossary; - if(parm->count>0){ - cJSON_AddStringToObject(entry,name,parm->sval[0]); - } +void get_str_parm_json(struct arg_str* parm, cJSON* entry) { + const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; + if (parm->count > 0) { + cJSON_AddStringToObject(entry, name, parm->sval[0]); + } } -void get_file_parm_json(struct arg_file * parm, cJSON * entry){ - const char * name = parm->hdr.longopts?parm->hdr.longopts:parm->hdr.glossary; - if(parm->count>0){ - cJSON_AddStringToObject(entry,name,parm->filename[0]); - } +void get_file_parm_json(struct arg_file* parm, cJSON* entry) { + const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; + if (parm->count > 0) { + cJSON_AddStringToObject(entry, name, parm->filename[0]); + } } -void get_lit_parm_json(struct arg_lit * parm, cJSON * entry){ - const char * name = parm->hdr.longopts?parm->hdr.longopts:parm->hdr.glossary; - cJSON_AddBoolToObject(entry,name,(parm->count>0)); +void get_lit_parm_json(struct arg_lit* parm, cJSON* entry) { + const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; + cJSON_AddBoolToObject(entry, name, (parm->count > 0)); } -void get_int_parm_json(struct arg_int * parm, cJSON * entry){ - const char * name = parm->hdr.longopts?parm->hdr.longopts:parm->hdr.glossary; - if(parm->count>0){ - cJSON_AddNumberToObject(entry,name,parm->ival[0]); - } +void get_int_parm_json(struct arg_int* parm, cJSON* entry) { + const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; + if (parm->count > 0) { + cJSON_AddNumberToObject(entry, name, parm->ival[0]); + } } -static int do_squeezelite_cmd(int argc, char **argv) -{ - esp_err_t err=ESP_OK; - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr ** )&squeezelite_args); - char *buf = NULL; - size_t buf_size = 0; - FILE *f = system_open_memstream(argv[0],&buf, &buf_size); - if (f == NULL) { - return 1; - } - fprintf(f,"Not yet implemented!"); - nerrors+=1; - fflush (f); - cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); - fclose(f); - FREE_AND_NULL(buf); - return (nerrors==0 && err==ESP_OK)?0:1; +static int do_squeezelite_cmd(int argc, char** argv) { + esp_err_t err = ESP_OK; + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&squeezelite_args); + char* buf = NULL; + size_t buf_size = 0; + FILE* f = system_open_memstream(argv[0], &buf, &buf_size); + if (f == NULL) { + return 1; + } + fprintf(f, "Not yet implemented!"); + nerrors += 1; + fflush(f); + cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); + fclose(f); + FREE_AND_NULL(buf); + return (nerrors == 0 && err == ESP_OK) ? 0 : 1; } -cJSON * squeezelite_cb(){ - cJSON * values = cJSON_CreateObject(); -// char * nvs_config= config_alloc_get(NVS_TYPE_STR, "autoexec1"); -// char **argv = NULL; -// char *buf = NULL; -// size_t buf_size = 0; -// int nerrors=1; -// FILE *f = system_open_memstream(argv[0],&buf, &buf_size); -// if (f == NULL) { -// return values; -// } +cJSON* squeezelite_cb() { + cJSON* values = cJSON_CreateObject(); + // char * nvs_config= config_alloc_get(NVS_TYPE_STR, "autoexec1"); + // char **argv = NULL; + // char *buf = NULL; + // size_t buf_size = 0; + // int nerrors=1; + // FILE *f = system_open_memstream(argv[0],&buf, &buf_size); + // if (f == NULL) { + // return values; + // } -// if(nvs_config && strlen(nvs_config)>0){ -// ESP_LOGD(TAG,"Parsing command %s",nvs_config); -// argv = (char **) calloc(22, sizeof(char *)); -// if (argv == NULL) { -// FREE_AND_NULL(nvs_config); -// fclose(f); -// return values; -// } -// size_t argc = esp_console_split_argv(nvs_config, argv,22); -// if (argc != 0) { -// nerrors = arg_parse(argc, argv,(void **)&squeezelite_args); -// ESP_LOGD(TAG,"Parsing completed"); -// } -// } -// if (nerrors == 0) { -// get_str_parm_json(squeezelite_args.buffers, values); -// get_str_parm_json(squeezelite_args.codecs, values); -// get_lit_parm_json(squeezelite_args.header_format, values); -// get_str_parm_json(squeezelite_args.log_level, values); - -// // get_str_parm_json(squeezelite_args.log_level_all, values); -// // get_str_parm_json(squeezelite_args.log_level_decode, values); -// // get_str_parm_json(squeezelite_args.log_level_output, values); -// // get_str_parm_json(squeezelite_args.log_level_slimproto, values); -// // get_str_parm_json(squeezelite_args.log_level_stream, values); -// get_str_parm_json(squeezelite_args.mac_addr, values); -// get_str_parm_json(squeezelite_args.output_device, values); -// #if defined(CONFIG_WITH_METRICS) -// if(squeezelite_args.output_device->sval[0]!=NULL && strlen(squeezelite_args.output_device->sval[0])>0){ -// metrics_add_feature_variant("output",squeezelite_args.output_device->sval[0]); -// } -// #endif -// get_str_parm_json(squeezelite_args.model_name, values); -// get_str_parm_json(squeezelite_args.name, values); -// get_int_parm_json(squeezelite_args.rate, values); -// get_str_parm_json(squeezelite_args.rates, values); -// get_str_parm_json(squeezelite_args.server, values); -// get_int_parm_json(squeezelite_args.timeout, values); -// char * p = cJSON_Print(values); -// ESP_LOGD(TAG,"%s",p); -// free(p); -// } -// else { -// arg_print_errors(f, squeezelite_args.end, desc_squeezelite); -// } -// fflush (f); -// if(strlen(buf)>0){ -// log_send_messaging(nerrors?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); -// } -// fclose(f); -// FREE_AND_NULL(buf); -// FREE_AND_NULL(nvs_config); -// FREE_AND_NULL(argv); -// TODO: Add support for the commented code - return values; + // if(nvs_config && strlen(nvs_config)>0){ + // ESP_LOGD(TAG,"Parsing command %s",nvs_config); + // argv = (char **) calloc(22, sizeof(char *)); + // if (argv == NULL) { + // FREE_AND_NULL(nvs_config); + // fclose(f); + // return values; + // } + // size_t argc = esp_console_split_argv(nvs_config, argv,22); + // if (argc != 0) { + // nerrors = arg_parse(argc, argv,(void **)&squeezelite_args); + // ESP_LOGD(TAG,"Parsing completed"); + // } + // } + // if (nerrors == 0) { + // get_str_parm_json(squeezelite_args.buffers, values); + // get_str_parm_json(squeezelite_args.codecs, values); + // get_lit_parm_json(squeezelite_args.header_format, values); + // get_str_parm_json(squeezelite_args.log_level, values); + + // // get_str_parm_json(squeezelite_args.log_level_all, values); + // // get_str_parm_json(squeezelite_args.log_level_decode, values); + // // get_str_parm_json(squeezelite_args.log_level_output, values); + // // get_str_parm_json(squeezelite_args.log_level_slimproto, values); + // // get_str_parm_json(squeezelite_args.log_level_stream, values); + // get_str_parm_json(squeezelite_args.mac_addr, values); + // get_str_parm_json(squeezelite_args.output_device, values); + // #if defined(CONFIG_WITH_METRICS) + // if(squeezelite_args.output_device->sval[0]!=NULL && strlen(squeezelite_args.output_device->sval[0])>0){ + // metrics_add_feature_variant("output",squeezelite_args.output_device->sval[0]); + // } + // #endif + // get_str_parm_json(squeezelite_args.model_name, values); + // get_str_parm_json(squeezelite_args.name, values); + // get_int_parm_json(squeezelite_args.rate, values); + // get_str_parm_json(squeezelite_args.rates, values); + // get_str_parm_json(squeezelite_args.server, values); + // get_int_parm_json(squeezelite_args.timeout, values); + // char * p = cJSON_Print(values); + // ESP_LOGD(TAG,"%s",p); + // free(p); + // } + // else { + // arg_print_errors(f, squeezelite_args.end, desc_squeezelite); + // } + // fflush (f); + // if(strlen(buf)>0){ + // log_send_messaging(nerrors?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf); + // } + // fclose(f); + // FREE_AND_NULL(buf); + // FREE_AND_NULL(nvs_config); + // FREE_AND_NULL(argv); + // TODO: Add support for the commented code + return values; } -static char * get_log_level_options(const char * longname){ - const char * template = "<%s=info|%s=debug|%s=sdebug>"; - char * options = NULL; - int len = snprintf(NULL,0,template,longname,longname,longname); - if(len>0){ - options = malloc_init_external(len+1); - snprintf(options,len,template,longname,longname,longname); - } - return options; +static char* get_log_level_options(const char* longname) { + const char* template = "<%s=info|%s=debug|%s=sdebug>"; + char* options = NULL; + int len = snprintf(NULL, 0, template, longname, longname, longname); + if (len > 0) { + options = malloc_init_external(len + 1); + snprintf(options, len, template, longname, longname, longname); + } + return options; } // // loop through dac_set and concatenate model name separated with | @@ -1188,68 +1234,68 @@ static char * get_log_level_options(const char * longname){ // } // return dac_list; // } -void replace_char_in_string(char * str, char find, char replace){ - for(int i=0;str[i];i++){ - if(str[i]==find){ - str[i]=replace; - } - } +void replace_char_in_string(char* str, char find, char replace) { + for (int i = 0; str[i]; i++) { + if (str[i] == find) { + str[i] = replace; + } + } } -static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE * f){ - esp_err_t err = ESP_OK; - char * json_string=NULL; - json_string = cJSON_Print(known_item); - ESP_LOGD(TAG,"known_item_string: %s",STR_OR_BLANK(json_string)); - FREE_AND_NULL(json_string); - cJSON * kvp=NULL; - cJSON * config_array = cJSON_GetObjectItem(known_item,"config"); - if(config_array && cJSON_IsArray(config_array)){ - json_string = cJSON_Print(config_array); - ESP_LOGD(TAG,"config_array: %s",STR_OR_BLANK(json_string)); - FREE_AND_NULL(json_string); - cJSON_ArrayForEach(kvp, config_array){ - cJSON * kvp_value=kvp->child; - if(!kvp_value){ - printf("config entry is not an object!\n"); - err=ESP_FAIL; - continue; - } - char * key = kvp_value->string; - char * value = kvp_value->valuestring; - if(!key || !value || strlen(key)==0){ - printf("Invalid config entry %s:%s\n",STR_OR_BLANK(key),STR_OR_BLANK(value)); - err=ESP_FAIL; - continue; - } - - fprintf(f,"Storing %s=%s\n",key,value); - // err = config_set_value(NVS_TYPE_STR,key,value); - // TODO: Add support for the commented code - if(err){ - fprintf(f,"Failed to store config value: %s\n",esp_err_to_name(err)); - break; - } - } - } - else { - json_string = cJSON_Print(config_array); - char * known_item_string = cJSON_Print(known_item); - fprintf(f,"Failed to parse config array. %s\n%s\nKnown item found: %s\n",config_array?cJSON_IsArray(config_array)?"":"NOT AN ARRAY":"config entry not found",STR_OR_BLANK(json_string),STR_OR_BLANK(known_item_string)); - FREE_AND_NULL(json_string); - FREE_AND_NULL(known_item_string); - err = ESP_FAIL; - } - +static esp_err_t save_known_config(cJSON* known_item, const char* name, FILE* f) { + esp_err_t err = ESP_OK; + char* json_string = NULL; + json_string = cJSON_Print(known_item); + ESP_LOGD(TAG, "known_item_string: %s", STR_OR_BLANK(json_string)); + FREE_AND_NULL(json_string); + cJSON* kvp = NULL; + cJSON* config_array = cJSON_GetObjectItem(known_item, "config"); + if (config_array && cJSON_IsArray(config_array)) { + json_string = cJSON_Print(config_array); + ESP_LOGD(TAG, "config_array: %s", STR_OR_BLANK(json_string)); + FREE_AND_NULL(json_string); + cJSON_ArrayForEach(kvp, config_array) { + cJSON* kvp_value = kvp->child; + if (!kvp_value) { + printf("config entry is not an object!\n"); + err = ESP_FAIL; + continue; + } + char* key = kvp_value->string; + char* value = kvp_value->valuestring; + if (!key || !value || strlen(key) == 0) { + printf("Invalid config entry %s:%s\n", STR_OR_BLANK(key), STR_OR_BLANK(value)); + err = ESP_FAIL; + continue; + } - if(err==ESP_OK){ - // err = config_set_value(NVS_TYPE_STR,"board_model",name); - // TODO: Add support for the commented code - if(err!=ESP_OK){ - fprintf(f,"Failed to save board model %s\n",name); - } - } - - return err; + fprintf(f, "Storing %s=%s\n", key, value); + // err = config_set_value(NVS_TYPE_STR,key,value); + // TODO: Add support for the commented code + if (err) { + fprintf(f, "Failed to store config value: %s\n", esp_err_to_name(err)); + break; + } + } + } else { + json_string = cJSON_Print(config_array); + char* known_item_string = cJSON_Print(known_item); + fprintf(f, "Failed to parse config array. %s\n%s\nKnown item found: %s\n", + config_array ? cJSON_IsArray(config_array) ? "" : "NOT AN ARRAY" : "config entry not found", STR_OR_BLANK(json_string), + STR_OR_BLANK(known_item_string)); + FREE_AND_NULL(json_string); + FREE_AND_NULL(known_item_string); + err = ESP_FAIL; + } + + if (err == ESP_OK) { + // err = config_set_value(NVS_TYPE_STR,"board_model",name); + // TODO: Add support for the commented code + if (err != ESP_OK) { + fprintf(f, "Failed to save board model %s\n", name); + } + } + + return err; } // static int do_register_known_templates_config(int argc, char **argv){ @@ -1312,9 +1358,9 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE * // } // else { // fprintf(f,"Registered known config %s.\n",known_model_args.model_config->sval[0]); -// } +// } // } - + // if(!nerrors ){ // fprintf(f,"Done.\n"); // } @@ -1326,9 +1372,8 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE * // } // static void register_known_templates_config(){ -// known_model_args.model_config = arg_str1(NULL,"model_config","SqueezeAMP|T-WATCH2020 by LilyGo","Known Board Name.\nFor known boards, several systems parameters will be updated"); -// known_model_args.end = arg_end(1); -// const esp_console_cmd_t cmd = { +// known_model_args.model_config = arg_str1(NULL,"model_config","SqueezeAMP|T-WATCH2020 by LilyGo","Known Board Name.\nFor known boards, several +// systems parameters will be updated"); known_model_args.end = arg_end(1); const esp_console_cmd_t cmd = { // .command = CFG_TYPE_HW("preset"), // .help = desc_preset, // .hint = NULL, @@ -1380,37 +1425,37 @@ static esp_err_t save_known_config(cJSON * known_item, const char * name,FILE * // ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); // } -static void register_bt_source_config(void){ - - bt_source_args.sink_name= arg_str1("n","sink_name", "name","Bluetooth audio device name. This applies when output mode is Bluetooth"); - bt_source_args.pin_code= arg_str1("p","pin_code", "pin","Bluetooth security/pin code. Usually 0000. This applies when output mode is Bluetooth"); -// bt_source_args.control_delay= arg_dbl0("d","control_delay","seconds","Control response delay, in seconds. This determines the response time of the system Bluetooth events. The default value should work for the majority of cases and changing this could lead to instabilities."); -// bt_source_args.connect_timeout_delay= arg_dbl0("t","connect_timeout_delay","seconds","Connection timeout. Determines the maximum amount of time, in seconds, that the system will wait when connecting to a bluetooth device. Beyond this delay, a new connect attempt will be made."); - bt_source_args.end= arg_end(1); - const esp_console_cmd_t cmd = { - .command = CFG_TYPE_AUDIO("bt_source"), - .help = desc_bt_source, - .hint = NULL, - .func = &do_bt_source_cmd, - .argtable = &bt_source_args - }; - cmd_to_json_with_cb(&cmd,&bt_source_cb); +static void register_bt_source_config(void) { + + bt_source_args.sink_name = arg_str1("n", "sink_name", "name", "Bluetooth audio device name. This applies when output mode is Bluetooth"); + bt_source_args.pin_code = + arg_str1("p", "pin_code", "pin", "Bluetooth security/pin code. Usually 0000. This applies when output mode is Bluetooth"); + // bt_source_args.control_delay= arg_dbl0("d","control_delay","seconds","Control response delay, in seconds. This determines the response time of + //the system Bluetooth events. The default value should work for the majority of cases and changing this could lead to instabilities."); + // bt_source_args.connect_timeout_delay= arg_dbl0("t","connect_timeout_delay","seconds","Connection timeout. Determines the maximum amount of + //time, in seconds, that the system will wait when connecting to a bluetooth device. Beyond this delay, a new connect attempt will be made."); + bt_source_args.end = arg_end(1); + const esp_console_cmd_t cmd = { + .command = CFG_TYPE_AUDIO("bt_source"), .help = desc_bt_source, .hint = NULL, .func = &do_bt_source_cmd, .argtable = &bt_source_args}; + cmd_to_json_with_cb(&cmd, &bt_source_cb); ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } // void register_rotary_config(void){ -// rotary_args.rem = arg_rem("remark","One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.\r\nEncoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT and AirPlay."); -// rotary_args.A = arg_int1(NULL,"A","gpio","A/DT gpio"); -// rotary_args.B = arg_int1(NULL,"B","gpio","B/CLK gpio"); -// rotary_args.SW = arg_int0(NULL,"SW","gpio","Switch gpio"); -// rotary_args.knobonly = arg_lit0(NULL,"knobonly","Single knob full navigation. Left, Right and Press is navigation, with Press always going to lower submenu item. Longpress is 'Play', Double press is 'Back', a quick left-right movement on the encoder is 'Pause'"); -// rotary_args.timer = arg_int0(NULL,"timer","ms","The speed of double click (or left-right) when knob only option is enabled. Be aware that the longer you set double click speed, the less responsive the interface will be. "); -// rotary_args.volume_lock = arg_lit0(NULL,"volume_lock", "Force Volume down/up/play toggle all the time (even in LMS). "); -// rotary_args.longpress = arg_lit0(NULL,"longpress","Enable alternate mode mode on long-press. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode actual behavior depends on 'volume')."); -// rotary_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); -// rotary_args.raw_mode = arg_lit0(NULL, "raw_mode", "Send button events as raw values to LMS. No remapping is possible when this is enabled"); -// rotary_args.end = arg_end(3); -// const esp_console_cmd_t cmd = { +// rotary_args.rem = arg_rem("remark","One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders +// (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is +// provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by +// software.\r\nEncoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT and +// AirPlay."); rotary_args.A = arg_int1(NULL,"A","gpio","A/DT gpio"); rotary_args.B = arg_int1(NULL,"B","gpio","B/CLK gpio"); rotary_args.SW = +// arg_int0(NULL,"SW","gpio","Switch gpio"); rotary_args.knobonly = arg_lit0(NULL,"knobonly","Single knob full navigation. Left, Right and Press is +// navigation, with Press always going to lower submenu item. Longpress is 'Play', Double press is 'Back', a quick left-right movement on the encoder +// is 'Pause'"); rotary_args.timer = arg_int0(NULL,"timer","ms","The speed of double click (or left-right) when knob only option is enabled. Be aware +// that the longer you set double click speed, the less responsive the interface will be. "); rotary_args.volume_lock = arg_lit0(NULL,"volume_lock", +// "Force Volume down/up/play toggle all the time (even in LMS). "); rotary_args.longpress = arg_lit0(NULL,"longpress","Enable alternate mode mode on +// long-press. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode +// actual behavior depends on 'volume')."); rotary_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); rotary_args.raw_mode = arg_lit0(NULL, +// "raw_mode", "Send button events as raw values to LMS. No remapping is possible when this is enabled"); rotary_args.end = arg_end(3); const +// esp_console_cmd_t cmd = { // .command = CFG_TYPE_HW("rotary"), // .help = desc_rotary, // .hint = NULL, @@ -1422,11 +1467,9 @@ static void register_bt_source_config(void){ // } // void register_ledvu_config(void){ -// ledvu_args.type = arg_str1(NULL,"type","|WS2812","Led type (supports one rgb strip to display built in effects and allow remote control through 'dmx' messaging)"); -// ledvu_args.length = arg_int1(NULL,"length","<1..255>","Strip length (1-255 supported)"); -// ledvu_args.gpio = arg_int1(NULL,"gpio","gpio","Data pin"); -// ledvu_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); -// ledvu_args.end = arg_end(4); +// ledvu_args.type = arg_str1(NULL,"type","|WS2812","Led type (supports one rgb strip to display built in effects and allow remote control +// through 'dmx' messaging)"); ledvu_args.length = arg_int1(NULL,"length","<1..255>","Strip length (1-255 supported)"); ledvu_args.gpio = +// arg_int1(NULL,"gpio","gpio","Data pin"); ledvu_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); ledvu_args.end = arg_end(4); // const esp_console_cmd_t cmd = { // .command = CFG_TYPE_HW("ledvu"), @@ -1439,19 +1482,18 @@ static void register_bt_source_config(void){ // ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); // } -void register_audio_config(void){ - audio_args.jack_behavior = arg_str0("j", "jack_behavior","Headphones|Subwoofer","On supported DAC, determines the audio jack behavior. Selecting headphones will cause the external amp to be muted on insert, while selecting Subwoofer will keep the amp active all the time."); - audio_args.loudness = arg_int0("l", "loudness","0-10","Sets a loudness level, from 0 to 10. 0 will disable the loudness completely. Note that LMS has priority over setting this value, so use it only when away from your server."); +void register_audio_config(void) { + audio_args.jack_behavior = arg_str0("j", "jack_behavior", "Headphones|Subwoofer", + "On supported DAC, determines the audio jack behavior. Selecting headphones will cause the external amp to be muted on insert, while " + "selecting Subwoofer will keep the amp active all the time."); + audio_args.loudness = arg_int0("l", "loudness", "0-10", + "Sets a loudness level, from 0 to 10. 0 will disable the loudness completely. Note that LMS has priority over setting this value, so use it " + "only when away from your server."); audio_args.end = arg_end(6); audio_args.end = arg_end(6); - const esp_console_cmd_t cmd = { - .command = CFG_TYPE_AUDIO("general"), - .help = desc_audio, - .hint = NULL, - .func = &do_audio_cmd, - .argtable = &audio_args - }; - cmd_to_json_with_cb(&cmd,&audio_cb); + const esp_console_cmd_t cmd = { + .command = CFG_TYPE_AUDIO("general"), .help = desc_audio, .hint = NULL, .func = &do_audio_cmd, .argtable = &audio_args}; + cmd_to_json_with_cb(&cmd, &audio_cb); ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } @@ -1472,84 +1514,145 @@ void register_audio_config(void){ // cmd_to_json_with_cb(&cmd,&spdif_cb); // ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); // } -static void register_squeezelite_config(void){ - squeezelite_args.server = arg_str0("s","server","[:]","Connect to specified server, otherwise uses autodiscovery to find server"); - squeezelite_args.buffers = arg_str0("b","buffers",":","Internal Stream and Output buffer sizes in Kbytes"); - squeezelite_args.codecs = arg_strn("c","codecs","+" CODECS "+",0,20,"Restrict codecs to those specified, otherwise load all available codecs; known codecs: " CODECS ); - squeezelite_args.timeout = arg_int0("C","timeout","","Close output device when idle after timeout seconds, default is to keep it open while player is 'on"); - squeezelite_args.log_level = arg_str0("d","loglevel","log=level","Set logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug"); // " -d =\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n" -// squeezelite_args.log_level_all = arg_str0(NULL,"all",get_log_level_options("all"),"Overall Logging Level"); -// squeezelite_args.log_level_slimproto = arg_str0(NULL,"loglevel_slimproto",get_log_level_options("slimproto"),"Slimproto Logging Level"); -// squeezelite_args.log_level_stream= arg_str0(NULL,"loglevel_stream",get_log_level_options("stream"),"Stream Logging Level"); -// squeezelite_args.log_level_decode= arg_str0(NULL,"loglevel_decode",get_log_level_options("decode"),"Decode Logging Level"); -// squeezelite_args.log_level_output= arg_str0(NULL,"loglevel_output",get_log_level_options("output"),"Output Logging Level"); - #if IR - squeezelite_args.log_level_ir= arg_str0(NULL,"loglevel_ir",get_log_level_options("ir"),"IR Logging Level"); - #endif +static void register_squeezelite_config(void) { + squeezelite_args.server = + arg_str0("s", "server", "[:]", "Connect to specified server, otherwise uses autodiscovery to find server"); + squeezelite_args.buffers = arg_str0("b", "buffers", ":", "Internal Stream and Output buffer sizes in Kbytes"); + squeezelite_args.codecs = arg_strn( + "c", "codecs", "+" CODECS "+", 0, 20, "Restrict codecs to those specified, otherwise load all available codecs; known codecs: " CODECS); + squeezelite_args.timeout = + arg_int0("C", "timeout", "", "Close output device when idle after timeout seconds, default is to keep it open while player is 'on"); + squeezelite_args.log_level = arg_str0("d", "loglevel", "log=level", + "Set logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug"); // " -d =\tSet logging level, logs: + // all|slimproto|stream|decode|output|ir, level: + // info|debug|sdebug\n" + // squeezelite_args.log_level_all = arg_str0(NULL,"all",get_log_level_options("all"),"Overall Logging Level"); + // squeezelite_args.log_level_slimproto = arg_str0(NULL,"loglevel_slimproto",get_log_level_options("slimproto"),"Slimproto Logging Level"); + // squeezelite_args.log_level_stream= arg_str0(NULL,"loglevel_stream",get_log_level_options("stream"),"Stream Logging Level"); + // squeezelite_args.log_level_decode= arg_str0(NULL,"loglevel_decode",get_log_level_options("decode"),"Decode Logging Level"); + // squeezelite_args.log_level_output= arg_str0(NULL,"loglevel_output",get_log_level_options("output"),"Output Logging Level"); +#if IR + squeezelite_args.log_level_ir = arg_str0(NULL, "loglevel_ir", get_log_level_options("ir"), "IR Logging Level"); +#endif - squeezelite_args.output_device = arg_str0("o","output_device","","Output device (BT, I2S or SPDIF)"); - squeezelite_args.mac_addr = arg_str0("m","mac_addr","","Mac address, format: ab:cd:ef:12:34:56."); - squeezelite_args.model_name = arg_str0("M", "modelname", "","Set the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")"); - squeezelite_args.name = arg_str0("n","name","","Player name, if different from the current host name. Name can alternatively be assigned from the system/device name configuration."); - squeezelite_args.header_format = arg_lit0("W","header_format","Read wave and aiff format from header, ignore server parameters"); - squeezelite_args.rates = arg_str0("r","rates","[:]", "Sample rates supported, allows output to be off when squeezelite is started; rates = |-|,,; delay = optional delay switching rates in ms\n"); - #if RESAMPLE - squeezelite_args.resample = arg_lit0("R","resample","Activate Resample"); - squeezelite_args.resample_parms = arg_str0("u","resample_parms","::::::","Resample, params"); - #endif - #if RESAMPLE16 - squeezelite_args.resample = arg_lit0("R","resample","Activate Resample"); - squeezelite_args.resample_parms = arg_str0("u","resample_parms","(b|l|m)[:i]","Resample, params. b = basic linear interpolation, l = 13 taps, m = 21 taps, i = interpolate filter coefficients"); - #endif - squeezelite_args.rate = arg_int0("Z","max_rate", "", "Report rate to server in helo as the maximum sample rate we can support"); - squeezelite_args.end = arg_end(6); + squeezelite_args.output_device = arg_str0("o", "output_device", "", "Output device (BT, I2S or SPDIF)"); + squeezelite_args.mac_addr = arg_str0("m", "mac_addr", "", "Mac address, format: ab:cd:ef:12:34:56."); + squeezelite_args.model_name = + arg_str0("M", "modelname", "", "Set the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")"); + squeezelite_args.name = arg_str0("n", "name", "", + "Player name, if different from the current host name. Name can alternatively be assigned from the system/device name configuration."); + squeezelite_args.header_format = arg_lit0("W", "header_format", "Read wave and aiff format from header, ignore server parameters"); + squeezelite_args.rates = arg_str0("r", "rates", "[:]", + "Sample rates supported, allows output to be off when squeezelite is started; rates = |-|,,; " + "delay = optional delay switching rates in ms\n"); +#if RESAMPLE + squeezelite_args.resample = arg_lit0("R", "resample", "Activate Resample"); + squeezelite_args.resample_parms = arg_str0( + "u", "resample_parms", "::::::", "Resample, params"); +#endif +#if RESAMPLE16 + squeezelite_args.resample = arg_lit0("R", "resample", "Activate Resample"); + squeezelite_args.resample_parms = arg_str0("u", "resample_parms", "(b|l|m)[:i]", + "Resample, params. b = basic linear interpolation, l = 13 taps, m = 21 taps, i = interpolate filter coefficients"); +#endif + squeezelite_args.rate = arg_int0("Z", "max_rate", "", "Report rate to server in helo as the maximum sample rate we can support"); + squeezelite_args.end = arg_end(6); const esp_console_cmd_t cmd = { - .command = CFG_TYPE_AUDIO("squeezelite"), - .help = desc_squeezelite, - .hint = NULL, - .func = &do_squeezelite_cmd, - .argtable = &squeezelite_args - }; + .command = CFG_TYPE_AUDIO("squeezelite"), .help = desc_squeezelite, .hint = NULL, .func = &do_squeezelite_cmd, .argtable = &squeezelite_args}; // cmd_to_json_with_cb(&cmd,&squeezelite_cb); // ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -void dummy_register_cmd(){ - -} -void register_wifi_connect(){ - wifi_ap_args.conn= arg_lit0(NULL,"join","Connect to an access point "); - wifi_ap_args.ap_name= arg_str0("w","wifi","string","Access Point to connect to "); - wifi_ap_args.password= arg_str0("p","pass","string","Password for the access point (if needed) "); - wifi_ap_args.end = arg_end(1); - const esp_console_cmd_t cmd = { - .command = CFG_TYPE_SYST("wifi"), - .help = desc_wifi, +void dummy_register_cmd() {} + + +void register_wifi_commands() { + // WiFi Join Command + wifi_join_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to connect to"); + wifi_join_args.password = arg_str0(NULL, NULL, "[password]", "Password for the access point"); + wifi_join_args.end = arg_end(2); + const esp_console_cmd_t join_cmd = { + .command = "wifi_join", + .help = "Join a WiFi network", .hint = NULL, - .func = &do_wifi_ops, - .argtable = &wifi_ap_args + .func = &do_wifi_join, + .argtable = &wifi_join_args }; - cmd_to_json_with_cb(&cmd,&squeezelite_cb); - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&join_cmd)); + wifi_add_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to connect to"); + wifi_add_args.password = arg_str0(NULL, NULL, "[password]", "Password for the access point"); + wifi_add_args.end = arg_end(2); + const esp_console_cmd_t add_cmd = { + .command = "wifi_add", + .help = "Adds a WiFi network to known list without connecting to it", + .hint = NULL, + .func = &do_wifi_add, + .argtable = &wifi_add_args + }; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&add_cmd)); + // WiFi Delete Command + wifi_delete_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to forget"); + wifi_delete_args.end = arg_end(1); + const esp_console_cmd_t delete_cmd = { + .command = "wifi_delete", + .help = "Delete a WiFi network", + .hint = NULL, + .func = &do_wifi_delete, + .argtable = &wifi_delete_args + }; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&delete_cmd)); + + // WiFi Scan Command + wifi_scan_args.end = arg_end(1); + const esp_console_cmd_t scan_cmd = { + .command = "wifi_scan", + .help = "Scan for available WiFi networks", + .hint = NULL, + .func = &do_wifi_scan, + .argtable = &wifi_scan_args + }; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&scan_cmd)); + + // WiFi Status Command + wifi_status_args.end = arg_end(1); + const esp_console_cmd_t status_cmd = { + .command = "wifi_status", + .help = "Show current WiFi connection status", + .hint = NULL, + .func = &do_wifi_status, + .argtable = &wifi_status_args + }; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&status_cmd)); + + + // WiFi Reset Command + wifi_reset_args.end = arg_end(1); + const esp_console_cmd_t reset_cmd = { + .command = "wifi_reset", + .help = "Reset WiFi configuration to default settings", + .hint = NULL, + .func = &do_wifi_reset, + .argtable = &wifi_reset_args + }; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&reset_cmd)); } -void register_config_cmd(void){ - // if(!is_dac_config_locked()){ - // register_known_templates_config(); - // } +void register_config_cmd(void) { + // if(!is_dac_config_locked()){ + // register_known_templates_config(); + // } -// #ifdef CONFIG_CSPOT_SINK +// #ifdef CONFIG_CSPOT_SINK // register_cspot_config(); -// #endif - // register_bt_source_config(); -#if CONFIG_WITH_CONFIG_UI - if(!is_dac_config_locked()){ - register_i2s_config(); - } - else { +// #endif +// register_bt_source_config(); +#if CONFIG_WITH_CONFIG_UI + if (!is_dac_config_locked()) { + register_i2s_config(); + } else { #if defined(CONFIG_WITH_METRICS) - metrics_add_feature("i2s",true); + metrics_add_feature("i2s", true); #endif - } + } // if(!is_spdif_config_locked()){ // register_spdif_config(); // } @@ -1559,7 +1662,6 @@ void register_config_cmd(void){ // #endif // } #endif - register_optional_cmd(); - register_wifi_connect(); + register_optional_cmd(); + register_wifi_commands(); } - diff --git a/components/platform_console/cmd_i2ctools.c b/components/platform_console/cmd_i2ctools.c index 6daa258e..792cdb82 100644 --- a/components/platform_console/cmd_i2ctools.c +++ b/components/platform_console/cmd_i2ctools.c @@ -16,7 +16,7 @@ #include "driver/i2c.h" #include "esp_log.h" #include "messaging.h" -// #include "Configurator.h" +// #include "Config.h" #pragma message("fixme: look for TODO below") #include "platform_console.h" #include "stdio.h" @@ -41,19 +41,18 @@ const char* desc_spiconfig = "SPI Bus Parameters"; const char* desc_i2c = "I2C Bus Parameters"; const char* desc_display = "Display"; -#ifdef CONFIG_I2C_LOCKED -static i2c_port_t i2c_port = I2C_NUM_1; -#else -static i2c_port_t i2c_port = I2C_NUM_0; -#endif static struct { + struct arg_int* port; struct arg_int* chip_address; struct arg_int* register_address; struct arg_int* data_length; struct arg_end* end; } i2cget_args; - +static struct { + struct arg_int* port; + struct arg_end* end; +} i2cdetect_args; static struct { struct arg_int* chip_address; struct arg_int* port; @@ -288,31 +287,31 @@ static esp_err_t i2c_get_port(int port, i2c_port_t* i2c_port) { } return ESP_OK; } -static esp_err_t i2c_master_driver_install(const char* cmdname) { - esp_err_t err = ESP_OK; - cmd_send_messaging(cmdname, MESSAGING_INFO, "Installing i2c driver on port %u\n", i2c_port); - if ((err = i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, - I2C_MASTER_TX_BUF_DISABLE, 0)) != ESP_OK) { - cmd_send_messaging( - cmdname, MESSAGING_ERROR, "Driver install failed! %s\n", esp_err_to_name(err)); - } - return err; -} +// static esp_err_t i2c_master_driver_install(const char* cmdname) { +// esp_err_t err = ESP_OK; +// cmd_send_messaging(cmdname, MESSAGING_INFO, "Installing i2c driver on port %u\n", i2c_port); +// if ((err = i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, +// I2C_MASTER_TX_BUF_DISABLE, 0)) != ESP_OK) { +// cmd_send_messaging( +// cmdname, MESSAGING_ERROR, "Driver install failed! %s\n", esp_err_to_name(err)); +// } +// return err; +// } -static esp_err_t i2c_master_driver_initialize(const char* cmdname, i2c_config_t* conf) { - esp_err_t err = ESP_OK; - cmd_send_messaging(cmdname, MESSAGING_INFO, - "Initializing i2c driver configuration.\n mode = I2C_MODE_MASTER, \n scl_pullup_en = " - "GPIO_PULLUP_ENABLE, \n i2c port = %u, \n sda_io_num = %u, \n sda_pullup_en = " - "GPIO_PULLUP_ENABLE, \n scl_io_num = %u, \n scl_pullup_en = GPIO_PULLUP_ENABLE, \n " - "master.clk_speed = %u\n", - i2c_port, conf->sda_io_num, conf->scl_io_num, conf->master.clk_speed); - if ((err = i2c_param_config(i2c_port, conf)) != ESP_OK) { - cmd_send_messaging( - cmdname, MESSAGING_ERROR, "i2c driver config load failed. %s\n", esp_err_to_name(err)); - } - return err; -} +// static esp_err_t i2c_master_driver_initialize(const char* cmdname, i2c_config_t* conf) { +// esp_err_t err = ESP_OK; +// cmd_send_messaging(cmdname, MESSAGING_INFO, +// "Initializing i2c driver configuration.\n mode = I2C_MODE_MASTER, \n scl_pullup_en = " +// "GPIO_PULLUP_ENABLE, \n i2c port = %u, \n sda_io_num = %u, \n sda_pullup_en = " +// "GPIO_PULLUP_ENABLE, \n scl_io_num = %u, \n scl_pullup_en = GPIO_PULLUP_ENABLE, \n " +// "master.clk_speed = %u\n", +// i2c_port, conf->sda_io_num, conf->scl_io_num, conf->master.clk_speed); +// if ((err = i2c_param_config(i2c_port, conf)) != ESP_OK) { +// cmd_send_messaging( +// cmdname, MESSAGING_ERROR, "i2c driver config load failed. %s\n", esp_err_to_name(err)); +// } +// return err; +// } #if CONFIG_WITH_CONFIG_UI static int do_i2c_set_display(int argc, char** argv) { @@ -763,12 +762,9 @@ static int do_i2cget_cmd(int argc, char** argv) { if (i2cget_args.data_length->count) { len = i2cget_args.data_length->ival[0]; } - i2c_port_t loc_i2c_port = i2c_port; - if (i2cset_args.port->count && - i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != ESP_OK) { - return 1; - } - + i2c_port_t loc_i2c_port = i2cget_args.port->ival[0]; + const sys_i2c_bus*i2c = get_i2c_bus(loc_i2c_port); + #pragma message("TODO: Fix this!") char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); @@ -897,18 +893,21 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { return 0; } + static int do_i2cdetect_cmd(int argc, char** argv) { #ifdef CONFIG_WITH_CONFIG_UI uint8_t matches[128] = {}; int last_match = 0; #endif esp_err_t ret = ESP_OK; - i2c_port_t loc_i2c_port = i2c_port; + i2c_port_t loc_i2c_port = i2cdetect_args.port->ival[0]; + // if (i2cset_args.port->count && i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != // ESP_OK) { return 1; // } - int i2c_port; - const i2c_config_t* i2c = config_i2c_get(&i2c_port); + + const sys_i2c_bus*i2c = get_i2c_bus(loc_i2c_port); + uint8_t address; char* buf = NULL; @@ -919,8 +918,7 @@ static int do_i2cdetect_cmd(int argc, char** argv) { return 1; } - if (!GPIO_IS_VALID_OUTPUT_GPIO(i2c->scl_io_num) || !GPIO_IS_VALID_GPIO(i2c->scl_io_num) || - !GPIO_IS_VALID_OUTPUT_GPIO(i2c->sda_io_num) || !GPIO_IS_VALID_GPIO(i2c->sda_io_num)) { + if (!i2c) { fprintf(f, "I2C bus configuration invalid.\r\n"); } else { @@ -1007,12 +1005,13 @@ static void register_i2c_set_display() { } #endif static void register_i2cdectect(void) { + i2cdetect_args.port = arg_int1(NULL,NULL, "<0|1>", "Specify the i2c port number"); + i2cdetect_args.end = arg_end(1); const esp_console_cmd_t i2cdetect_cmd = {.command = "i2cdetect", .help = "Scan I2C bus for devices", .hint = NULL, .func = &do_i2cdetect_cmd, - .argtable = NULL}; - cmd_to_json(&i2cdetect_cmd); + .argtable = &i2cdetect_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&i2cdetect_cmd)); } @@ -1023,6 +1022,7 @@ static void register_i2cget(void) { "r", "register", "", "Specify the address on that chip to read from"); i2cget_args.data_length = arg_int0("l", "length", "", "Specify the length to read from that data address"); + i2cget_args.port = arg_int1(NULL,NULL, "<0|1>", "Specify the i2c port number"); i2cget_args.end = arg_end(1); const esp_console_cmd_t i2cget_cmd = {.command = "i2cget", .help = "Read registers visible through the I2C bus", @@ -1070,8 +1070,7 @@ static void register_i2cdump(void) { cJSON* i2config_cb() { cJSON* values = cJSON_CreateObject(); - int i2c_port; - const i2c_config_t* i2c = config_i2c_get(&i2c_port); + const i2c_config_t* i2c = config_i2c_get(&platform->dev.i2c); if (i2c->scl_io_num > 0) { cJSON_AddNumberToObject(values, "scl", i2c->scl_io_num); } @@ -1081,8 +1080,8 @@ cJSON* i2config_cb() { if (i2c->master.clk_speed > 0) { cJSON_AddNumberToObject(values, "speed", i2c->master.clk_speed); } - if (i2c_port >= 0) { - cJSON_AddNumberToObject(values, "port", i2c_port); + if (platform->dev.i2c.port-sys_i2c_port_PORT0 >= 0) { + cJSON_AddNumberToObject(values, "port", platform->dev.i2c.port-sys_i2c_port_PORT0); } return values; } diff --git a/components/platform_console/cmd_system.c b/components/platform_console/cmd_system.c index 0d0b6a70..a69af382 100644 --- a/components/platform_console/cmd_system.c +++ b/components/platform_console/cmd_system.c @@ -1,36 +1,41 @@ /* Console example — various system commands This example code is in the Public Domain (or CC0 licensed, at your option.) - + Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include -#include -#include "esp_log.h" -#include "esp_console.h" -#include "esp_system.h" -#include "esp_spi_flash.h" +#include "cmd_system.h" +#include "Config.h" +#include "argtable3/argtable3.h" +#include "bootstate.h" #include "driver/rtc_io.h" #include "driver/uart.h" -#include "argtable3/argtable3.h" +#include "esp_console.h" +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_partition.h" +#include "esp_rom_uart.h" +#include "esp_sleep.h" +#include "esp_spi_flash.h" +#include "esp_system.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "soc/rtc_cntl_reg.h" -#include "esp_rom_uart.h" -#include "cmd_system.h" -#include "sdkconfig.h" -#include "esp_partition.h" -#include "esp_ota_ops.h" -#include "platform_esp32.h" -#include "Configurator.h" -#include "esp_sleep.h" -#include "messaging.h" +#include "messaging.h" +#include "network_manager.h" #include "platform_console.h" +#include "platform_esp32.h" +#include "sdkconfig.h" +#include "soc/rtc_cntl_reg.h" #include "tools.h" +#include +#include +#include +#include "tools_spiffs_utils.h" + + #if defined(CONFIG_WITH_METRICS) #include "Metrics.h" #endif @@ -38,30 +43,58 @@ #ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS #pragma message("Runtime stats enabled") #define WITH_TASKS_INFO 1 -#else +#else #pragma message("Runtime stats disabled") #endif EXT_RAM_ATTR static struct { - struct arg_str * device; - // AirPlay device name - struct arg_str * airplay; - // Spotify device name - struct arg_str * spotify; - // Bluetooth player name advertized - struct arg_str * bluetooth; - // Player name reported to the Logitech Media Server - struct arg_str * squeezelite; - // Wifi Access Point name - struct arg_str * wifi_ap_name; - struct arg_lit * all; - struct arg_end *end; + struct arg_str* device; + // AirPlay device name + struct arg_str* airplay; + // Spotify device name + struct arg_str* spotify; + // Bluetooth player name advertized + struct arg_str* bluetooth; + // Player name reported to the Logitech Media Server + struct arg_str* squeezelite; + // Wifi Access Point name + struct arg_str* wifi_ap_name; + struct arg_lit* all; + struct arg_end* end; } names_args; +EXT_RAM_ATTR static struct { + struct arg_str* name; + struct arg_lit*reset; + struct arg_end* end; +} target_args; -static const char * TAG = "cmd_system"; +EXT_RAM_ATTR static struct { + struct arg_str* confirm; + struct arg_end* end; +} reset_config_args; + +// Global or static scope +EXT_RAM_ATTR static struct { + struct arg_str* path; + struct arg_end* end; +} ls_args; +// EXT_RAM_ATTR static struct { +// struct arg_str *component; +// struct arg_int *level; +// struct arg_end *end; +// } ls_level; + +// Global or static scope +EXT_RAM_ATTR static struct { + struct arg_str* path; + struct arg_end* end; +} erase_args; + +static const char* TAG = "cmd_system"; static void register_free(); static void register_setdevicename(); +static void register_settarget(); static void register_heap(); static void register_dump_heap(); static void register_version(); @@ -77,65 +110,35 @@ static void register_restart_ota(); static void register_tasks(); #endif extern BaseType_t network_manager_task; -FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size){ - FILE *f = open_memstream(buf, buf_size); - if (f == NULL) { - cmd_send_messaging(cmdname,MESSAGING_ERROR,"Unable to open memory stream."); - } +FILE* system_open_memstream(const char* cmdname, char** buf, size_t* buf_size) { + FILE* f = open_memstream(buf, buf_size); + if (f == NULL) { + cmd_send_messaging(cmdname, MESSAGING_ERROR, "Unable to open memory stream."); + } return f; } -void register_system() -{ - // register_set_services(); - register_setdevicename(); - register_free(); - register_heap(); - register_dump_heap(); - register_version(); - register_restart(); - register_factory_boot(); - register_restart_ota(); -#if WITH_TASKS_INFO - register_tasks(); -#endif -#if CONFIG_WITH_CONFIG_UI - register_deep_sleep(); - register_light_sleep(); -#endif -} -void simple_restart() -{ - log_send_messaging(MESSAGING_WARNING,"Rebooting."); - if(!configurator_waitcommit()){ - log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. "); - } - vTaskDelay(750/ portTICK_PERIOD_MS); - esp_restart(); -} /* 'version' command */ -static int get_version(int argc, char **argv) -{ +static int get_version(int argc, char** argv) { esp_chip_info_t info; esp_chip_info(&info); - cmd_send_messaging(argv[0],MESSAGING_INFO, - "IDF Version:%s\r\n" - "Chip info:\r\n" - "\tmodel:%s\r\n" - "\tcores:%d\r\n" - "\tfeature:%s%s%s%s%d%s\r\n" - "\trevision number:%d\r\n", - esp_get_idf_version(), info.model == CHIP_ESP32 ? "ESP32" : "Unknow", info.cores, - info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", - info.features & CHIP_FEATURE_BLE ? "/BLE" : "", - info.features & CHIP_FEATURE_BT ? "/BT" : "", - info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", - spi_flash_get_chip_size() / (1024 * 1024), " MB", info.revision); + cmd_send_messaging(argv[0], MESSAGING_INFO, + "IDF Version:%s\r\n" + "Chip info:\r\n" + "\tmodel:%s\r\n" + "\tcores:%d\r\n" + "\tfeature:%s%s%s%s%d%s\r\n" + "\trevision number:%d\r\n", + esp_get_idf_version(), info.model == CHIP_ESP32 ? "ESP32" : "Unknow", info.cores, + info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", + info.features & CHIP_FEATURE_BLE ? "/BLE" : "", + info.features & CHIP_FEATURE_BT ? "/BT" : "", + info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", + spi_flash_get_chip_size() / (1024 * 1024), " MB", info.revision); return 0; } -static void register_version() -{ +static void register_version() { const esp_console_cmd_t cmd = { .command = "version", .help = "Get version of chip and SDK", @@ -143,138 +146,69 @@ static void register_version() .func = &get_version, }; cmd_to_json(&cmd); - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) -{ - if(is_recovery_running){ - if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){ - // log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active"); - simple_restart(); - } - } - else { - if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){ - // log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active"); - simple_restart(); - } - } - esp_err_t err = ESP_OK; - // log_send_messaging(MESSAGING_INFO, "Looking for partition type %u",partition_subtype); - const esp_partition_t *partition; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL); - - if(it == NULL){ - log_send_messaging(MESSAGING_ERROR,"Reboot failed. Partitions error"); - } - else - { - ESP_LOGD(TAG, "Found partition. Getting info."); - partition = (esp_partition_t *) esp_partition_get(it); - ESP_LOGD(TAG, "Releasing partition iterator"); - esp_partition_iterator_release(it); - if(partition != NULL){ - log_send_messaging(MESSAGING_INFO, "Rebooting to %s", partition->label); - err=esp_ota_set_boot_partition(partition); - if(err!=ESP_OK){ - log_send_messaging(MESSAGING_ERROR,"Unable to select partition for reboot: %s",esp_err_to_name(err)); - } - } - else - { - log_send_messaging(MESSAGING_ERROR,"partition type %u not found! Unable to reboot to recovery.",partition_subtype); - - } - ESP_LOGD(TAG, "Yielding to other processes"); - taskYIELD(); - simple_restart(); - } - - return ESP_OK; -} - -static int restart(int argc, char **argv) -{ +static int restart(int argc, char** argv) { simple_restart(); return 0; } - - -esp_err_t guided_restart_ota(){ - log_send_messaging(MESSAGING_WARNING,"Booting to Squeezelite"); +static int restart_factory(int argc, char** argv) { + cmd_send_messaging(argv[0], MESSAGING_WARNING, "Booting to Recovery"); + guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); + return 0; // return fail. This should never return... we're rebooting! +} +static int restart_ota(int argc, char** argv) { + cmd_send_messaging(argv[0], MESSAGING_WARNING, "Booting to Squeezelite"); guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); - return ESP_FAIL; // return fail. This should never return... we're rebooting! + return 0; // return fail. This should never return... we're rebooting! } -esp_err_t guided_factory(){ - log_send_messaging(MESSAGING_WARNING,"Booting to recovery"); - guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); - return ESP_FAIL; // return fail. This should never return... we're rebooting! -} -static int restart_factory(int argc, char **argv) -{ - cmd_send_messaging(argv[0],MESSAGING_WARNING, "Booting to Recovery"); - guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); - return 0; // return fail. This should never return... we're rebooting! -} -static int restart_ota(int argc, char **argv) -{ - cmd_send_messaging(argv[0],MESSAGING_WARNING, "Booting to Squeezelite"); - guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); - return 0; // return fail. This should never return... we're rebooting! -} -static void register_restart() -{ +static void register_restart() { const esp_console_cmd_t cmd = { .command = "restart", .help = "Reboot system", .hint = NULL, .func = &restart, }; -#if CONFIG_WITH_CONFIG_UI +#if CONFIG_WITH_CONFIG_UI cmd_to_json(&cmd); -#endif - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); +#endif + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -static void register_restart_ota() -{ +static void register_restart_ota() { const esp_console_cmd_t cmd = { .command = "restart_ota", .help = "Reboot system to Squeezelite", .hint = NULL, .func = &restart_ota, }; -#if CONFIG_WITH_CONFIG_UI +#if CONFIG_WITH_CONFIG_UI cmd_to_json(&cmd); #endif - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -static void register_factory_boot() -{ +static void register_factory_boot() { const esp_console_cmd_t cmd = { .command = "recovery", .help = "Reboot system to Recovery", .hint = NULL, .func = &restart_factory, }; -#if CONFIG_WITH_CONFIG_UI +#if CONFIG_WITH_CONFIG_UI cmd_to_json(&cmd); #endif - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } /** 'free' command prints available heap memory */ -static int free_mem(int argc, char **argv) -{ - cmd_send_messaging(argv[0],MESSAGING_INFO,"%d", esp_get_free_heap_size()); +static int free_mem(int argc, char** argv) { + cmd_send_messaging(argv[0], MESSAGING_INFO, "%d", esp_get_free_heap_size()); return 0; } - -static void register_free() -{ +static void register_free() { const esp_console_cmd_t cmd = { .command = "free", .help = "Get free heap memory", @@ -285,61 +219,68 @@ static void register_free() cmd_to_json(&cmd); #endif - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -static int dump_heap(int argc, char **argv) -{ +static int dump_heap(int argc, char** argv) { ESP_LOGD(TAG, "Dumping heap"); heap_caps_dump_all(); return 0; } -/* 'heap' command prints minumum heap size */ -static int heap_size(int argc, char **argv) -{ - // ESP_LOGI(TAG,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)", - // heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - // heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - // heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), - // heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - // heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - // heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), - // heap_caps_get_free_size(MALLOC_CAP_DMA), - // heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), - // heap_caps_get_largest_free_block(MALLOC_CAP_DMA)); - cmd_send_messaging(argv[0],MESSAGING_INFO,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), - heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), - heap_caps_get_largest_free_block(MALLOC_CAP_DMA)); +static int dump_config(int argc, char** argv) { + ESP_LOGD(TAG, "Dumping config object"); + config_dump_config(); return 0; } -cJSON * setdevicename_cb(){ - // char * default_host_name = config_alloc_get_str("host_name",NULL,"Squeezelite"); - cJSON * values = cJSON_CreateObject(); - // cJSON_AddStringToObject(values,"name",default_host_name); - // free(default_host_name); - // TODO: Add support for the commented code") - return values; +/* 'heap' command prints minumum heap size */ +static int heap_size(int argc, char** argv) { + size_t total_internal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL); + size_t free_internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + size_t allocated_internal = total_internal - free_internal; + + size_t total_external = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); + size_t free_external = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); + size_t allocated_external = total_external - free_external; + + size_t total_dma = heap_caps_get_total_size(MALLOC_CAP_DMA); + size_t free_dma = heap_caps_get_free_size(MALLOC_CAP_DMA); + size_t allocated_dma = total_dma - free_dma; + + ESP_LOGI(TAG, + "\nType | TOTAL | ALLOC | MIN | LARGEST | FREE | USED %%| FREE %%\n" + "Internal | %7zu | %7zu | %7zu | %7zu | %7zu | %4.1f%% | %4.1f%%\n" + "External | %7zu | %7zu | %7zu | %7zu | %7zu | %4.1f%% | %4.1f%%\n" + "DMA | %7zu | %7zu | %7zu | %7zu | %7zu | %4.1f%% | %4.1f%%", + total_internal, allocated_internal, heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), free_internal, + (allocated_internal * 100.0) / total_internal, (free_internal * 100.0) / total_internal, + total_external, allocated_external, heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), free_external, + (allocated_external * 100.0) / total_external, (free_external * 100.0) / total_external, + total_dma, allocated_dma, heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), + heap_caps_get_largest_free_block(MALLOC_CAP_DMA), free_dma, + (allocated_dma * 100.0) / total_dma, (free_dma * 100.0) / total_dma); + + return 0; } -static int setnamevar(char * nvsname, FILE *f, char * value){ - esp_err_t err=ESP_OK; - // if((err=config_set_value(NVS_TYPE_STR, nvsname, value))!=ESP_OK){ - // fprintf(f,"Unable to set %s=%s. %s\n",nvsname,value,esp_err_to_name(err)); - // } +cJSON* setdevicename_cb() { + // char * default_host_name = config_alloc_get_str("host_name",NULL,"Squeezelite"); + cJSON* values = cJSON_CreateObject(); + // cJSON_AddStringToObject(values,"name",default_host_name); + // free(default_host_name); // TODO: Add support for the commented code") - return err==ESP_OK?0:1; + return values; } -typedef enum { - SCANNING, - PROCESSING_NAME -} scanstate_t; -int set_cspot_player_name(FILE * f,const char * name){ - int ret=0; +static int setnamevar(char* nvsname, FILE* f, char* value) { + esp_err_t err = ESP_OK; + // if((err=config_set_value(NVS_TYPE_STR, nvsname, value))!=ESP_OK){ + // fprintf(f,"Unable to set %s=%s. %s\n",nvsname,value,esp_err_to_name(err)); + // } + // TODO: Add support for the commented code") + return err == ESP_OK ? 0 : 1; +} +typedef enum { SCANNING, PROCESSING_NAME } scanstate_t; +int set_cspot_player_name(FILE* f, const char* name) { + int ret = 0; // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); // if(cspot_config==NULL){ // fprintf(f,"Unable to get cspot_config\n"); @@ -368,11 +309,11 @@ int set_cspot_player_name(FILE * f,const char * name){ // TODO: Add support for the commented code") return ret; } -int set_squeezelite_player_name(FILE * f,const char * name){ - int nerrors=0; +int set_squeezelite_player_name(FILE* f, const char* name) { + int nerrors = 0; // TODO: Add support for the commented code") // char * nvs_config= config_alloc_get(NVS_TYPE_STR, "autoexec1"); - // char **argv = NULL; + // char **argv = NULL; // esp_err_t err=ESP_OK; // bool bFoundParm=false; // scanstate_t state=SCANNING; @@ -384,18 +325,18 @@ int set_squeezelite_player_name(FILE * f,const char * name){ // *p='_'; // no spaces allowed // } // } - // if(nvs_config && strlen(nvs_config)>0){ + // if(nvs_config && strlen(nvs_config)>0){ // // allocate enough memory to hold the new command line // size_t cmdLength = strlen(nvs_config) + strlen(cleaned_name) + strlen(parm) +1 ; // newCommandLine = malloc_init_external(cmdLength); // ESP_LOGD(TAG,"Parsing command %s",nvs_config); - // argv = (char **) malloc_init_external(22* sizeof(char *)); - // if (argv == NULL) { - // FREE_AND_NULL(nvs_config); - // return 1; - // } - // size_t argc = esp_console_split_argv(nvs_config, argv,22); - // for(int i=0;i0){ // strcat(newCommandLine," "); // } @@ -412,7 +353,7 @@ int set_squeezelite_player_name(FILE * f,const char * name){ // strcat(newCommandLine,cleaned_name); // state = SCANNING; // break; - + // default: // break; // } @@ -426,67 +367,178 @@ int set_squeezelite_player_name(FILE * f,const char * name){ // nerrors++; // fprintf(f,"Failed updating squeezelite command. %s", esp_err_to_name(err)); // } - - // } - // FREE_AND_NULL(nvs_config); - // FREE_AND_NULL(argv); - // free(cleaned_name); - return nerrors; - + // } + + // FREE_AND_NULL(nvs_config); + // FREE_AND_NULL(argv); + // free(cleaned_name); + return nerrors; } -static int setdevicename(int argc, char **argv) -{ - bool changed = false; - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&names_args); + +static int do_cat(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&ls_args); + if (nerrors != 0) { + arg_print_errors(stderr, ls_args.end, argv[0]); + return 1; + } + + // List files in the provided path + cat_file(ls_args.path->sval[0]); + + return 0; +} +static int do_ls(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&ls_args); + if (nerrors != 0) { + arg_print_errors(stderr, ls_args.end, argv[0]); + return 1; + } + + // List files in the provided path + listFiles(ls_args.path->sval[0]); + + return 0; +} +// static int do_level(int argc, char **argv) +// { +// int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr **)&ls_level); +// if (nerrors != 0) { +// arg_print_errors(stderr, ls_level.end, argv[0]); +// return 1; +// } +// if(ls_level.component->count >0 && ls_level.level->count == 0){ +// // loop on ls_level.component->sval[i], and call +// } + +// return 0; +// } +static int do_erase(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&erase_args); + if (nerrors != 0) { + arg_print_errors(stderr, erase_args.end, argv[0]); + return 1; + } + + // Erase file at the provided path + const char* path = erase_args.path->sval[0]; + if (!erase_path(path, true)) { + // Handle error if erase_path returns false + // For example, log an error message + fprintf(stderr, "Failed to erase file at path: %s\n", path); + return 1; + } + + // Optionally, print a success message + printf("File at path '%s' erased successfully.\n", path); + + return 0; +} + +static int do_set_target(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&target_args); if (nerrors != 0) { return 1; } - if (names_args.device->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_device_tag, &platform->names,names_args.device->sval[0]); - } - else { - ESP_LOGE(TAG,"Device name must be specified"); - return 1; - } - if (names_args.airplay->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_airplay_tag, &platform->names,names_args.airplay->sval[0]); + if (target_args.name->count <= 0) { + ESP_LOGW(TAG, "Target name must be specified. Current target: %s", + STR_OR_ALT(platform->target, "N/A")); + return 1; } + network_async_callback((void*)target_args.name->sval[0], (network_manager_cb_t)(target_args.reset->count>0?config_set_target_reset:config_set_target_no_reset)); - if (names_args.bluetooth->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_bluetooth_tag, &platform->names,names_args.bluetooth->sval[0]); - } - if (names_args.spotify->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_spotify_tag, &platform->names,names_args.spotify->sval[0]); - } - if (names_args.squeezelite->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_squeezelite_tag, &platform->names,names_args.squeezelite->sval[0]); - } - if (names_args.wifi_ap_name->count >0){ - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_wifi_ap_name_tag, &platform->names,names_args.wifi_ap_name->sval[0]); - } - if (names_args.all->count >0){ - ESP_LOGI(TAG,"Setting all names to %s", platform->names.device); - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_airplay_tag, &platform->names,platform->names.device); - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_bluetooth_tag, &platform->names,platform->names.device); - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_spotify_tag, &platform->names,platform->names.device); - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_squeezelite_tag, &platform->names,platform->names.device); - changed = changed | configurator_set_string(&sys_Names_msg,sys_Names_wifi_ap_name_tag, &platform->names,platform->names.device); - } - if(changed){ - ESP_LOGI(TAG,"Found change(s). Saving"); - configurator_raise_changed(); - } - else { - ESP_LOGW(TAG,"No change detected."); - } - - return nerrors; - + return nerrors; } -static void register_heap() -{ +static int do_reset_config(int argc, char** argv) { + + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&reset_config_args); + if (nerrors != 0) { + return 1; + } + if (reset_config_args.confirm->count <= 0 || + strcmp(reset_config_args.confirm->sval[0], "YES") != 0) { + ESP_LOGW(TAG, "Confirmation needed. Call reset_config YES to confirm"); + return 1; + } + set_mac_string(); + // the below call will restart to factory + config_erase_config(); + return nerrors; +} + +static void register_reset_config() { + reset_config_args.confirm = + arg_str0(NULL, NULL, "YES", "To execute the reset, confirm with YES"); + reset_config_args.end = arg_end(1); + + const esp_console_cmd_t reset_config = {.command = "reset_config", + .help = "Reset the configuration and reboot to recovery", + .hint = NULL, + .func = &do_reset_config, + .argtable = &reset_config_args}; + + ESP_ERROR_CHECK(esp_console_cmd_register(&reset_config)); +} + +static int setdevicename(int argc, char** argv) { + bool changed = false; + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&names_args); + if (nerrors != 0) { + return 1; + } + if (names_args.device->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_device_tag, + &platform->names, names_args.device->sval[0]); + } else { + ESP_LOGE(TAG, "Device name must be specified"); + return 1; + } + if (names_args.airplay->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, + &platform->names, names_args.airplay->sval[0]); + } + + if (names_args.bluetooth->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, + &platform->names, names_args.bluetooth->sval[0]); + } + if (names_args.spotify->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, + &platform->names, names_args.spotify->sval[0]); + } + if (names_args.squeezelite->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, + &platform->names, names_args.squeezelite->sval[0]); + } + if (names_args.wifi_ap_name->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, + &platform->names, names_args.wifi_ap_name->sval[0]); + } + if (names_args.all->count > 0) { + ESP_LOGI(TAG, "Setting all names to %s", platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, + &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, + &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, + &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, + &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, + &platform->names, platform->names.device); + } + if (changed) { + ESP_LOGI(TAG, "Found change(s). Saving"); + config_raise_changed(false); + } else { + ESP_LOGW(TAG, "No change detected."); + } + + return nerrors; +} + +static void register_heap() { const esp_console_cmd_t heap_cmd = { .command = "heap", .help = "Get minimum size of free heap memory", @@ -495,160 +547,221 @@ static void register_heap() }; #if CONFIG_WITH_CONFIG_UI cmd_to_json(&heap_cmd); -#endif - ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); - +#endif + ESP_ERROR_CHECK(esp_console_cmd_register(&heap_cmd)); } -static void register_dump_heap() -{ +static void register_dump_heap() { const esp_console_cmd_t heap_cmd = { .command = "dump_heap", .help = "Dumps the content of the heap to serial output", .hint = NULL, .func = &dump_heap, }; - ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&heap_cmd)); +} +static void register_dump_config() { + const esp_console_cmd_t cmd = { + .command = "dump_config", + .help = "Dumps the content of the configuration object", + .hint = NULL, + .func = &dump_config, + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} +static void register_settarget() { + target_args.name = arg_str0(NULL, NULL, STR_OR_BLANK(platform->target), "New Target Name"); + target_args.reset = arg_lit0("r","reset","Full reset before setting target (recommended)"); + target_args.end = arg_end(1); + const esp_console_cmd_t set_target = {.command = "target", + .help = "Set the device target Name (SqueezeAMP, SqueezeIO, Muse, etc. )", + .hint = NULL, + .func = &do_set_target, + .argtable = &target_args}; + ESP_ERROR_CHECK(esp_console_cmd_register(&set_target)); } -static void register_setdevicename() -{ - char * default_host_name = platform->names.device; - names_args.device = arg_str0("n", "device", default_host_name, "New Name"); +// static void register_loglevel() +// { +// ls_level.component = arg_str1(NULL, NULL, "", "Component name for which to set log +// level. * for all components"); ls_level.level = arg_str1(NULL, NULL, "", +// "NONE=0, ERROR=1, WARN=2, INFO=3, DEBUG=4, VERBOSE=5"); ls_args.end = arg_end(1); const +// esp_console_cmd_t ls_cmd = { +// .command = "ls", +// .help = "List files in a path", +// .hint = NULL, +// .func = &do_level, +// .argtable = &ls_level +// }; + +// ESP_ERROR_CHECK(esp_console_cmd_register(&ls_cmd)); +// } + +static void register_ls() { + ls_args.path = arg_str1(NULL, NULL, "", "Path to list files"); + ls_args.end = arg_end(1); + const esp_console_cmd_t ls_cmd = {.command = "ls", + .help = "List files in a path", + .hint = NULL, + .func = &do_ls, + .argtable = &ls_args}; + + ESP_ERROR_CHECK(esp_console_cmd_register(&ls_cmd)); +} +static void register_cat() { + ls_args.path = arg_str1(NULL, NULL, "", "File name to cat"); + ls_args.end = arg_end(1); + const esp_console_cmd_t cat_cmd = {.command = "cat", + .help = "Dumps the content of a file to the console", + .hint = NULL, + .func = &do_cat, + .argtable = &ls_args}; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cat_cmd)); +} + +static void register_erase() { + erase_args.path = arg_str1(NULL, NULL, "", "Path of the file(s) to erase"); + erase_args.end = arg_end(1); + const esp_console_cmd_t erase_cmd = {.command = "erase", + .help = "Erase file(s) at a given path", + .hint = NULL, + .func = &do_erase, + .argtable = &erase_args}; + + ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd)); +} + +static void register_setdevicename() { + char* default_host_name = platform->names.device; + names_args.device = arg_str0("n", "device", default_host_name, "New Name"); names_args.airplay = arg_str0("a", "airplay", default_host_name, "New Airplay Device Name"); names_args.bluetooth = arg_str0("b", "bt", default_host_name, "New Bluetooth Device Name"); names_args.spotify = arg_str0("s", "spotify", default_host_name, "New Spotify Device Name"); - names_args.squeezelite = arg_str0("l", "squeezelite", default_host_name, "New Squeezelite Player Name"); + names_args.squeezelite = + arg_str0("l", "squeezelite", default_host_name, "New Squeezelite Player Name"); names_args.wifi_ap_name = arg_str0("w", "wifiap", default_host_name, "New Wifi AP Name"); names_args.all = arg_lit0(NULL, "all", "Set all names to device name"); - names_args.end = arg_end(2); - const esp_console_cmd_t set_name= { - .command = CFG_TYPE_SYST("name"), - .help="Device Name", - .hint = NULL, - .func = &setdevicename, - .argtable = &names_args - }; + names_args.end = arg_end(2); + const esp_console_cmd_t set_name = {.command = CFG_TYPE_SYST("name"), + .help = "Device Name", + .hint = NULL, + .func = &setdevicename, + .argtable = &names_args}; - ESP_ERROR_CHECK(esp_console_cmd_register(&set_name)); + ESP_ERROR_CHECK(esp_console_cmd_register(&set_name)); } /** 'tasks' command prints the list of tasks and related information */ #if WITH_TASKS_INFO -static int tasks_info(int argc, char **argv) -{ +static int tasks_info(int argc, char** argv) { const size_t bytes_per_task = 40; /* see vTaskList description */ - char *task_list_buffer = malloc_init_external(uxTaskGetNumberOfTasks() * bytes_per_task); + char* task_list_buffer = malloc_init_external(uxTaskGetNumberOfTasks() * bytes_per_task); if (task_list_buffer == NULL) { - cmd_send_messaging(argv[0],MESSAGING_ERROR, "failed to allocate buffer for vTaskList output"); + cmd_send_messaging( + argv[0], MESSAGING_ERROR, "failed to allocate buffer for vTaskList output"); return 1; } - cmd_send_messaging(argv[0],MESSAGING_INFO,"Task Name\tStatus\tPrio\tHWM\tTask#" + cmd_send_messaging(argv[0], MESSAGING_INFO, + "Task Name\tStatus\tPrio\tHWM\tTask#" #ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID - "\tAffinity" + "\tAffinity" #endif - "\n"); + "\n"); vTaskList(task_list_buffer); - cmd_send_messaging(argv[0],MESSAGING_INFO,"%s", task_list_buffer); + cmd_send_messaging(argv[0], MESSAGING_INFO, "%s", task_list_buffer); free(task_list_buffer); return 0; } -static void register_tasks() -{ +static void register_tasks() { const esp_console_cmd_t cmd = { .command = "tasks", .help = "Get information about running tasks", .hint = NULL, .func = &tasks_info, }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } #endif // WITH_TASKS_INFO - /** 'deep_sleep' command puts the chip into deep sleep mode */ #if CONFIG_WITH_CONFIG_UI static struct { - struct arg_int *wakeup_time; - struct arg_int *wakeup_gpio_num; - struct arg_int *wakeup_gpio_level; - struct arg_end *end; + struct arg_int* wakeup_time; + struct arg_int* wakeup_gpio_num; + struct arg_int* wakeup_gpio_level; + struct arg_end* end; } deep_sleep_args; - -static int deep_sleep(int argc, char **argv) -{ - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&deep_sleep_args); +static int deep_sleep(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&deep_sleep_args); if (nerrors != 0) { return 1; } if (deep_sleep_args.wakeup_time->count) { uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0]; - cmd_send_messaging(argv[0],MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); - ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); + cmd_send_messaging( + argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); + ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(timeout)); } if (deep_sleep_args.wakeup_gpio_num->count) { int io_num = deep_sleep_args.wakeup_gpio_num->ival[0]; if (!rtc_gpio_is_valid_gpio(io_num)) { - cmd_send_messaging(argv[0],MESSAGING_ERROR, "GPIO %d is not an RTC IO", io_num); + cmd_send_messaging(argv[0], MESSAGING_ERROR, "GPIO %d is not an RTC IO", io_num); return 1; } int level = 0; if (deep_sleep_args.wakeup_gpio_level->count) { level = deep_sleep_args.wakeup_gpio_level->ival[0]; if (level != 0 && level != 1) { - cmd_send_messaging(argv[0],MESSAGING_ERROR, "Invalid wakeup level: %d", level); + cmd_send_messaging(argv[0], MESSAGING_ERROR, "Invalid wakeup level: %d", level); return 1; } } - cmd_send_messaging(argv[0],MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", + io_num, level ? "HIGH" : "LOW"); - ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) ); + ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(1ULL << io_num, level)); } rtc_gpio_isolate(GPIO_NUM_12); esp_deep_sleep_start(); return 0; // this code will never run. deep sleep will cause the system to restart } -static void register_deep_sleep() -{ - deep_sleep_args.wakeup_time = - arg_int0("t", "time", "", "Wake up time, ms"); +static void register_deep_sleep() { + deep_sleep_args.wakeup_time = arg_int0("t", "time", "", "Wake up time, ms"); deep_sleep_args.wakeup_gpio_num = - arg_int0(NULL, "io", "", - "If specified, wakeup using GPIO with given number"); + arg_int0(NULL, "io", "", "If specified, wakeup using GPIO with given number"); deep_sleep_args.wakeup_gpio_level = arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup"); deep_sleep_args.end = arg_end(3); - const esp_console_cmd_t cmd = { - .command = "deep_sleep", + const esp_console_cmd_t cmd = {.command = "deep_sleep", .help = "Enter deep sleep mode. ", .hint = NULL, .func = &deep_sleep, - .argtable = &deep_sleep_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + .argtable = &deep_sleep_args}; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } #endif -static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ - esp_err_t err = ESP_OK; +static int enable_disable(FILE* f, char* nvs_name, struct arg_lit* arg) { + esp_err_t err = ESP_OK; // err= config_set_value(NVS_TYPE_STR, nvs_name, arg->count>0?"Y":"N"); - // const char * name = arg->hdr.longopts?arg->hdr.longopts:arg->hdr.glossary; + // const char * name = arg->hdr.longopts?arg->hdr.longopts:arg->hdr.glossary; - // if(err!=ESP_OK){ - // fprintf(f,"Error %s %s. %s\n",arg->count>0?"Enabling":"Disabling", name, esp_err_to_name(err)); - // } - // else { - // fprintf(f,"%s %s\n",arg->count>0?"Enabled":"Disabled",name); - // } - return err; + // if(err!=ESP_OK){ + // fprintf(f,"Error %s %s. %s\n",arg->count>0?"Enabling":"Disabling", name, + // esp_err_to_name(err)); + // } + // else { + // fprintf(f,"%s %s\n",arg->count>0?"Enabled":"Disabled",name); + // } + return err; } // static int do_set_services(int argc, char **argv) @@ -667,14 +780,14 @@ static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ // nerrors += enable_disable(f,"enable_airplay",set_services_args.airplay); // nerrors += enable_disable(f,"enable_bt_sink",set_services_args.btspeaker); -// #if CONFIG_CSPOT_SINK +// #if CONFIG_CSPOT_SINK // nerrors += enable_disable(f,"enable_cspot",set_services_args.cspot); -// #endif +// #endif // if(set_services_args.telnet->count>0){ // // if(strcasecmp(set_services_args.telnet->sval[0],"Disabled") == 0){ // // err = config_set_value(NVS_TYPE_STR, "telnet_enable", "N"); -// // } +// // } // // else if(strcasecmp(set_services_args.telnet->sval[0],"Telnet Only") == 0){ // // err = config_set_value(NVS_TYPE_STR, "telnet_enable", "Y"); // // } @@ -684,14 +797,15 @@ static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ // // TODO: Add support for the commented code") // if(err!=ESP_OK){ // nerrors++; -// fprintf(f,"Error setting telnet to %s. %s\n",set_services_args.telnet->sval[0], esp_err_to_name(err)); +// fprintf(f,"Error setting telnet to %s. %s\n",set_services_args.telnet->sval[0], +// esp_err_to_name(err)); // } // else { // fprintf(f,"Telnet service changed to %s\n",set_services_args.telnet->sval[0]); // } // } -// #if WITH_TASKS_INFO +// #if WITH_TASKS_INFO // nerrors += enable_disable(f,"stats",set_services_args.stats); // #endif // if(!nerrors ){ @@ -704,24 +818,25 @@ static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ // return nerrors; // } - // cJSON * set_services_cb(){ // cJSON * values = cJSON_CreateObject(); // char * p=NULL; // console_set_bool_parameter(values,"enable_bt_sink",set_services_args.btspeaker); // console_set_bool_parameter(values,"enable_airplay",set_services_args.airplay); -// #if CONFIG_CSPOT_SINK +// #if CONFIG_CSPOT_SINK // console_set_bool_parameter(values,"enable_cspot",set_services_args.cspot); // #endif -// #if WITH_TASKS_INFO +// #if WITH_TASKS_INFO // console_set_bool_parameter(values,"stats",set_services_args.stats); // #endif // // if ((p = config_alloc_get(NVS_TYPE_STR, "telnet_enable")) != NULL) { // // if(strcasestr("YX",p)!=NULL){ -// // cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet Only"); +// // cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet +// Only"); // // } // // else if(strcasestr("D",p)!=NULL){ -// // cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet and Serial"); +// // cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet and +// Serial"); // // } // // else { // // cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Disabled"); @@ -737,14 +852,14 @@ static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ // static void register_set_services(){ // set_services_args.airplay = arg_lit0(NULL, "AirPlay", "AirPlay"); -// #if CONFIG_CSPOT_SINK +// #if CONFIG_CSPOT_SINK // set_services_args.cspot = arg_lit0(NULL, "cspot", "Spotify (cspot)"); // #endif // set_services_args.btspeaker = arg_lit0(NULL, "BT_Speaker", "Bluetooth Speaker"); -// set_services_args.telnet= arg_str0("t", "telnet","Disabled|Telnet Only|Telnet and Serial","Telnet server. Use only for troubleshooting"); -// #if WITH_TASKS_INFO -// set_services_args.stats= arg_lit0(NULL, "stats", "System Statistics. Use only for troubleshooting"); -// #endif +// set_services_args.telnet= arg_str0("t", "telnet","Disabled|Telnet Only|Telnet and +// Serial","Telnet server. Use only for troubleshooting"); #if WITH_TASKS_INFO +// set_services_args.stats= arg_lit0(NULL, "stats", "System Statistics. Use only for +// troubleshooting"); #endif // set_services_args.end=arg_end(2); // const esp_console_cmd_t cmd = { // .command = CFG_TYPE_SYST("services"), @@ -759,54 +874,57 @@ static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){ #if CONFIG_WITH_CONFIG_UI static struct { - struct arg_int *wakeup_time; - struct arg_int *wakeup_gpio_num; - struct arg_int *wakeup_gpio_level; - struct arg_end *end; + struct arg_int* wakeup_time; + struct arg_int* wakeup_gpio_num; + struct arg_int* wakeup_gpio_level; + struct arg_end* end; } light_sleep_args; -static int light_sleep(int argc, char **argv) -{ - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&light_sleep_args); +static int light_sleep(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&light_sleep_args); if (nerrors != 0) { return 1; } esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); if (light_sleep_args.wakeup_time->count) { uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0]; - cmd_send_messaging(argv[0],MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); - ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) ); + cmd_send_messaging( + argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); + ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(timeout)); } int io_count = light_sleep_args.wakeup_gpio_num->count; if (io_count != light_sleep_args.wakeup_gpio_level->count) { - cmd_send_messaging(argv[0],MESSAGING_INFO, "Should have same number of 'io' and 'io_level' arguments"); + cmd_send_messaging( + argv[0], MESSAGING_INFO, "Should have same number of 'io' and 'io_level' arguments"); return 1; } for (int i = 0; i < io_count; ++i) { int io_num = light_sleep_args.wakeup_gpio_num->ival[i]; int level = light_sleep_args.wakeup_gpio_level->ival[i]; if (level != 0 && level != 1) { - cmd_send_messaging(argv[0],MESSAGING_ERROR, "Invalid wakeup level: %d", level); + cmd_send_messaging(argv[0], MESSAGING_ERROR, "Invalid wakeup level: %d", level); return 1; } - cmd_send_messaging(argv[0],MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", + io_num, level ? "HIGH" : "LOW"); - ESP_ERROR_CHECK( gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL) ); + ESP_ERROR_CHECK( + gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL)); } if (io_count > 0) { - ESP_ERROR_CHECK( esp_sleep_enable_gpio_wakeup() ); + ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup()); } if (CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) { - cmd_send_messaging(argv[0],MESSAGING_INFO, "Enabling UART wakeup (press ENTER to exit light sleep)"); - ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) ); - ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) ); + cmd_send_messaging( + argv[0], MESSAGING_INFO, "Enabling UART wakeup (press ENTER to exit light sleep)"); + ESP_ERROR_CHECK(uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3)); + ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM)); } fflush(stdout); esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); esp_light_sleep_start(); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - const char *cause_str; + const char* cause_str; switch (cause) { case ESP_SLEEP_WAKEUP_GPIO: cause_str = "GPIO"; @@ -821,32 +939,54 @@ static int light_sleep(int argc, char **argv) cause_str = "unknown"; printf("%d\n", cause); } - cmd_send_messaging(argv[0],MESSAGING_INFO, "Woke up from: %s", cause_str); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Woke up from: %s", cause_str); return 0; } -static void register_light_sleep() -{ - light_sleep_args.wakeup_time = - arg_int0("t", "time", "", "Wake up time, ms"); +static void register_light_sleep() { + light_sleep_args.wakeup_time = arg_int0("t", "time", "", "Wake up time, ms"); light_sleep_args.wakeup_gpio_num = - arg_intn(NULL, "io", "", 0, 8, - "If specified, wakeup using GPIO with given number"); + arg_intn(NULL, "io", "", 0, 8, "If specified, wakeup using GPIO with given number"); light_sleep_args.wakeup_gpio_level = arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup"); light_sleep_args.end = arg_end(3); - const esp_console_cmd_t cmd = { - .command = "light_sleep", + const esp_console_cmd_t cmd = {.command = "light_sleep", .help = "Enter light sleep mode. " - "Two wakeup modes are supported: timer and GPIO. " - "Multiple GPIO pins can be specified using pairs of " - "'io' and 'io_level' arguments. " - "Will also wake up on UART input.", + "Two wakeup modes are supported: timer and GPIO. " + "Multiple GPIO pins can be specified using pairs of " + "'io' and 'io_level' arguments. " + "Will also wake up on UART input.", .hint = NULL, .func = &light_sleep, - .argtable = &light_sleep_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + .argtable = &light_sleep_args}; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } #endif + +void register_system() { + + // register_set_services(); + // register_loglevel(); + register_reset_config(); + register_setdevicename(); + register_free(); + register_heap(); + register_dump_heap(); + register_version(); + register_restart(); + register_factory_boot(); + register_restart_ota(); + register_ls(); + register_cat(); + register_settarget(); + register_erase(); + register_dump_config(); +#if WITH_TASKS_INFO + register_tasks(); +#endif +#if CONFIG_WITH_CONFIG_UI + register_deep_sleep(); + register_light_sleep(); +#endif +} \ No newline at end of file diff --git a/components/platform_console/cmd_system.h b/components/platform_console/cmd_system.h index c920f67f..c13471c7 100644 --- a/components/platform_console/cmd_system.h +++ b/components/platform_console/cmd_system.h @@ -14,9 +14,7 @@ extern "C" { // Register system functions void register_system(); -esp_err_t guided_factory(); -esp_err_t guided_restart_ota(); -void simple_restart(); + FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size); #ifdef __cplusplus } diff --git a/components/platform_console/cmd_wifi.c b/components/platform_console/cmd_wifi.c index ef0033ec..453fe897 100644 --- a/components/platform_console/cmd_wifi.c +++ b/components/platform_console/cmd_wifi.c @@ -54,7 +54,7 @@ static struct { -// todo: implement access point config - cmd_to_json(&i2cdetect_cmd); + static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) diff --git a/components/platform_console/platform_console.c b/components/platform_console/platform_console.c index cc87f018..5982eff8 100644 --- a/components/platform_console/platform_console.c +++ b/components/platform_console/platform_console.c @@ -9,24 +9,24 @@ #include "platform_console.h" +#include "argtable3/argtable3.h" +#include "bootstate.h" +#include "cmd_decl.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_log.h" +#include "esp_vfs_dev.h" +#include "linenoise/linenoise.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "platform_esp32.h" +#include "pthread.h" +#include "trace.h" #include #include #include -#include "esp_log.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" -#include "driver/uart.h" -#include "linenoise/linenoise.h" -#include "argtable3/argtable3.h" -#include "nvs.h" -#include "nvs_flash.h" -#include "pthread.h" -#include "platform_esp32.h" -#include "cmd_decl.h" -#include "trace.h" -// #include "Configurator.h" -#pragma message("fixme: search for TODO below") -#include "telnet.h" + +#include "telnet.h" #include "tools.h" #if defined(CONFIG_WITH_METRICS) #include "metrics.h" @@ -35,19 +35,19 @@ #include "config.h" static pthread_t thread_console; -static void * console_thread(); +static void* console_thread(); void console_start(); -static const char * TAG = "console"; +static const char* TAG = "console"; extern bool bypass_network_manager; extern void launchsqueezelite(); static EXT_RAM_ATTR QueueHandle_t uart_queue; static EXT_RAM_ATTR struct { - uint8_t _buf[512]; - StaticRingbuffer_t _ringbuf; - RingbufHandle_t handle; - QueueSetHandle_t queue_set; -} stdin_redir; + uint8_t _buf[512]; + StaticRingbuffer_t _ringbuf; + RingbufHandle_t handle; + QueueSetHandle_t queue_set; +} stdin_redir; /* Prompt to be printed before each line. * This can be customized, made dynamic, etc. @@ -62,94 +62,99 @@ const char* recovery_prompt = LOG_COLOR_E "recovery-squeezelite-esp32> " LOG_RES #define MOUNT_PATH "/data" #define HISTORY_PATH MOUNT_PATH "/history.txt" -static esp_err_t run_command(char * line); -#define ADD_TO_JSON(o,t,n) if (t->n) cJSON_AddStringToObject(o,QUOTE(n),t->n); -#define ADD_PARMS_TO_CMD(o,t,n) { cJSON * parms = ParmsToJSON(&t.n->hdr); if(parms) cJSON_AddItemToObject(o,QUOTE(n),parms); } -cJSON * cmdList; -cJSON * values_fn_list; -cJSON * get_cmd_list(){ - cJSON * element; - cJSON * values=cJSON_CreateObject(); - cJSON * list = cJSON_CreateObject(); - cJSON_AddItemReferenceToObject(list,"commands",cmdList); - cJSON_AddItemToObject(list,"values",values); - cJSON_ArrayForEach(element,cmdList){ - cJSON * name = cJSON_GetObjectItem(element,"name"); - cJSON * vals_fn = cJSON_GetObjectItem(values_fn_list,cJSON_GetStringValue(name)); - if(vals_fn!=NULL ){ - parm_values_fn_t *parm_values_fn = (parm_values_fn_t *)strtoul(cJSON_GetStringValue(vals_fn), NULL, 16);; +static esp_err_t run_command(char* line); +#define ADD_TO_JSON(o, t, n) \ + if (t->n) cJSON_AddStringToObject(o, QUOTE(n), t->n); +#define ADD_PARMS_TO_CMD(o, t, n) \ + { \ + cJSON* parms = ParmsToJSON(&t.n->hdr); \ + if (parms) cJSON_AddItemToObject(o, QUOTE(n), parms); \ + } +cJSON* cmdList; +cJSON* values_fn_list; +cJSON* get_cmd_list() { + cJSON* element; + cJSON* values = cJSON_CreateObject(); + cJSON* list = cJSON_CreateObject(); + cJSON_AddItemReferenceToObject(list, "commands", cmdList); + cJSON_AddItemToObject(list, "values", values); + cJSON_ArrayForEach(element, cmdList) { + cJSON* name = cJSON_GetObjectItem(element, "name"); + cJSON* vals_fn = cJSON_GetObjectItem(values_fn_list, cJSON_GetStringValue(name)); + if (vals_fn != NULL) { + parm_values_fn_t* parm_values_fn = (parm_values_fn_t*)strtoul(cJSON_GetStringValue(vals_fn), NULL, 16); + ; - if(parm_values_fn){ - cJSON_AddItemToObject(values,cJSON_GetStringValue(name),parm_values_fn()); - } - } - } - return list; + if (parm_values_fn) { + cJSON_AddItemToObject(values, cJSON_GetStringValue(name), parm_values_fn()); + } + } + } + return list; } -void console_set_bool_parameter(cJSON * root,char * nvs_name, struct arg_lit *arg){ - char * p=NULL; - bool enabled = false; - if(!root) { - ESP_LOGE(TAG,"Invalid json parameter. Cannot set %s from %s",arg->hdr.longopts?arg->hdr.longopts:arg->hdr.glossary,nvs_name); +void console_set_bool_parameter(cJSON* root, char* nvs_name, struct arg_lit* arg) { + char* p = NULL; + bool enabled = false; + if (!root) { + ESP_LOGE(TAG, "Invalid json parameter. Cannot set %s from %s", arg->hdr.longopts ? arg->hdr.longopts : arg->hdr.glossary, nvs_name); return; } -// if ((p = config_alloc_get(NVS_TYPE_STR, nvs_name)) != NULL) { -// enabled = strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0; -// cJSON_AddBoolToObject(root,arg->hdr.longopts,enabled); -// FREE_AND_NULL(p); -// } -// #if defined(CONFIG_WITH_METRICS) -// if(enabled){ -// metrics_add_feature(nvs_name,"enabled"); -// } -// #endif -// TODO: Add support for the commented code - + // if ((p = config_alloc_get(NVS_TYPE_STR, nvs_name)) != NULL) { + // enabled = strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0; + // cJSON_AddBoolToObject(root,arg->hdr.longopts,enabled); + // FREE_AND_NULL(p); + // } + // #if defined(CONFIG_WITH_METRICS) + // if(enabled){ + // metrics_add_feature(nvs_name,"enabled"); + // } + // #endif + // TODO: Add support for the commented code } -struct arg_end *getParmsEnd(struct arg_hdr * * argtable){ - if(!argtable) return NULL; - struct arg_hdr * *table = (struct arg_hdr * *)argtable; - int tabindex = 0; - while (!(table[tabindex]->flag & ARG_TERMINATOR)) - { - tabindex++; - } - return (struct arg_end *)table[tabindex]; +struct arg_end* getParmsEnd(struct arg_hdr** argtable) { + if (!argtable) return NULL; + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex = 0; + while (!(table[tabindex]->flag & ARG_TERMINATOR)) { + tabindex++; + } + return (struct arg_end*)table[tabindex]; } -cJSON * ParmsToJSON(struct arg_hdr * * argtable){ - if(!argtable) return NULL; - cJSON * arg_list = cJSON_CreateArray(); - struct arg_hdr * *table = (struct arg_hdr * *)argtable; - int tabindex = 0; - while (!(table[tabindex]->flag & ARG_TERMINATOR)) - { - cJSON * entry = cJSON_CreateObject(); - ADD_TO_JSON(entry,table[tabindex],datatype); - ADD_TO_JSON(entry,table[tabindex],glossary); - ADD_TO_JSON(entry,table[tabindex],longopts); - ADD_TO_JSON(entry,table[tabindex],shortopts); - cJSON_AddBoolToObject(entry, "checkbox", (table[tabindex]->flag & ARG_HASOPTVALUE)==0 && (table[tabindex]->flag & ARG_HASVALUE)==0 && (table[tabindex]->longopts || table[tabindex]->shortopts) ); - cJSON_AddBoolToObject(entry, "remark", (table[tabindex]->flag & ARG_HASOPTVALUE)==0 && (table[tabindex]->flag & ARG_HASVALUE)==0 && (!table[tabindex]->longopts && !table[tabindex]->shortopts)); - cJSON_AddBoolToObject(entry, "hasvalue", table[tabindex]->flag & ARG_HASVALUE); - cJSON_AddNumberToObject(entry,"mincount",table[tabindex]->mincount); - cJSON_AddNumberToObject(entry,"maxcount",table[tabindex]->maxcount); - cJSON_AddItemToArray(arg_list, entry); - tabindex++; - } - return arg_list; +cJSON* ParmsToJSON(struct arg_hdr** argtable) { + if (!argtable) return NULL; + cJSON* arg_list = cJSON_CreateArray(); + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex = 0; + while (!(table[tabindex]->flag & ARG_TERMINATOR)) { + cJSON* entry = cJSON_CreateObject(); + ADD_TO_JSON(entry, table[tabindex], datatype); + ADD_TO_JSON(entry, table[tabindex], glossary); + ADD_TO_JSON(entry, table[tabindex], longopts); + ADD_TO_JSON(entry, table[tabindex], shortopts); + cJSON_AddBoolToObject(entry, "checkbox", + (table[tabindex]->flag & ARG_HASOPTVALUE) == 0 && (table[tabindex]->flag & ARG_HASVALUE) == 0 && + (table[tabindex]->longopts || table[tabindex]->shortopts)); + cJSON_AddBoolToObject(entry, "remark", + (table[tabindex]->flag & ARG_HASOPTVALUE) == 0 && (table[tabindex]->flag & ARG_HASVALUE) == 0 && + (!table[tabindex]->longopts && !table[tabindex]->shortopts)); + cJSON_AddBoolToObject(entry, "hasvalue", table[tabindex]->flag & ARG_HASVALUE); + cJSON_AddNumberToObject(entry, "mincount", table[tabindex]->mincount); + cJSON_AddNumberToObject(entry, "maxcount", table[tabindex]->maxcount); + cJSON_AddItemToArray(arg_list, entry); + tabindex++; + } + return arg_list; } -esp_err_t cmd_to_json(const esp_console_cmd_t *cmd){ - return cmd_to_json_with_cb(cmd, NULL); -} +esp_err_t cmd_to_json(const esp_console_cmd_t* cmd) { return cmd_to_json_with_cb(cmd, NULL); } -esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t parm_values_fn){ - if(!cmdList){ - cmdList=cJSON_CreateArray(); - } - if(!values_fn_list){ - values_fn_list=cJSON_CreateObject(); - } +esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t* cmd, parm_values_fn_t parm_values_fn) { + if (!cmdList) { + cmdList = cJSON_CreateArray(); + } + if (!values_fn_list) { + values_fn_list = cJSON_CreateObject(); + } if (cmd->command == NULL) { return ESP_ERR_INVALID_ARG; @@ -157,27 +162,26 @@ esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t par if (strchr(cmd->command, ' ') != NULL) { return ESP_ERR_INVALID_ARG; } - cJSON * jsoncmd = cJSON_CreateObject(); - ADD_TO_JSON(jsoncmd,cmd,help); - ADD_TO_JSON(jsoncmd,cmd,hint); - if(parm_values_fn){ - char addr[11]={0}; - snprintf(addr,sizeof(addr),"%lx",(unsigned long)parm_values_fn); - cJSON_AddStringToObject(values_fn_list,cmd->command,addr); - } - cJSON_AddBoolToObject(jsoncmd,"hascb",parm_values_fn!=NULL); + cJSON* jsoncmd = cJSON_CreateObject(); + ADD_TO_JSON(jsoncmd, cmd, help); + ADD_TO_JSON(jsoncmd, cmd, hint); + if (parm_values_fn) { + char addr[11] = {0}; + snprintf(addr, sizeof(addr), "%lx", (unsigned long)parm_values_fn); + cJSON_AddStringToObject(values_fn_list, cmd->command, addr); + } + cJSON_AddBoolToObject(jsoncmd, "hascb", parm_values_fn != NULL); - if(cmd->argtable){ - cJSON_AddItemToObject(jsoncmd,"argtable",ParmsToJSON(cmd->argtable)); + if (cmd->argtable) { + cJSON_AddItemToObject(jsoncmd, "argtable", ParmsToJSON(cmd->argtable)); } if (cmd->hint) { - cJSON_AddStringToObject(jsoncmd, "hint", cmd->hint); - } - else if (cmd->argtable) { + cJSON_AddStringToObject(jsoncmd, "hint", cmd->hint); + } else if (cmd->argtable) { /* Generate hint based on cmd->argtable */ - char *buf = NULL; + char* buf = NULL; size_t buf_size = 0; - FILE *f = open_memstream(&buf, &buf_size); + FILE* f = open_memstream(&buf, &buf_size); if (f != NULL) { arg_print_syntax(f, cmd->argtable, NULL); fflush(f); @@ -187,303 +191,237 @@ esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t par FREE_AND_NULL(buf); } cJSON_AddStringToObject(jsoncmd, "name", cmd->command); - char * b=cJSON_Print(jsoncmd); - if(b){ - ESP_LOGD(TAG,"Adding command table %s",b); - free(b); + char* b = cJSON_Print(jsoncmd); + if (b) { + ESP_LOGD(TAG, "Adding command table %s", b); + free(b); } cJSON_AddItemToArray(cmdList, jsoncmd); return ESP_OK; } -int arg_parse_msg(int argc, char **argv, struct arg_hdr ** args){ - int nerrors = arg_parse(argc, argv, (void **)args); +int arg_parse_msg(int argc, char** argv, struct arg_hdr** args) { + int nerrors = arg_parse(argc, argv, (void**)args); if (nerrors != 0) { - char *buf = NULL; - size_t buf_size = 0; - FILE *f = open_memstream(&buf, &buf_size); - if (f != NULL) { - arg_print_errors(f, getParmsEnd(args), argv[0]); - fflush (f); - cmd_send_messaging(argv[0],MESSAGING_ERROR,"%s", buf); - } + char* buf = NULL; + size_t buf_size = 0; + FILE* f = open_memstream(&buf, &buf_size); + if (f != NULL) { + arg_print_errors(f, getParmsEnd(args), argv[0]); + fflush(f); + cmd_send_messaging(argv[0], MESSAGING_ERROR, "%s", buf); + } fclose(f); FREE_AND_NULL(buf); } return nerrors; } -void process_autoexec(){ - int i=1; - char autoexec_name[21]={0}; - char * autoexec_value=NULL; - uint8_t autoexec_flag=0; - // TODO: Add support for the commented code - void * cmd = run_command; - - // char * str_flag = config_alloc_get(NVS_TYPE_STR, "autoexec"); - // if(!bypass_network_manager){ - // ESP_LOGW(TAG, "Processing autoexec commands while network manager active. Wifi related commands will be ignored."); - // } - // if(is_recovery_running){ - // ESP_LOGD(TAG, "Processing autoexec commands in recovery mode. Squeezelite commands will be ignored."); - // } - // if(str_flag !=NULL ){ - // autoexec_flag=atoi(str_flag); - // ESP_LOGI(TAG,"autoexec is set to %s auto-process", autoexec_flag>0?"perform":"skip"); - // if(autoexec_flag == 1) { - // do { - // snprintf(autoexec_name,sizeof(autoexec_name)-1,"autoexec%u",i++); - // ESP_LOGD(TAG,"Getting command name %s", autoexec_name); - // autoexec_value= config_alloc_get(NVS_TYPE_STR, autoexec_name); - // if(autoexec_value!=NULL ){ - // if(!bypass_network_manager && strstr(autoexec_value, "join ")!=NULL ){ - // ESP_LOGW(TAG,"Ignoring wifi join command."); - // } - // else if(is_recovery_running && !strstr(autoexec_value, "squeezelite " ) ){ - // ESP_LOGW(TAG,"Ignoring command. "); - // } - // else { - // ESP_LOGI(TAG,"Running command %s = %s", autoexec_name, autoexec_value); - // run_command(autoexec_value); - // } - // ESP_LOGD(TAG,"Freeing memory for command %s name", autoexec_name); - // free(autoexec_value); - // } - // else { - // ESP_LOGD(TAG,"No matching command found for name %s", autoexec_name); - // break; - // } - // } while(1); - // } - // free(str_flag); - - // } - // else - // { - // ESP_LOGD(TAG,"No matching command found for name autoexec."); - // } - // TODO: Add support for the commented code -} - static ssize_t stdin_read(int fd, void* data, size_t size) { - size_t bytes = -1; - - while (1) { - QueueSetMemberHandle_t activated = xQueueSelectFromSet(stdin_redir.queue_set, portMAX_DELAY); - - if (activated == uart_queue) { - uart_event_t event; - - xQueueReceive(uart_queue, &event, 0); - - if (event.type == UART_DATA) { - bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < event.size ? size : event.size, 0); - // we have to do our own line ending translation here - for (int i = 0; i < bytes; i++) if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; - break; - } - } else if (xRingbufferCanRead(stdin_redir.handle, activated)) { - char *p = xRingbufferReceiveUpTo(stdin_redir.handle, &bytes, 0, size); - // we might receive strings, replace null by \n - for (int i = 0; i < bytes; i++) if (p[i] == '\0' || p[i] == '\r') p[i] = '\n'; - memcpy(data, p, bytes); - vRingbufferReturnItem(stdin_redir.handle, p); - break; - } - } - - return bytes; + size_t bytes = -1; + static size_t remain = 0; + if (remain > 0) { + bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < remain ? size : remain, 0); + remain -= bytes; + for (int i = 0; i < bytes; i++) + if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; + return bytes; + } + while (1) { + QueueSetMemberHandle_t activated = xQueueSelectFromSet(stdin_redir.queue_set, portMAX_DELAY); + + if (activated == uart_queue) { + uart_event_t event; + xQueueReceive(uart_queue, &event, 0); + if (event.type == UART_DATA) { + bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < event.size ? size : event.size, 0); + // we have to do our own line ending translation here + for (int i = 0; i < bytes; i++) + if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; + if (event.size > bytes) { + remain = event.size - bytes; + } + break; + } + } else if (xRingbufferCanRead(stdin_redir.handle, activated)) { + char* p = xRingbufferReceiveUpTo(stdin_redir.handle, &bytes, 0, size); + // we might receive strings, replace null by \n + for (int i = 0; i < bytes; i++) + if (p[i] == '\0' || p[i] == '\r') p[i] = '\n'; + memcpy(data, p, bytes); + vRingbufferReturnItem(stdin_redir.handle, p); + xRingbufferPrintInfo(stdin_redir.handle); + break; + } + } + + return bytes; } -static int stdin_dummy(const char * path, int flags, int mode) { return 0; } +static int stdin_dummy(const char* path, int flags, int mode) { return 0; } void initialize_console() { - /* Minicom, screen, idf_monitor send CR when ENTER key is pressed (unused if we redirect stdin) */ - esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); + /* Minicom, screen, idf_monitor send CR when ENTER key is pressed (unused if we redirect stdin) */ + esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); - /* Configure UART. Note that REF_TICK is used so that the baud rate remains - * correct while APB frequency is changing in light sleep mode. - */ - const uart_config_t uart_config = { .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, - }; - ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config)); + /* Configure UART. Note that REF_TICK is used so that the baud rate remains + * correct while APB frequency is changing in light sleep mode. + */ + const uart_config_t uart_config = { + .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + }; + ESP_ERROR_CHECK(uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config)); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 3, &uart_queue, 0)); - - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); - - /* re-direct stdin to our own driver so we can gather data from various sources */ - stdin_redir.queue_set = xQueueCreateSet(2); - stdin_redir.handle = xRingbufferCreateStatic(sizeof(stdin_redir._buf), RINGBUF_TYPE_BYTEBUF, stdin_redir._buf, &stdin_redir._ringbuf); - xRingbufferAddToQueueSetRead(stdin_redir.handle, stdin_redir.queue_set); - xQueueAddToSet(uart_queue, stdin_redir.queue_set); - - esp_vfs_t vfs = { }; - vfs.flags = ESP_VFS_FLAG_DEFAULT; - vfs.open = stdin_dummy; - vfs.read = stdin_read; + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK(uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 3, &uart_queue, 0)); - ESP_ERROR_CHECK(esp_vfs_register("/dev/redirect", &vfs, NULL)); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); + + /* re-direct stdin to our own driver so we can gather data from various sources */ + stdin_redir.queue_set = xQueueCreateSet(2); + stdin_redir.handle = xRingbufferCreateStatic(sizeof(stdin_redir._buf), RINGBUF_TYPE_BYTEBUF, stdin_redir._buf, &stdin_redir._ringbuf); + xRingbufferAddToQueueSetRead(stdin_redir.handle, stdin_redir.queue_set); + xQueueAddToSet(uart_queue, stdin_redir.queue_set); + + esp_vfs_t vfs = {}; + vfs.flags = ESP_VFS_FLAG_DEFAULT; + vfs.open = stdin_dummy; + vfs.read = stdin_read; + + ESP_ERROR_CHECK(esp_vfs_register("/dev/redirect", &vfs, NULL)); freopen("/dev/redirect", "r", stdin); - /* Disable buffering on stdin */ - setvbuf(stdin, NULL, _IONBF, 0); + /* Disable buffering on stdin */ + setvbuf(stdin, NULL, _IONBF, 0); - /* Initialize the console */ - esp_console_config_t console_config = { .max_cmdline_args = 28, - .max_cmdline_length = 600, + /* Initialize the console */ + esp_console_config_t console_config = { + .max_cmdline_args = 28, + .max_cmdline_length = 600, #if CONFIG_LOG_COLORS - .hint_color = atoi(LOG_COLOR_CYAN) + .hint_color = atoi(LOG_COLOR_CYAN) #endif - }; - ESP_ERROR_CHECK(esp_console_init(&console_config)); + }; + ESP_ERROR_CHECK(esp_console_init(&console_config)); - /* Configure linenoise line completion library */ - /* Enable multiline editing. If not set, long commands will scroll within - * single line. - */ - linenoiseSetMultiLine(1); + /* Configure linenoise line completion library */ + /* Enable multiline editing. If not set, long commands will scroll within + * single line. + */ + linenoiseSetMultiLine(1); - /* Tell linenoise where to get command completions and hints */ - linenoiseSetCompletionCallback(&esp_console_get_completion); - linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint); + /* Tell linenoise where to get command completions and hints */ + linenoiseSetCompletionCallback(&esp_console_get_completion); + linenoiseSetHintsCallback((linenoiseHintsCallback*)&esp_console_get_hint); - /* Set command history size */ - linenoiseHistorySetMaxLen(100); + /* Set command history size */ + linenoiseHistorySetMaxLen(100); - /* Load command history from filesystem */ - //linenoiseHistoryLoad(HISTORY_PATH); } -bool console_push(const char *data, size_t size) { - return xRingbufferSend(stdin_redir.handle, data, size, pdMS_TO_TICKS(100)) == pdPASS; -} +bool console_push(const char* data, size_t size) { return xRingbufferSend(stdin_redir.handle, data, size, pdMS_TO_TICKS(100)) == pdPASS; } void console_start() { - /* we always run console b/c telnet sends commands to stdin */ - initialize_console(); - /* Register commands */ - MEMTRACE_PRINT_DELTA_MESSAGE("Registering help command"); - esp_console_register_help_command(); - MEMTRACE_PRINT_DELTA_MESSAGE("Registering system commands"); - register_system(); - MEMTRACE_PRINT_DELTA_MESSAGE("Registering config commands"); - register_config_cmd(); - MEMTRACE_PRINT_DELTA_MESSAGE("Registering wifi commands"); - register_wifi(); + /* Register commands */ + esp_console_register_help_command(); + register_system(); + register_config_cmd(); + register_wifi(); - if(is_recovery_running){ - MEMTRACE_PRINT_DELTA_MESSAGE("Registering recovery commands"); - register_ota_cmd(); - } - MEMTRACE_PRINT_DELTA_MESSAGE("Registering i2c commands"); - register_i2ctools(); - - printf("\n"); - if(is_recovery_running){ - printf("****************************************************************\n" - "RECOVERY APPLICATION\n" - "This mode is used to flash Squeezelite into the OTA partition\n" - "****\n\n"); - } - printf("Type 'help' to get the list of commands.\n" - "Use UP/DOWN arrows to navigate through command history.\n" - "Press TAB when typing command name to auto-complete.\n" - "\n"); - if(!is_recovery_running){ - printf("To automatically execute lines at startup:\n" - "\tSet NVS variable autoexec (U8) = 1 to enable, 0 to disable automatic execution.\n" - "\tSet NVS variable autoexec[1~9] (string)to a command that should be executed automatically\n"); - } - printf("\n\n"); + if (is_recovery_running) { + register_ota_cmd(); + } + register_i2ctools(); - /* Figure out if the terminal supports escape sequences */ - int probe_status = linenoiseProbe(); - if (probe_status) { /* zero indicates success */ - printf("\n****************************\n" - "Your terminal application does not support escape sequences.\n" - "Line editing and history features are disabled.\n" - "On Windows, try using Putty instead.\n" - "****************************\n"); - linenoiseSetDumbMode(1); + printf("\n"); + if (is_recovery_running) { + printf("****************************************************************\n" + "RECOVERY APPLICATION\n" + "This mode is used to flash Squeezelite into the OTA partition\n" + "****\n\n"); + } + printf("Type 'help' to get the list of commands.\n" + "Use UP/DOWN arrows to navigate through command history.\n" + "Press TAB when typing command name to auto-complete.\n" + "\n"); + printf("\n\n"); + + /* Figure out if the terminal supports escape sequences */ + int probe_status = linenoiseProbe(); + if (probe_status) { /* zero indicates success */ + printf("\n****************************\n" + "Your terminal application does not support escape sequences.\n" + "Line editing and history features are disabled.\n" + "On Windows, try using Putty instead.\n" + "****************************\n"); + linenoiseSetDumbMode(1); #if CONFIG_LOG_COLORS - /* Since the terminal doesn't support escape sequences, - * don't use color codes in the prompt. - */ - if(is_recovery_running){ - recovery_prompt= "recovery-squeezelite-esp32>"; - } - prompt = "squeezelite-esp32> "; -#endif //CONFIG_LOG_COLORS - } - esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); - cfg.thread_name= "console"; - cfg.inherit_cfg = true; - cfg.stack_size = 4*1024; - if(is_recovery_running){ - prompt = recovery_prompt; - } - MEMTRACE_PRINT_DELTA_MESSAGE("Creating console thread with stack size of 4096 bytes"); - esp_pthread_set_cfg(&cfg); - pthread_create(&thread_console, NULL, console_thread, NULL); - MEMTRACE_PRINT_DELTA_MESSAGE("Console thread created"); - + /* Since the terminal doesn't support escape sequences, + * don't use color codes in the prompt. + */ + if (is_recovery_running) { + recovery_prompt = "recovery-squeezelite-esp32>"; + } + prompt = "squeezelite-esp32> "; +#endif // CONFIG_LOG_COLORS + } + esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); + cfg.thread_name = "console"; + cfg.inherit_cfg = true; + cfg.stack_size = 4 * 1024; + if (is_recovery_running) { + prompt = recovery_prompt; + } + esp_pthread_set_cfg(&cfg); + pthread_create(&thread_console, NULL, console_thread, NULL); } -static esp_err_t run_command(char * line){ - /* Try to run the command */ - int ret; - esp_err_t err = esp_console_run(line, &ret); +static esp_err_t run_command(char* line) { + /* Try to run the command */ + int ret; + esp_err_t err = esp_console_run(line, &ret); - if (err == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG,"Unrecognized command: %s", line); - } else if (err == ESP_ERR_INVALID_ARG) { - // command was empty - } else if (err != ESP_OK && ret != ESP_OK) { - ESP_LOGW(TAG,"Command returned non-zero error code: 0x%x (%s)", ret, - esp_err_to_name(err)); - } else if (err == ESP_OK && ret != ESP_OK) { - ESP_LOGW(TAG,"Command returned in error"); - err = ESP_FAIL; - } else if (err != ESP_OK) { - ESP_LOGE(TAG,"Internal error: %s", esp_err_to_name(err)); - } - return err; + if (err == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Unrecognized command: %s", line); + } else if (err == ESP_ERR_INVALID_ARG) { + // command was empty + } else if (err != ESP_OK && ret != ESP_OK) { + ESP_LOGW(TAG, "Command returned non-zero error code: 0x%x (%s)", ret, esp_err_to_name(err)); + } else if (err == ESP_OK && ret != ESP_OK) { + ESP_LOGW(TAG, "Command returned in error"); + err = ESP_FAIL; + } else if (err != ESP_OK) { + ESP_LOGE(TAG, "Internal error: %s", esp_err_to_name(err)); + } + return err; } -static void * console_thread() { - if(!is_recovery_running){ - MEMTRACE_PRINT_DELTA_MESSAGE("Running autoexec"); - process_autoexec(); - MEMTRACE_PRINT_DELTA_MESSAGE("Autoexec done"); - } - /* Main loop */ - while (1) { - /* Get a line using linenoise. - * The line is returned when ENTER is pressed. - */ - char* line = linenoise(prompt); - if (line == NULL) { /* Ignore empty lines */ - continue; - } - /* Add the command to the history */ - linenoiseHistoryAdd(line); +static void* console_thread() { + /* Main loop */ + while (1) { + /* Get a line using linenoise. + * The line is returned when ENTER is pressed. + */ + char* line = linenoise(prompt); + if (line == NULL) { /* Ignore empty lines */ + continue; + } + /* Add the command to the history */ + linenoiseHistoryAdd(line); - /* Save command history to filesystem */ - linenoiseHistorySave(HISTORY_PATH); - printf("\n"); - run_command(line); - /* linenoise allocates line buffer on the heap, so need to free it */ - linenoiseFree(line); - taskYIELD(); - } - return NULL; + /* Save command history to filesystem */ + linenoiseHistorySave(HISTORY_PATH); + printf("\n"); + run_command(line); + /* linenoise allocates line buffer on the heap, so need to free it */ + linenoiseFree(line); + taskYIELD(); + } + return NULL; } - diff --git a/components/platform_console/platform_console.h b/components/platform_console/platform_console.h index 527591f9..71c2d2cb 100644 --- a/components/platform_console/platform_console.h +++ b/components/platform_console/platform_console.h @@ -22,6 +22,7 @@ typedef cJSON * parm_values_fn_t(void); esp_err_t cmd_to_json(const esp_console_cmd_t *cmd); esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t parm_values_fn); int arg_parse_msg(int argc, char **argv, struct arg_hdr ** args); +void initialize_console(); cJSON * get_cmd_list(); #ifdef __cplusplus } diff --git a/components/platform_console/test/test_system.c b/components/platform_console/test/test_system.c index 3ff2ab86..715d1c8f 100644 --- a/components/platform_console/test/test_system.c +++ b/components/platform_console/test/test_system.c @@ -11,7 +11,7 @@ #include "unity.h" #include "platform_console.h" #include "platform_esp32.h" -// #include "Configurator.h" +// #include "Config.h" #pragma message("fixme: search for TODO below") #include "string.h" struct arg_lit *arglit; diff --git a/components/raop/CMakeLists.txt b/components/raop/CMakeLists.txt index 7ae88a52..2050a8b4 100644 --- a/components/raop/CMakeLists.txt +++ b/components/raop/CMakeLists.txt @@ -1,7 +1,7 @@ idf_component_register(SRC_DIRS . INCLUDE_DIRS . - PRIV_REQUIRES newlib freertos pthread platform_config mdns services codecs tools display wifi-manager + PRIV_REQUIRES newlib freertos pthread tools platform_config mdns services codecs display wifi-manager ) set_source_files_properties(raop.c diff --git a/components/raop/raop_sink.c b/components/raop/raop_sink.c index fb8418d9..b0ba42ee 100644 --- a/components/raop/raop_sink.c +++ b/components/raop/raop_sink.c @@ -9,7 +9,7 @@ #include "esp_pthread.h" #include "esp_system.h" #include "freertos/timers.h" -#include "Configurator.h" +#include "Config.h" #include "raop.h" #include "audio_controls.h" #include "display.h" diff --git a/components/services/CMakeLists.txt b/components/services/CMakeLists.txt index 495a25c8..ff9ca17c 100644 --- a/components/services/CMakeLists.txt +++ b/components/services/CMakeLists.txt @@ -1,5 +1,6 @@ idf_component_register(SRC_DIRS . INCLUDE_DIRS . - REQUIRES json tools platform_config display wifi-manager esp-tls platform_config + REQUIRES json tools platform_config display wifi-manager esp-tls PRIV_REQUIRES soc esp32 ) + diff --git a/components/services/accessors.c b/components/services/accessors.c index d650207e..41c1b614 100644 --- a/components/services/accessors.c +++ b/components/services/accessors.c @@ -5,15 +5,13 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG - +#define LOG_LOCAL_LEVEL ESP_LOG_INFO #include #include "esp_log.h" #include "driver/gpio.h" #include "driver/i2c.h" #include "driver/spi_master.h" -// #include "Configurator.h" -#pragma message("fixme: look for TODO below") +#include "Config.h" #include "accessors.h" #include "globdefs.h" #include "display.h" @@ -94,12 +92,20 @@ bool is_dac_config_locked(){ } - +const sys_i2c_bus* get_i2c_bus(i2c_port_t port){ + if(platform->dev.has_i2c && port == platform->dev.i2c.port-sys_i2c_port_PORT0 && platform->dev.i2c.scl>=0){ + return &platform->dev.i2c; + } + if(platform->dev.has_dac && platform->dev.dac.has_i2c && platform->dev.dac.i2c.port == port && platform->dev.dac.i2c.scl>=0){ + return &platform->dev.dac.i2c; + } + return NULL; +} /**************************************************************************************** * */ -const i2c_config_t * config_i2c_get(int * i2c_port) { - sys_I2CBus * bus = NULL; +const i2c_config_t * config_i2c_get(sys_i2c_bus * bus) { + static i2c_config_t i2c = { .mode = I2C_MODE_MASTER, .sda_io_num = -1, @@ -109,38 +115,30 @@ const i2c_config_t * config_i2c_get(int * i2c_port) { .master.clk_speed = 0, }; - if(SYS_I2CBUS(bus)){ - if(bus->has_scl){ - i2c.scl_io_num = bus->scl.pin; + if(bus && bus->scl >=0 && bus->sda >=0 ){ + if(bus->scl>=0){ + i2c.scl_io_num = bus->scl; } else { ESP_LOGE(TAG,"%s missing for i2c","SCL"); } - if(bus->has_sda){ - i2c.sda_io_num= bus->sda.pin; + if(bus->sda>=0){ + i2c.sda_io_num= bus->sda; } else { ESP_LOGE(TAG,"%s missing for i2c","SDA"); } if(bus->speed>0){ i2c.master.clk_speed = bus->speed; - } - if(bus->port != sys_I2CPortEnum_UNSPECIFIED_PORT){ - i2c_system_port = bus->port - sys_I2CPortEnum_I2CPort0; - } - // TODO: untangle i2c system port handling - if(i2c_port) { - *i2c_port=i2c_system_port; - } - + } } return &i2c; } -void config_set_gpio(int * pin, sys_GPIO * gpio,bool has_value, const char * name, bool mandatory){ +void config_set_gpio(int * pin, sys_gpio_config * gpio,bool has_value, const char * name, bool mandatory){ if(has_value){ ESP_LOGD(TAG, "Setting pin %d as %s", gpio->pin, name); if(pin) *pin= gpio->pin; @@ -166,14 +164,14 @@ const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) { .quadhd_io_num = -1 }; if(platform->has_dev && platform->dev.has_spi){ - ESP_LOGI(TAG,"SPI Configuration found"); - ASSIGN_GPIO(spi.mosi_io_num,platform->dev.spi,mosi,true); - ASSIGN_GPIO(spi.miso_io_num,platform->dev.spi,miso,false); - ASSIGN_GPIO(spi.sclk_io_num,platform->dev.spi,clk,true); - ASSIGN_GPIO(spi_system_dc_gpio,platform->dev.spi,dc,true); + ESP_LOGD(TAG,"SPI Configuration found"); + spi.mosi_io_num = platform->dev.spi.mosi; + spi.miso_io_num = platform->dev.spi.miso; + spi.sclk_io_num = platform->dev.spi.clk; + spi_system_dc_gpio = platform->dev.spi.dc; // only VSPI (1) can be used as Flash and PSRAM run at 80MHz - if(platform->dev.spi.host!=sys_HostEnum_UNSPECIFIED_HOST){ - spi_system_host = platform->dev.spi.host; + if(platform->dev.spi.host!=sys_dev_common_hosts_NONE){ + spi_system_host = platform->dev.spi.host-sys_dev_common_hosts_Host0; } } else { diff --git a/components/services/accessors.h b/components/services/accessors.h index 82a52b4f..0518a9cd 100644 --- a/components/services/accessors.h +++ b/components/services/accessors.h @@ -13,6 +13,7 @@ #include "driver/i2s.h" #include "driver/spi_master.h" #include "gpio_exp.h" +#include "I2CBus.pb.h" #define ASSIGN_GPIO(pin, root, name, mandatory) config_set_gpio(&pin, &(root).name, (root).has_##name, #name, mandatory) #define ASSIGN_COND_VAL_1LVL(name, targetval) \ @@ -31,7 +32,9 @@ #define SYS_NET(target) ASSIGN_COND_VAL_1LVL(net,target) #define SYS_DISPLAY(target) ASSIGN_COND_VAL_2LVL(dev,display,target) #define SYS_DEV_LEDSTRIP(target) ASSIGN_COND_VAL_2LVL(dev,led_strip,target) +#define SYS_DEV(target) ASSIGN_COND_VAL_1LVL(dev,target) #define SYS_DEV_ROTARY(target) ASSIGN_COND_VAL_2LVL(dev,rotary,target) +#define SYS_DEV_IR(target) ASSIGN_COND_VAL_2LVL(dev,ir,target) #define SYS_DISPLAY_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,display,common,target) #define SYS_DISPLAY_SPI(target) ASSIGN_COND_VAL_3LVL(dev,display,spi,target) #define SYS_DISPLAY_I2C(target) ASSIGN_COND_VAL_3LVL(dev,display,i2c,target) @@ -40,25 +43,25 @@ #define SYS_ETH_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,eth,common,target) -#define SYS_I2CBUS(target) ASSIGN_COND_VAL_2LVL(dev,i2c,target) +#define sys_i2c_bus(target) ASSIGN_COND_VAL_2LVL(dev,i2c,target) #define SYS_GPIOS_NAME(name,target) ASSIGN_COND_VAL_2LVL(gpios,name,target) -#define SYS_SERVICES(target) ASSIGN_COND_VAL_1LVL(services,target) -#define SYS_SERVICES_SPOTIFY(target) ASSIGN_COND_VAL_2LVL(services,cspot,target) -#define SYS_SERVICES_METADATA(target) ASSIGN_COND_VAL_2LVL(services,metadata,target) -#define SYS_SERVICES_AIRPLAY(target) ASSIGN_COND_VAL_2LVL(services,airplay,target) -#define SYS_SERVICES_SLEEP(target) ASSIGN_COND_VAL_2LVL(services,sleep,target) -#define SYS_SERVICES_EQUALIZER(target) ASSIGN_COND_VAL_2LVL(services,equalizer,target) +#define sys_services_config(target) ASSIGN_COND_VAL_1LVL(services,target) +#define sys_services_config_SPOTIFY(target) ASSIGN_COND_VAL_2LVL(services,cspot,target) +#define sys_services_config_METADATA(target) ASSIGN_COND_VAL_2LVL(services,metadata,target) +#define sys_services_config_AIRPLAY(target) ASSIGN_COND_VAL_2LVL(services,airplay,target) +#define sys_services_config_SLEEP(target) ASSIGN_COND_VAL_2LVL(services,sleep,target) +#define sys_services_config_EQUALIZER(target) ASSIGN_COND_VAL_2LVL(services,equalizer,target) -#define SYS_SERVICES_TELNET(target) ASSIGN_COND_VAL_2LVL(services,telnet,target) -#define SYS_SERVICES_BTSINK(target) ASSIGN_COND_VAL_2LVL(services,bt_sink,target) -#define SYS_SERVICES_SQUEEZELITE(target) ASSIGN_COND_VAL_2LVL(services,squeezelite,target) +#define sys_services_config_TELNET(target) ASSIGN_COND_VAL_2LVL(services,telnet,target) +#define sys_services_config_BTSINK(target) ASSIGN_COND_VAL_2LVL(services,bt_sink,target) #define SYS_DEV_BATTERY(target) ASSIGN_COND_VAL_2LVL(dev,battery,target) -const i2c_config_t * config_i2c_get(int * i2c_port); +const i2c_config_t * config_i2c_get(sys_i2c_bus * bus); const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host); const gpio_exp_config_t * config_gpio_exp_get(int index); +const sys_i2c_bus* get_i2c_bus(i2c_port_t port); bool is_dac_config_locked(); bool are_statistics_enabled(); diff --git a/components/services/audio_controls.c b/components/services/audio_controls.c index 98086402..12521a8a 100644 --- a/components/services/audio_controls.c +++ b/components/services/audio_controls.c @@ -1,4 +1,4 @@ -/* +/* * audio control callbacks * * (c) Sebastien 2019 @@ -8,113 +8,93 @@ * https://opensource.org/licenses/MIT * */ +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "audio_controls.h" +#include "Config.h" +#include "accessors.h" +#include "buttons.h" +#include "cJSON.h" +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/timers.h" +#include "services.h" #include #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/timers.h" -#include "esp_system.h" -#include "esp_log.h" -#include "cJSON.h" -#include "buttons.h" -#include "Configurator.h" -#include "accessors.h" -#include "services.h" -#include "audio_controls.h" -typedef esp_err_t (actrls_config_map_handler) (const cJSON * member, actrls_config_t *cur_config,uint32_t offset); +typedef esp_err_t(actrls_config_map_handler)(const cJSON* member, actrls_config_t* cur_config, uint32_t offset); typedef struct { - char * member; - uint32_t offset; - actrls_config_map_handler * handler; + char* member; + uint32_t offset; + actrls_config_map_handler* handler; } actrls_config_map_t; -static esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_config); -static esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cur_config); -static esp_err_t actrls_process_int (const cJSON * member, actrls_config_t *cur_config, uint32_t offset); -static esp_err_t actrls_process_type (const cJSON * member, actrls_config_t *cur_config, uint32_t offset); -static esp_err_t actrls_process_bool (const cJSON * member, actrls_config_t *cur_config, uint32_t offset); -static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *cur_config, uint32_t offset); +static void actrls_parse_action(const char* name); +static esp_err_t actrls_init_profile(const char* profile_name, bool create); -static esp_err_t actrls_init_json(const char *profile_name, bool create); -static void control_rotary_handler(void *client, rotary_event_e event, bool long_press); -static void rotary_timer( TimerHandle_t xTimer ); +static esp_err_t actrls_process_press(const sys_btns_press* action, sys_btns_press* cur_config_press); +static esp_err_t actrls_process_button(const sys_btns_btn* button, actrls_config_t* cur_config); +static void control_rotary_handler(void* client, rotary_event_e event, bool long_press); +static void rotary_timer(TimerHandle_t xTimer); -static const actrls_config_map_t actrls_config_map[] = - { - {"gpio", offsetof(actrls_config_t,gpio), actrls_process_int}, - {"debounce", offsetof(actrls_config_t,debounce), actrls_process_int}, - {"type", offsetof(actrls_config_t,type), actrls_process_type}, - {"pull", offsetof(actrls_config_t,pull), actrls_process_bool}, - {"long_press", offsetof(actrls_config_t,long_press),actrls_process_int}, - {"shifter_gpio", offsetof(actrls_config_t,shifter_gpio), actrls_process_int}, - {"normal", offsetof(actrls_config_t,normal), actrls_process_action}, - {"shifted", offsetof(actrls_config_t,shifted), actrls_process_action}, - {"longpress", offsetof(actrls_config_t,longpress), actrls_process_action}, - {"longshifted", offsetof(actrls_config_t,longshifted), actrls_process_action}, - {"", 0, NULL} - }; - -// BEWARE: the actions below need to stay aligned with the corresponding enum to properly support json parsing -// along with the actrls_t controls in LMS_controls, bt_sink and raop_sink -#define EP(x) [x] = #x /* ENUM PRINT */ -static const char * actrls_action_s[ ] = { EP(ACTRLS_POWER),EP(ACTRLS_VOLUP),EP(ACTRLS_VOLDOWN),EP(ACTRLS_TOGGLE),EP(ACTRLS_PLAY), - EP(ACTRLS_PAUSE),EP(ACTRLS_STOP),EP(ACTRLS_REW),EP(ACTRLS_FWD),EP(ACTRLS_PREV),EP(ACTRLS_NEXT), - EP(BCTRLS_UP),EP(BCTRLS_DOWN),EP(BCTRLS_LEFT),EP(BCTRLS_RIGHT), - EP(BCTRLS_PS0),EP(BCTRLS_PS1),EP(BCTRLS_PS2),EP(BCTRLS_PS3),EP(BCTRLS_PS4),EP(BCTRLS_PS5),EP(BCTRLS_PS6),EP(BCTRLS_PS7),EP(BCTRLS_PS8),EP(BCTRLS_PS9), - EP(KNOB_LEFT),EP(KNOB_RIGHT),EP(KNOB_PUSH), EP(ACTRLS_SLEEP), - ""} ; - -static const char * TAG = "audio controls"; -static actrls_config_t *json_config; -cJSON * control_profiles = NULL; +static const char* TAG = "audio controls"; +static actrls_config_t* json_config; +cJSON* control_profiles = NULL; static EXT_RAM_ATTR actrls_t default_controls, current_controls; static actrls_hook_t *default_hook, *current_hook; static bool default_raw_controls, current_raw_controls; static actrls_ir_handler_t *default_ir_handler, *current_ir_handler; static EXT_RAM_ATTR struct { - bool long_state; - bool volume_lock; - TimerHandle_t timer; - bool click_pending; - int left_count; + bool long_state; + bool volume_lock; + TimerHandle_t timer; + bool click_pending; + int left_count; } rotary; -static const struct ir_action_map_s{ - uint32_t code; - actrls_action_e action; -} ir_action_map[] = { - {0x7689b04f, BCTRLS_DOWN}, {0x7689906f, BCTRLS_LEFT}, {0x7689d02f, BCTRLS_RIGHT}, {0x7689e01f, BCTRLS_UP}, - {0x768900ff, ACTRLS_VOLDOWN}, {0x7689807f, ACTRLS_VOLUP}, - {0x7689c03f, ACTRLS_PREV}, {0x7689a05f, ACTRLS_NEXT}, - {0x768920df, ACTRLS_PAUSE}, {0x768910ef, ACTRLS_PLAY}, - {0x00, 0x00}, +static const struct ir_action_map_s { + uint32_t code; + sys_btns_actions action; +} ir_action_map[] = { + {0x7689b04f, sys_btns_actions_B_DOWN}, + {0x7689906f, sys_btns_actions_B_LEFT}, + {0x7689d02f, sys_btns_actions_B_RIGHT}, + {0x7689e01f, sys_btns_actions_B_UP}, + {0x768900ff, sys_btns_actions_A_VOLDOWN}, + {0x7689807f, sys_btns_actions_A_VOLUP}, + {0x7689c03f, sys_btns_actions_A_PREV}, + {0x7689a05f, sys_btns_actions_A_NEXT}, + {0x768920df, sys_btns_actions_A_PAUSE}, + {0x768910ef, sys_btns_actions_A_PLAY}, + {0x00, 0x00}, }; /**************************************************************************************** * This function can be called to map IR codes to default actions */ bool actrls_ir_action(uint16_t addr, uint16_t cmd) { - uint32_t code = (addr << 16) | cmd; - struct ir_action_map_s const *map = ir_action_map; - - while (map->code && map->code != code) map++; - - if (map->code && current_controls[map->action]) { - current_controls[map->action](true); - return true; - } else { - return false; - } + uint32_t code = (addr << 16) | cmd; + struct ir_action_map_s const* map = ir_action_map; + + while (map->code && map->code != code) + map++; + + if (map->code && current_controls[map->action]) { + current_controls[map->action](true); + return true; + } else { + return false; + } } /**************************************************************************************** - * + * */ static void ir_handler(uint16_t addr, uint16_t cmd) { - ESP_LOGD(TAG, "recaived IR %04hx:%04hx", addr, cmd); - if (current_ir_handler) current_ir_handler(addr, cmd); + ESP_LOGD(TAG, "recaived IR %04hx:%04hx", addr, cmd); + if (current_ir_handler) current_ir_handler(addr, cmd); } /**************************************************************************************** @@ -122,484 +102,436 @@ static void ir_handler(uint16_t addr, uint16_t cmd) { */ esp_err_t actrls_init(const char* profile_name) { esp_err_t err = ESP_OK; - sys_Rotary* dev_config = NULL; - if (!SYS_DEV_ROTARY(dev_config) ) { + sys_dev_ir* ir = NULL; + sys_btns_rotary* dev_config = NULL; + if (!SYS_DEV_ROTARY(dev_config)) { ESP_LOGD(TAG, "Rotary not configured"); return ESP_OK; } char* p; int A = -1, B = -1, SW = -1, longpress = 0; - A = dev_config->A.pin; - B = dev_config->B.pin; - SW = dev_config->SW.pin; + A = dev_config->A; + B = dev_config->B; + SW = dev_config->SW; + if (A >= 0 && B >= 0) { + if (dev_config->has_knobonly && dev_config->knobonly.enable) { + p = strchr(p, '='); - if (dev_config->has_knobonly && dev_config->knobonly.enable) { - p = strchr(p, '='); + int double_press = dev_config->knobonly.delay_ms > 0 ? dev_config->knobonly.delay_ms : 350; + rotary.timer = xTimerCreate("knobTimer", double_press / portTICK_RATE_MS, pdFALSE, NULL, rotary_timer); + longpress = 500; + ESP_LOGI(TAG, "single knob navigation %d", double_press); + } else { - int double_press = - dev_config->knobonly.delay_ms > 0 ? dev_config->knobonly.delay_ms : 350; - rotary.timer = - xTimerCreate("knobTimer", double_press / portTICK_RATE_MS, pdFALSE, NULL, rotary_timer); - longpress = 500; - ESP_LOGI(TAG, "single knob navigation %d", double_press); + if (dev_config->volume) rotary.volume_lock = true; + if (dev_config->longpress) longpress = 1000; + } + + // create rotary (no handling of long press) + err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL; } else { - - if (dev_config->volume) rotary.volume_lock = true; - if (dev_config->longpress) longpress = 1000; + ESP_LOGI(TAG, "Rotary control not configured."); } - // create rotary (no handling of long press) - err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL; - - if (platform->dev.has_ir && platform->dev.ir.gpio.pin >= 0) { - - if (platform->dev.ir.type == sys_InfraredType_IR_NEC) { - create_infrared(platform->dev.ir.gpio.pin, ir_handler, IR_RC5); + if (SYS_DEV_IR(ir) && ir->gpio >= 0 && ir->type != sys_dev_ir_types_IR_UNKNOWN) { + ESP_LOGD(TAG, "Infrared config found on pin %d, protocol: %s", ir->gpio, sys_dev_ir_types_name(ir->type)); + if (ir->type == sys_dev_ir_types_IR_NEC) { + create_infrared(ir->gpio, ir_handler, IR_RC5); } else { - create_infrared(platform->dev.ir.gpio.pin, ir_handler, IR_NEC); + create_infrared(ir->gpio, ir_handler, IR_NEC); } } if (!err) - return actrls_init_json(profile_name, true); + return actrls_init_profile(profile_name, true); else return err; return err; } /**************************************************************************************** - * + * */ -static void control_handler(void *client, button_event_e event, button_press_e press, bool long_press) { - actrls_config_t *key = (actrls_config_t*) client; - actrls_action_detail_t action_detail; - - switch(press) { - case BUTTON_NORMAL: - if (long_press) action_detail = key->longpress[event == BUTTON_PRESSED ? 0 : 1]; - else action_detail = key->normal[event == BUTTON_PRESSED ? 0 : 1]; - break; - case BUTTON_SHIFTED: - if (long_press) action_detail = key->longshifted[event == BUTTON_PRESSED ? 0 : 1]; - else action_detail = key->shifted[event == BUTTON_PRESSED ? 0 : 1]; - break; - default: - action_detail.action = ACTRLS_NONE; - break; - } - - ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u action:%u", key->gpio, press, long_press, event, action_detail.action); - - // stop here if control hook served the request - if (current_hook && (*current_hook)(key->gpio, action_detail.action, event, press, long_press)) return; - - // in raw mode, we just do normal action press *and* release, there is no longpress nor shift - if (current_raw_controls && action_detail.action != ACTRLS_SLEEP) { - actrls_action_e action = key->normal[0].action != ACTRLS_NONE ? key->normal[0].action : key->normal[1].action; - ESP_LOGD(TAG, "calling action %u in raw mode", action); - if (action != ACTRLS_NONE && current_controls[action]) current_controls[action](event == BUTTON_PRESSED); - return; - } - - // otherwise process using configuration - if (action_detail.action == ACTRLS_REMAP) { - // remap requested - ESP_LOGD(TAG, "remapping buttons to profile %s",action_detail.name); - cJSON * profile_obj = cJSON_GetObjectItem(control_profiles,action_detail.name); - if (profile_obj) { - actrls_config_t *cur_config = (actrls_config_t *) cJSON_GetStringValue(profile_obj); - if (cur_config) { - ESP_LOGD(TAG,"Remapping all the buttons that are found in the new profile"); - while (cur_config->gpio != -1) { - ESP_LOGD(TAG,"Remapping button with gpio %u", cur_config->gpio); - button_remap((void*) cur_config, cur_config->gpio, control_handler, cur_config->long_press, cur_config->shifter_gpio); - cur_config++; - } - } else { - ESP_LOGE(TAG,"Profile %s exists, but is empty. Cannot remap buttons",action_detail.name); - } - } else { - ESP_LOGE(TAG,"Invalid profile name %s. Cannot remap buttons",action_detail.name); - } - } else if (action_detail.action == ACTRLS_SLEEP) { - ESP_LOGI(TAG, "special sleep button pressed"); - services_sleep_activate(SLEEP_ONKEY); - } else if (action_detail.action != ACTRLS_NONE) { - ESP_LOGD(TAG, "calling action %u", action_detail.action); - if (current_controls[action_detail.action]) (*current_controls[action_detail.action])(event == BUTTON_PRESSED); - } -} - -/**************************************************************************************** - * - */ -static void control_rotary_handler(void *client, rotary_event_e event, bool long_press) { - actrls_action_e action = ACTRLS_NONE; - bool pressed = true; - - // in raw mode, we just pass rotary events - if (current_raw_controls) { - if (event == ROTARY_LEFT) (*current_controls[KNOB_LEFT])(true); - else if (event == ROTARY_RIGHT) (*current_controls[KNOB_RIGHT])(true); - else (*current_controls[KNOB_PUSH])(event == ROTARY_PRESSED); - return; - } - - switch(event) { - case ROTARY_LEFT: - if (rotary.timer) { - if (rotary.left_count) { - action = KNOB_LEFT; - // need to add a left button the first time - if (rotary.left_count == 1) (*current_controls[KNOB_LEFT])(true); - } - xTimerStart(rotary.timer, 20 / portTICK_RATE_MS); - rotary.left_count++; - } - else if (rotary.long_state) action = ACTRLS_PREV; - else if (rotary.volume_lock) action = ACTRLS_VOLDOWN; - else action = KNOB_LEFT; - break; - case ROTARY_RIGHT: - if (rotary.timer) { - if (rotary.left_count == 1) { - action = ACTRLS_PAUSE; - rotary.left_count = 0; - xTimerStop(rotary.timer, 0); - } else action = KNOB_RIGHT; - } - else if (rotary.long_state) action = ACTRLS_NEXT; - else if (rotary.volume_lock) action = ACTRLS_VOLUP; - else action = KNOB_RIGHT; - break; - case ROTARY_PRESSED: - if (rotary.timer) { - if (long_press) action = ACTRLS_PLAY; - else if (rotary.click_pending) { - action = BCTRLS_LEFT; - xTimerStop(rotary.timer, 0); - } - else xTimerStart(rotary.timer, 20 / portTICK_RATE_MS); - rotary.click_pending = !rotary.click_pending; - } - else if (long_press) rotary.long_state = !rotary.long_state; - else if (rotary.volume_lock) action = ACTRLS_TOGGLE; - else action = KNOB_PUSH; - break; - default: - break; - } - - if (action != ACTRLS_NONE) (*current_controls[action])(pressed); -} - -/**************************************************************************************** - * - */ -static void rotary_timer( TimerHandle_t xTimer ) { - if (rotary.click_pending) { - (*current_controls[KNOB_PUSH])(true); - rotary.click_pending = false; - } else if (rotary.left_count) { - if (rotary.left_count == 1) (*current_controls[KNOB_LEFT])(true); - rotary.left_count = 0; - } -} - -/**************************************************************************************** - * - */ -static actrls_action_e actrls_parse_action_json(const char * name){ - actrls_action_e action = ACTRLS_NONE; - - if(!strcasecmp("ACTRLS_NONE",name)) return ACTRLS_NONE; - for(int i=0;ivalueint; - return err; -} - -/**************************************************************************************** - * - */ -static esp_err_t actrls_process_type (const cJSON * member, actrls_config_t *cur_config, uint32_t offset){ - esp_err_t err = ESP_OK; - ESP_LOGD(TAG,"Processing type member"); - int *value = (int *)((char*) cur_config + offset); - if (member->type == cJSON_String) { - *value = - !strcmp(member->valuestring, - "BUTTON_LOW") ? - BUTTON_LOW : BUTTON_HIGH; - } else { - ESP_LOGE(TAG, - "Button type value expected string value of BUTTON_LOW or BUTTON_HIGH, none found"); - err=ESP_FAIL; - } - return err; -} - -/**************************************************************************************** - * - */ -static esp_err_t actrls_process_bool (const cJSON * member, actrls_config_t *cur_config, uint32_t offset){ - esp_err_t err = ESP_OK; - if (!member) { - ESP_LOGE(TAG,"Null json member pointer!"); - err = ESP_FAIL; - } else { - ESP_LOGD(TAG,"Processing bool member "); - if (cJSON_IsBool(member)) { - bool*value = (bool*)((char*) cur_config + offset); - *value = cJSON_IsTrue(member); - } else { - ESP_LOGE(TAG,"Member %s is not a boolean", member->string?member->string:"unknown"); - err = ESP_FAIL; - } - } - - return err; -} - -/**************************************************************************************** - * - */ -static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *cur_config, uint32_t offset){ - esp_err_t err = ESP_OK; - cJSON * button_action= cJSON_GetObjectItemCaseSensitive(member, "pressed"); - actrls_action_detail_t*value = (actrls_action_detail_t*)((char *)cur_config + offset); - if (button_action != NULL) { - value[0].action = actrls_parse_action_json( button_action->valuestring); - if(value[0].action == ACTRLS_REMAP){ - value[0].name = strdup(button_action->valuestring); - } - } - button_action = cJSON_GetObjectItemCaseSensitive(member, "released"); - if (button_action != NULL) { - value[1].action = actrls_parse_action_json( button_action->valuestring); - if (value[1].action == ACTRLS_REMAP){ - value[1].name = strdup(button_action->valuestring); - } - } - - return err; -} - -/**************************************************************************************** - * - */ -static esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_config) { - esp_err_t err = ESP_OK; - const actrls_config_map_t * h=actrls_config_map; - - char * str = cJSON_Print(member); - while (h->handler && strcmp(member->string, h->member)) { h++; } - - if (h->handler) { - ESP_LOGD(TAG,"found handler for member %s, json value %s", h->member,str?str:""); - err = h->handler(member, cur_config, h->offset); - } else { - err = ESP_FAIL; - ESP_LOGE(TAG, "Unknown json structure member : %s", str?str:""); - } - - if (str) free(str); - return err; -} - -/**************************************************************************************** - * - */ -static esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cur_config) { - esp_err_t err= ESP_OK; - const cJSON *member; - - cJSON_ArrayForEach(member, button) - { - ESP_LOGD(TAG,"Processing member %s. ", member->string); - esp_err_t loc_err = actrls_process_member(member, cur_config); - err = (err == ESP_OK) ? loc_err : err; - } - return err; - -} - -/**************************************************************************************** - * - */ -static actrls_config_t * actrls_init_alloc_structure(const cJSON *buttons, const char * name){ - int member_count = 0; - const cJSON *button; - actrls_config_t * json_config=NULL; - - // Check if the main profiles array was created - if(!control_profiles){ - control_profiles = cJSON_CreateObject(); - } - - ESP_LOGD(TAG,"Counting the number of buttons definition"); - cJSON_ArrayForEach(button, buttons) { - member_count++; - } - - ESP_LOGD(TAG, "config contains %u button definitions", member_count); - if (member_count != 0) { - json_config = calloc(sizeof(actrls_config_t) * (member_count + 1), 1); - if (json_config){ - json_config[member_count].gpio = -1; - } else { - ESP_LOGE(TAG,"Unable to allocate memory to hold configuration for %u buttons ",member_count); - } - } else { - ESP_LOGE(TAG,"No button found in configuration structure"); - } - - // we're cheating here; we're going to store the control profile - // pointer as a string reference; this will prevent cJSON - // from trying to free the structure if we ever want to free the object - cJSON * new_profile = cJSON_CreateStringReference((const char *)json_config); - cJSON_AddItemToObject(control_profiles, name, new_profile); - - return json_config; -} - -/**************************************************************************************** - * - */ -static void actrls_defaults(actrls_config_t *config) { - config->type = BUTTON_LOW; - config->pull = false; - config->debounce = 0; - config->long_press = 0; - config->shifter_gpio = -1; - config->normal[0].action = config->normal[1].action = ACTRLS_NONE; - config->longpress[0].action = config->longpress[1].action = ACTRLS_NONE; - config->shifted[0].action = config->shifted[1].action = ACTRLS_NONE; - config->longshifted[0].action = config->longshifted[1].action = ACTRLS_NONE; -} - - -/**************************************************************************************** - * - */ -static esp_err_t actrls_init_json(const char *profile_name, bool create) { - esp_err_t err = ESP_OK; - #pragma message("Add support to button profile names") -// actrls_config_t *cur_config = NULL; -// actrls_config_t *config_root = NULL; -// char *config=NULL; -// const cJSON *button; - -// if (!profile_name) return ESP_OK; -// //if ((config = config_alloc_get_str(profile_name, NULL, CONFIG_AUDIO_CONTROLS)) == NULL) return ESP_FAIL; -// // TODO: Add support for the commented code -// if (!*config) goto exit; - -// ESP_LOGD(TAG,"Parsing JSON structure %s", config); -// cJSON *buttons = cJSON_Parse(config); -// if (buttons == NULL) { -// ESP_LOGE(TAG,"JSON Parsing failed for %s", config); -// err = ESP_FAIL; -// } else { -// ESP_LOGD(TAG,"Json parsing completed"); -// if (cJSON_IsArray(buttons)) { -// ESP_LOGD(TAG,"configuration is an array as expected"); -// cur_config =config_root= actrls_init_alloc_structure(buttons, profile_name); -// if(!cur_config) { -// ESP_LOGE(TAG,"Config buffer was empty. "); -// cJSON_Delete(buttons); -// err = ESP_FAIL; -// goto exit; -// } -// ESP_LOGD(TAG,"Processing button definitions. "); -// cJSON_ArrayForEach(button, buttons){ -// char * str = cJSON_Print(button); -// ESP_LOGD(TAG,"Processing %s. ", str?str:""); -// if(str){ -// free(str); -// } -// actrls_defaults(cur_config); -// esp_err_t loc_err = actrls_process_button(button, cur_config); -// err = (err == ESP_OK) ? loc_err : err; -// if (loc_err == ESP_OK) { -// if (create) button_create((void*) cur_config, cur_config->gpio,cur_config->type, -// cur_config->pull,cur_config->debounce, control_handler, -// cur_config->long_press, cur_config->shifter_gpio); -// } else { -// ESP_LOGE(TAG,"Error parsing button structure. Button will not be registered."); -// } - -// cur_config++; -// } -// } else { -// ESP_LOGE(TAG,"Invalid configuration; array is expected and none received in %s ", config); -// } -// cJSON_Delete(buttons); -// } -// // Now update the global json_config object. If we are recursively processing menu structures, -// // the last init that completes will assigh the first json config object found, which will match -// // the default config from nvs. -// json_config = config_root; -// exit: -// free(config); - return err; +static const char* get_action_desc(sys_btns_action* action_detail) { + if (action_detail->type != sys_btns_actions_REMAP) { + return sys_btns_actions_name(action_detail->type); + } + return STR_OR_ALT(action_detail->profile_name, ""); } /**************************************************************************************** * */ -void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler) { - memcpy(default_controls, controls, sizeof(actrls_t)); - memcpy(current_controls, default_controls, sizeof(actrls_t)); - default_hook = current_hook = hook; - default_raw_controls = current_raw_controls = raw_controls; - default_ir_handler = current_ir_handler = ir_handler; +static void control_handler(void* client, button_event_e event, button_press_e press, bool long_press) { + actrls_config_t* key = (actrls_config_t*)client; + sys_btns_action* action_detail; + static sys_btns_action actionNone = sys_btns_action_init_default; + + switch (press) { + case BUTTON_NORMAL: + if (long_press) + action_detail = (event == BUTTON_PRESSED ? &key->longpress.pressed : &key->longpress.released); + else + action_detail = (event == BUTTON_PRESSED ? &key->normal.pressed : &key->normal.released); + break; + case BUTTON_SHIFTED: + if (long_press) + action_detail = (event == BUTTON_PRESSED ? &key->longshifted.pressed : &key->longshifted.released); + else + action_detail = (event == BUTTON_PRESSED ? &key->shifted.pressed : &key->shifted.released); + break; + default: + action_detail = &actionNone; + break; + } + + ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u action:%s", key->gpio, press, long_press, event, get_action_desc(action_detail)); + + // stop here if control hook served the request + if (current_hook && (*current_hook)(key->gpio, action_detail, event, press, long_press)) return; + + // in raw mode, we just do normal action press *and* release, there is no longpress nor shift + if (current_raw_controls && action_detail->type != sys_btns_actions_A_SLEEP) { + sys_btns_actions action = + key->normal.has_pressed && key->normal.pressed.type != sys_btns_actions_A_NONE ? key->normal.pressed.type : key->normal.released.type; + ESP_LOGD(TAG, "calling action %s in raw mode", sys_btns_actions_name(action)); + if (action != sys_btns_actions_A_NONE && current_controls[action]) current_controls[action](event == BUTTON_PRESSED); + return; + } + + // otherwise process using configuration + if (action_detail->type == sys_btns_actions_REMAP) { + // remap requested + ESP_LOGD(TAG, "remapping buttons to profile %s", action_detail->profile_name); + cJSON* profile_obj = cJSON_GetObjectItem(control_profiles, action_detail->profile_name); + if (profile_obj) { + actrls_config_t* cur_config = (actrls_config_t*)cJSON_GetStringValue(profile_obj); + if (cur_config) { + ESP_LOGD(TAG, "Remapping all the buttons that are found in the new profile"); + while (cur_config->gpio != -1) { + ESP_LOGD(TAG, "Remapping button with gpio %u", cur_config->gpio); + button_remap((void*)cur_config, cur_config->gpio, control_handler, cur_config->long_press, cur_config->shifter_gpio); + cur_config++; + } + } else { + ESP_LOGE(TAG, "Profile %s exists, but is empty. Cannot remap buttons", action_detail->profile_name); + } + } else { + ESP_LOGE(TAG, "Invalid profile name %s. Cannot remap buttons", action_detail->profile_name); + } + } else if (action_detail->type == sys_btns_actions_A_SLEEP) { + ESP_LOGI(TAG, "special sleep button pressed"); + services_sleep_activate(SLEEP_ONKEY); + } else if (action_detail->type != sys_btns_actions_A_NONE) { + ESP_LOGD(TAG, "calling action %s", sys_btns_actions_name(action_detail->type)); + if (current_controls[action_detail->type]) (*current_controls[action_detail->type])(event == BUTTON_PRESSED); + } } /**************************************************************************************** - * + * */ -void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler) { - memcpy(current_controls, controls, sizeof(actrls_t)); - current_hook = hook; - current_raw_controls = raw_controls; - current_ir_handler = ir_handler; +static void control_rotary_handler(void* client, rotary_event_e event, bool long_press) { + sys_btns_actions action = sys_btns_actions_A_NONE; + bool pressed = true; + + // in raw mode, we just pass rotary events + if (current_raw_controls) { + if (event == ROTARY_LEFT) + (*current_controls[sys_btns_actions_KNOB_LEFT])(true); + else if (event == ROTARY_RIGHT) + (*current_controls[sys_btns_actions_KNOB_RIGHT])(true); + else + (*current_controls[sys_btns_actions_KNOB_PUSH])(event == ROTARY_PRESSED); + return; + } + + switch (event) { + case ROTARY_LEFT: + if (rotary.timer) { + if (rotary.left_count) { + action = sys_btns_actions_KNOB_LEFT; + // need to add a left button the first time + if (rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); + } + xTimerStart(rotary.timer, 20 / portTICK_RATE_MS); + rotary.left_count++; + } else if (rotary.long_state) + action = sys_btns_actions_A_PREV; + else if (rotary.volume_lock) + action = sys_btns_actions_A_VOLDOWN; + else + action = sys_btns_actions_KNOB_LEFT; + break; + case ROTARY_RIGHT: + if (rotary.timer) { + if (rotary.left_count == 1) { + action = sys_btns_actions_A_PAUSE; + rotary.left_count = 0; + xTimerStop(rotary.timer, 0); + } else + action = sys_btns_actions_KNOB_RIGHT; + } else if (rotary.long_state) + action = sys_btns_actions_A_NEXT; + else if (rotary.volume_lock) + action = sys_btns_actions_A_VOLUP; + else + action = sys_btns_actions_KNOB_RIGHT; + break; + case ROTARY_PRESSED: + if (rotary.timer) { + if (long_press) + action = sys_btns_actions_A_PLAY; + else if (rotary.click_pending) { + action = sys_btns_actions_B_LEFT; + xTimerStop(rotary.timer, 0); + } else + xTimerStart(rotary.timer, 20 / portTICK_RATE_MS); + rotary.click_pending = !rotary.click_pending; + } else if (long_press) + rotary.long_state = !rotary.long_state; + else if (rotary.volume_lock) + action = sys_btns_actions_A_TOGGLE; + else + action = sys_btns_actions_KNOB_PUSH; + break; + default: + break; + } + + if (action != sys_btns_actions_A_NONE) (*current_controls[action])(pressed); } /**************************************************************************************** - * + * + */ +static void rotary_timer(TimerHandle_t xTimer) { + if (rotary.click_pending) { + (*current_controls[sys_btns_actions_KNOB_PUSH])(true); + rotary.click_pending = false; + } else if (rotary.left_count) { + if (rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); + rotary.left_count = 0; + } +} + +/**************************************************************************************** + * + */ +static void actrls_parse_action(const char* name) { + // Check if there is a profile name that has a match + ESP_LOGD(TAG, "unknown action %s, trying to find matching profile ", name); + cJSON* existing = cJSON_GetObjectItem(control_profiles, name); + + if (!existing) { + ESP_LOGD(TAG, "Loading new audio control profile with name: %s", name); + actrls_init_profile(name, false); + } else { + ESP_LOGD(TAG, "Existing profile %s was referenced", name); + } +} + +/**************************************************************************************** + * + */ +static esp_err_t actrls_process_action(const sys_btns_action* action, sys_btns_action* cur_config_act) { + bool valid_name = action->profile_name && strlen(action->profile_name) > 0; + cur_config_act->type = action->type; + if (valid_name) { + cur_config_act->profile_name = strdup_psram(action->profile_name); + if (!cur_config_act->profile_name) { + ESP_LOGE(TAG, "Error allocating memory for action profile name %s", action->profile_name); + return ESP_ERR_NO_MEM; + } + } + + if (action->type == sys_btns_actions_REMAP) { + if (!valid_name) { + ESP_LOGE(TAG, "Missing name for action %s", sys_btns_actions_name(action->type)); + return ESP_ERR_INVALID_ARG; + } + actrls_parse_action(action->profile_name); + } + return ESP_OK; +} +static esp_err_t actrls_process_press(const sys_btns_press* press, sys_btns_press* cur_config_press) { + esp_err_t err = ESP_OK; + if (press->has_pressed) { + cur_config_press->has_pressed = true; + err = actrls_process_action(&press->pressed, &cur_config_press->pressed); + } + if (err == ESP_OK && press->has_released) { + cur_config_press->has_released = true; + err = actrls_process_action(&press->released, &cur_config_press->released); + } + return err; +} +/**************************************************************************************** + * + */ +static esp_err_t actrls_process_button(const sys_btns_btn* button, actrls_config_t* cur_config) { + esp_err_t err = ESP_OK; + if (button->has_gpio && button->gpio.pin >= 0) { + cur_config->type = button->gpio.level == sys_gpio_lvl_LOW ? BUTTON_LOW : BUTTON_HIGH; + cur_config->gpio = button->gpio.pin; + } + cur_config->pull = button->pull; + cur_config->debounce = button->debounce; + cur_config->long_press = button->longduration; + err = actrls_process_press(&button->normal, &cur_config->normal); + if (err == ESP_OK) err = actrls_process_press(&button->longpress, &cur_config->longpress); + if (err == ESP_OK) err = actrls_process_press(&button->shifted, &cur_config->shifted); + if (err == ESP_OK) err = actrls_process_press(&button->longshifted, &cur_config->longshifted); + cur_config->shifter_gpio = button->shifter; + return err; +} + +/**************************************************************************************** + * + */ +static actrls_config_t* actrls_init_alloc_structure(const sys_btns_profile* buttons, const char* name) { + actrls_config_t* json_config = NULL; + + // Check if the main profiles array was created + if (!control_profiles) { + control_profiles = cJSON_CreateObject(); + } + ESP_LOGD(TAG, "config contains %u button definitions", buttons->buttons_count); + if (buttons->buttons_count != 0) { + json_config = calloc(sizeof(actrls_config_t) * (buttons->buttons_count + 1), 1); + if (json_config) { + json_config[buttons->buttons_count].gpio = -1; + } else { + ESP_LOGE(TAG, "Unable to allocate memory to hold configuration for %u buttons ", buttons->buttons_count); + } + } else { + ESP_LOGE(TAG, "No button found in configuration structure"); + } + + // we're cheating here; we're going to store the control profile + // pointer as a string reference; this will prevent cJSON + // from trying to free the structure if we ever want to free the object + cJSON* new_profile = cJSON_CreateStringReference((const char*)json_config); + cJSON_AddItemToObject(control_profiles, name, new_profile); + + return json_config; +} + +/**************************************************************************************** + * + */ +static void actrls_defaults(actrls_config_t* config) { + sys_btns_press PressDefault = sys_btns_press_init_default; + config->type = BUTTON_LOW; + config->pull = false; + config->debounce = 0; + config->long_press = 0; + config->shifter_gpio = -1; + config->normal = PressDefault; + config->longpress = PressDefault; + config->shifted = PressDefault; + config->longshifted = PressDefault; +} + +/**************************************************************************************** + * + */ +static sys_btns_profile* get_profile(const char* profile_name) { + ESP_LOGD(TAG, "Looking for profile name %s in %d profile(s)", profile_name, platform->dev.buttons_profiles_count); + for (int i = 0; i < platform->dev.buttons_profiles_count; i++) { + if (strcasecmp(platform->dev.buttons_profiles[i].profile_name, profile_name) == 0) { + ESP_LOGD(TAG, "Found profile name %s", platform->dev.buttons_profiles[i].profile_name); + return &platform->dev.buttons_profiles[i]; + } else { + ESP_LOGD(TAG, "Profile name %s doesn't match %s", platform->dev.buttons_profiles[i].profile_name, profile_name); + } + } + ESP_LOGW(TAG, "Button control profile %s not found", profile_name); + return NULL; +} + +/**************************************************************************************** + * + */ +static esp_err_t actrls_init_profile(const char* profile_name, bool create) { + esp_err_t err = ESP_OK; + actrls_config_t* cur_config = NULL; + actrls_config_t* config_root = NULL; + sys_btns_profile* config; + + if (!profile_name || strlen(profile_name) == 0) { + ESP_LOGI(TAG, "No control button configured"); + return ESP_OK; + } + ESP_LOGI(TAG, "Initializing button control profile %s", profile_name); + config = get_profile(profile_name); + if (!config) { + ESP_LOGE(TAG, "Invalid button control profile %s", profile_name); + goto exit; + } + + if (config->buttons_count == 0) { + ESP_LOGE(TAG, "No button found %s", profile_name); + err = ESP_FAIL; + } else { + ESP_LOGD(TAG, "Number of buttons: %d", config->buttons_count); + cur_config = config_root = actrls_init_alloc_structure(config, profile_name); + if (!cur_config) { + ESP_LOGE(TAG, "Config buffer was empty. "); + err = ESP_FAIL; + goto exit; + } + ESP_LOGD(TAG, "Processing button definitions. "); + for (int i = 0; i < config->buttons_count; i++) { + ESP_LOGD(TAG, "Processing button %d of %d for profile %s. ", i + 1, config->buttons_count, profile_name); + actrls_defaults(cur_config); + esp_err_t loc_err = actrls_process_button(&config->buttons[i], cur_config); + err = (err == ESP_OK) ? loc_err : err; + if (loc_err == ESP_OK) { + if (create) + button_create((void*)cur_config, cur_config->gpio, cur_config->type, cur_config->pull, cur_config->debounce, control_handler, + cur_config->long_press, cur_config->shifter_gpio); + } else { + ESP_LOGE(TAG, "Error parsing button structure. Button will not be registered."); + } + + cur_config++; + } + } + // Now update the global json_config object. If we are recursively processing menu structures, + // the last init that completes will assigh the first json config object found, which will match + // the default config from nvs. + json_config = config_root; +exit: + return err; +} +/**************************************************************************************** + * + */ +void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_t* hook, actrls_ir_handler_t* ir_handler) { + memcpy(default_controls, controls, sizeof(actrls_t)); + memcpy(current_controls, default_controls, sizeof(actrls_t)); + default_hook = current_hook = hook; + default_raw_controls = current_raw_controls = raw_controls; + default_ir_handler = current_ir_handler = ir_handler; +} + +/**************************************************************************************** + * + */ +void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t* hook, actrls_ir_handler_t* ir_handler) { + memcpy(current_controls, controls, sizeof(actrls_t)); + current_hook = hook; + current_raw_controls = raw_controls; + current_ir_handler = ir_handler; +} + +/**************************************************************************************** + * */ void actrls_unset(void) { - memcpy(current_controls, default_controls, sizeof(actrls_t)); - current_hook = default_hook; - current_raw_controls = default_raw_controls; - current_ir_handler = default_ir_handler; + memcpy(current_controls, default_controls, sizeof(actrls_t)); + current_hook = default_hook; + current_raw_controls = default_raw_controls; + current_ir_handler = default_ir_handler; } diff --git a/components/services/audio_controls.h b/components/services/audio_controls.h index 2e45c20d..b4b77f4e 100644 --- a/components/services/audio_controls.h +++ b/components/services/audio_controls.h @@ -9,27 +9,28 @@ #pragma once #include "buttons.h" +#include "Buttons.pb.h" // BEWARE: this is the index of the array of action below (change actrls_action_s as well!) -typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, - ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT, - BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT, - BCTRLS_PS0,BCTRLS_PS1,BCTRLS_PS2,BCTRLS_PS3,BCTRLS_PS4,BCTRLS_PS5,BCTRLS_PS6,BCTRLS_PS7,BCTRLS_PS8,BCTRLS_PS9, - KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH, - ACTRLS_SLEEP, - ACTRLS_REMAP, ACTRLS_MAX - } actrls_action_e; +// typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, +// ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT, +// BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT, +// BCTRLS_PS0,BCTRLS_PS1,BCTRLS_PS2,BCTRLS_PS3,BCTRLS_PS4,BCTRLS_PS5,BCTRLS_PS6,BCTRLS_PS7,BCTRLS_PS8,BCTRLS_PS9, +// KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH, +// ACTRLS_SLEEP, +// ACTRLS_REMAP, ACTRLS_MAX +// } actrls_action_e; typedef void (*actrls_handler)(bool pressed); -typedef actrls_handler actrls_t[ACTRLS_MAX - ACTRLS_NONE - 1]; -typedef bool actrls_hook_t(int gpio, actrls_action_e action, button_event_e event, button_press_e press, bool long_press); +typedef actrls_handler actrls_t[sys_btns_actions_MAX- sys_btns_actions_A_NONE - 1]; +typedef bool actrls_hook_t(int gpio, sys_btns_action *action, button_event_e event, button_press_e press, bool long_press); typedef bool actrls_ir_handler_t(uint16_t addr, uint16_t cmd); // BEWARE any change to struct below must be mapped to actrls_config_map -typedef struct { - actrls_action_e action; - const char * name; -} actrls_action_detail_t; +// typedef struct { +// actrls_action_e action; +// const char * name; +// } actrls_action_detail_t; typedef struct actrl_config_s { int gpio; int type; @@ -37,7 +38,7 @@ typedef struct actrl_config_s { int debounce; int long_press; int shifter_gpio; - actrls_action_detail_t normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased + sys_btns_press normal, longpress, shifted, longshifted; // [0] keypressed, [1] keyreleased } actrls_config_t; esp_err_t actrls_init(const char *profile_name); diff --git a/components/services/battery.c b/components/services/battery.c index b842c1f4..85472f09 100644 --- a/components/services/battery.c +++ b/components/services/battery.c @@ -16,7 +16,7 @@ #include "esp_log.h" #include "driver/adc.h" #include "battery.h" -#include "Configurator.h" +#include "Config.h" /* There is a bug in esp32 which causes a spurious interrupt on gpio 36/39 when @@ -32,11 +32,11 @@ static const char *TAG = "battery"; static struct { float sum, avg, scale; int count; - sys_Battery * battery_config; + sys_battery_config * battery_config; TimerHandle_t timer; } battery; -#define BATTERY_CHANNEL(b) (b.battery_config?b.battery_config->channel - sys_BatteryChannelEnum_CH0:-1) -#define ATTENUATION(b) (b.battery_config?b.battery_config->atten - sys_BatteryAttenEnum_ATT_0:-1) +#define BATTERY_CHANNEL(b) (b.battery_config?b.battery_config->channel - sys_battery_channels_CH0:-1) +#define ATTENUATION(b) (b.battery_config?b.battery_config->atten - sys_battery_atten_ATT_0:-1) void (*battery_handler_svc)(float value, int cells); /**************************************************************************************** diff --git a/components/services/buttons.c b/components/services/buttons.c index 1c2a406e..814daf07 100644 --- a/components/services/buttons.c +++ b/components/services/buttons.c @@ -1,4 +1,4 @@ -/* +/* * a crude button press/long-press/shift management based on GPIO * * (c) Philippe G. 2019, philippe_44@outlook.com @@ -7,448 +7,458 @@ * https://opensource.org/licenses/MIT * */ - -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/timers.h" -#include "freertos/queue.h" -#include "esp_system.h" -#include "esp_log.h" -#include "esp_task.h" +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "buttons.h" #include "driver/gpio.h" #include "driver/rmt.h" -#include "gpio_exp.h" -#include "buttons.h" -#include "services.h" -#include "rotary_encoder.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_task.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/timers.h" #include "globdefs.h" +#include "gpio_exp.h" +#include "rotary_encoder.h" +#include "services.h" +#include +#include +#include +#include -static const char * TAG = "buttons"; +static const char* TAG = "buttons"; static EXT_RAM_ATTR int n_buttons; static EXT_RAM_ATTR uint32_t buttons_idle_since; -#define BUTTON_STACK_SIZE 4096 -#define MAX_BUTTONS 32 -#define DEBOUNCE 50 -#define BUTTON_QUEUE_LEN 10 +#define BUTTON_STACK_SIZE 4096 +#define MAX_BUTTONS 32 +#define DEBOUNCE 50 +#define BUTTON_QUEUE_LEN 10 static EXT_RAM_ATTR struct button_s { - void *client; - int gpio; - int debounce; - button_handler handler; - struct button_s *self, *shifter; - int shifter_gpio; // this one is just for post-creation - int long_press; - bool long_timer, shifted, shifting; - int type, level; - TimerHandle_t timer; + void* client; + int gpio; + int debounce; + button_handler handler; + struct button_s *self, *shifter; + int shifter_gpio; // this one is just for post-creation + int long_press; + bool long_timer, shifted, shifting; + int type, level; + TimerHandle_t timer; } buttons[MAX_BUTTONS]; // can't use EXT_RAM_ATTR for initialized structure static struct { - int gpio, level; - struct button_s *button; -} polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} }; + int gpio, level; + struct button_s* button; +} polled_gpio[] = {{36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL}}; static TimerHandle_t polled_timer; static EXT_RAM_ATTR struct { - QueueHandle_t queue; - void *client; - rotary_encoder_info_t info; - int A, B, SW; - rotary_handler handler; + QueueHandle_t queue; + void* client; + rotary_encoder_info_t info; + int A, B, SW; + rotary_handler handler; } rotary; static EXT_RAM_ATTR struct { - RingbufHandle_t rb; - infrared_handler handler; + RingbufHandle_t rb; + infrared_handler handler; } infrared; static EXT_RAM_ATTR QueueHandle_t button_queue; static EXT_RAM_ATTR QueueSetHandle_t common_queue_set; static void buttons_task(void* arg); -static void buttons_handler(struct button_s *button, int level); +static void buttons_handler(struct button_s* button, int level); /**************************************************************************************** * Start task needed by button,s rotaty and infrared */ static void common_task_init(void) { - static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); - static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__ ((aligned (4))); - - if (!common_queue_set) { - common_queue_set = xQueueCreateSet(BUTTON_QUEUE_LEN + 1); - xTaskCreateStatic( (TaskFunction_t) buttons_task, "buttons", BUTTON_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 2, xStack, &xTaskBuffer); - } - } + static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__((aligned(4))); + static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__((aligned(4))); + + if (!common_queue_set) { + ESP_LOGD(TAG,"Creating buttons task with a queue set length of %d",BUTTON_QUEUE_LEN+1); + common_queue_set = xQueueCreateSet(BUTTON_QUEUE_LEN + 1); + xTaskCreateStatic((TaskFunction_t)buttons_task, "buttons", BUTTON_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 2, xStack, &xTaskBuffer); + } +} /**************************************************************************************** * GPIO low-level ISR handler */ -static void IRAM_ATTR gpio_isr_handler(void* arg) -{ - struct button_s *button = (struct button_s*) arg; - BaseType_t woken = pdFALSE; +static void IRAM_ATTR gpio_isr_handler(void* arg) { + struct button_s* button = (struct button_s*)arg; + BaseType_t woken = pdFALSE; - if (xTimerGetPeriod(button->timer) > pdMS_TO_TICKS(button->debounce)) { - if (button->gpio < GPIO_NUM_MAX) xTimerChangePeriodFromISR(button->timer, pdMS_TO_TICKS(button->debounce), &woken); - else xTimerChangePeriod(button->timer, pdMS_TO_TICKS(button->debounce), pdMS_TO_TICKS(10)); - } else { - if (button->gpio < GPIO_NUM_MAX) xTimerResetFromISR(button->timer, &woken); - else xTimerReset(button->timer, portMAX_DELAY); - } + if (xTimerGetPeriod(button->timer) > pdMS_TO_TICKS(button->debounce)) { + if (button->gpio < GPIO_NUM_MAX) + xTimerChangePeriodFromISR(button->timer, pdMS_TO_TICKS(button->debounce), &woken); + else + xTimerChangePeriod(button->timer, pdMS_TO_TICKS(button->debounce), pdMS_TO_TICKS(10)); + } else { + if (button->gpio < GPIO_NUM_MAX) + xTimerResetFromISR(button->timer, &woken); + else + xTimerReset(button->timer, portMAX_DELAY); + } - if (woken) portYIELD_FROM_ISR(); + if (woken) portYIELD_FROM_ISR(); - ESP_EARLY_LOGD(TAG, "INT gpio %u level %u", button->gpio, button->level); + ESP_EARLY_LOGD(TAG, "INT gpio %u level %u", button->gpio, button->level); } /**************************************************************************************** * Buttons debounce/longpress timer */ -static void buttons_timer_handler( TimerHandle_t xTimer ) { - struct button_s *button = (struct button_s*) pvTimerGetTimerID (xTimer); - // if this is an expanded GPIO, must give cache a chance - buttons_handler(button, gpio_exp_get_level(button->gpio, (button->debounce * 3) / 2, NULL)); +static void buttons_timer_handler(TimerHandle_t xTimer) { + struct button_s* button = (struct button_s*)pvTimerGetTimerID(xTimer); + // if this is an expanded GPIO, must give cache a chance + buttons_handler(button, gpio_exp_get_level(button->gpio, (button->debounce * 3) / 2, NULL)); } /**************************************************************************************** * Buttons polling timer */ -static void buttons_polling( TimerHandle_t xTimer ) { - for (int i = 0; polled_gpio[i].gpio != -1; i++) { - if (!polled_gpio[i].button) continue; - - int level = gpio_get_level(polled_gpio[i].gpio); - - if (level != polled_gpio[i].level) { - polled_gpio[i].level = level; - buttons_handler(polled_gpio[i].button, level); - } - } +static void buttons_polling(TimerHandle_t xTimer) { + for (int i = 0; polled_gpio[i].gpio != -1; i++) { + if (!polled_gpio[i].button) continue; + + int level = gpio_get_level(polled_gpio[i].gpio); + + if (level != polled_gpio[i].level) { + polled_gpio[i].level = level; + buttons_handler(polled_gpio[i].button, level); + } + } } /**************************************************************************************** * Buttons timer handler for press/longpress */ -static void buttons_handler(struct button_s *button, int level) { - button->level = level; +static void buttons_handler(struct button_s* button, int level) { + button->level = level; - if (button->shifter && button->shifter->type == button->shifter->level) button->shifter->shifting = true; + if (button->shifter && button->shifter->type == button->shifter->level) button->shifter->shifting = true; - if (button->long_press && !button->long_timer && button->level == button->type) { - // detect a long press, so hold event generation - ESP_LOGD(TAG, "setting long timer gpio:%u level:%u", button->gpio, button->level); - xTimerChangePeriod(button->timer, button->long_press / portTICK_RATE_MS, 0); - button->long_timer = true; - } else { - // send a button pressed/released event (content is copied in queue) - ESP_LOGD(TAG, "sending event for gpio:%u level:%u", button->gpio, button->level); - // queue will have a copy of button's context - xQueueSend(button_queue, button, 0); - button->long_timer = false; - } + if (button->long_press && !button->long_timer && button->level == button->type) { + // detect a long press, so hold event generation + ESP_LOGD(TAG, "setting long timer gpio:%u level:%u", button->gpio, button->level); + xTimerChangePeriod(button->timer, button->long_press / portTICK_RATE_MS, 0); + button->long_timer = true; + } else { + // send a button pressed/released event (content is copied in queue) + ESP_LOGD(TAG, "sending event for gpio:%u level:%u", button->gpio, button->level); + // queue will have a copy of button's context + xQueueSend(button_queue, button, 0); + button->long_timer = false; + } } /**************************************************************************************** * Get inactivity callback */ -static uint32_t buttons_idle_callback(void) { - return pdTICKS_TO_MS(xTaskGetTickCount()) - buttons_idle_since; -} +static uint32_t buttons_idle_callback(void) { return pdTICKS_TO_MS(xTaskGetTickCount()) - buttons_idle_since; } /**************************************************************************************** * Tasks that calls the appropriate functions when buttons are pressed */ static void buttons_task(void* arg) { - ESP_LOGI(TAG, "starting button tasks"); - - buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); + ESP_LOGI(TAG, "starting button tasks"); + + buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); services_sleep_setsleeper(buttons_idle_callback); - + while (1) { - QueueSetMemberHandle_t xActivatedMember; + QueueSetMemberHandle_t xActivatedMember; bool active = true; - // wait on button, rotary and infrared queues - if ((xActivatedMember = xQueueSelectFromSet( common_queue_set, portMAX_DELAY )) == NULL) continue; - - if (xActivatedMember == button_queue) { - struct button_s button; - button_event_e event; - button_press_e press; - - // received a button event - xQueueReceive(button_queue, &button, 0); + // wait on button, rotary and infrared queues + if ((xActivatedMember = xQueueSelectFromSet(common_queue_set, portMAX_DELAY)) == NULL) continue; - event = (button.level == button.type) ? BUTTON_PRESSED : BUTTON_RELEASED; + if (xActivatedMember == button_queue) { + struct button_s button; + button_event_e event; + button_press_e press; - ESP_LOGD(TAG, "received event:%u from gpio:%u level:%u (timer %u shifting %u)", event, button.gpio, button.level, button.long_timer, button.shifting); + // received a button event + xQueueReceive(button_queue, &button, 0); - // find if shifting is activated - if (button.shifter && button.shifter->type == button.shifter->level) press = BUTTON_SHIFTED; - else press = BUTTON_NORMAL; - - /* - long_timer will be set either because we truly have a long press - or we have a release before the long press timer elapsed, so two - events shall be sent - */ - if (button.long_timer) { - if (event == BUTTON_RELEASED) { - // early release of a long-press button, send press/release - if (!button.shifting) { - button.handler(button.client, BUTTON_PRESSED, press, false); - button.handler(button.client, BUTTON_RELEASED, press, false); - } - // button is a copy, so need to go to real context - button.self->shifting = false; - } else if (!button.shifting) { - // normal long press and not shifting so don't discard - button.handler(button.client, BUTTON_PRESSED, press, true); - } - } else { - // normal press/release of a button or release of a long-press button - if (!button.shifting) button.handler(button.client, event, press, button.long_press); - // button is a copy, so need to go to real context - button.self->shifting = false; - } - } else if (xActivatedMember == rotary.queue) { - rotary_encoder_event_t event = { 0 }; - - // received a rotary event - xQueueReceive(rotary.queue, &event, 0); + event = (button.level == button.type) ? BUTTON_PRESSED : BUTTON_RELEASED; + + ESP_LOGD(TAG, "received event:%u from gpio:%u level:%u (timer %u shifting %u)", event, button.gpio, button.level, button.long_timer, + button.shifting); + + // find if shifting is activated + if (button.shifter && button.shifter->type == button.shifter->level) + press = BUTTON_SHIFTED; + else + press = BUTTON_NORMAL; + + /* + long_timer will be set either because we truly have a long press + or we have a release before the long press timer elapsed, so two + events shall be sent + */ + if (button.long_timer) { + if (event == BUTTON_RELEASED) { + // early release of a long-press button, send press/release + if (!button.shifting) { + button.handler(button.client, BUTTON_PRESSED, press, false); + button.handler(button.client, BUTTON_RELEASED, press, false); + } + // button is a copy, so need to go to real context + button.self->shifting = false; + } else if (!button.shifting) { + // normal long press and not shifting so don't discard + button.handler(button.client, BUTTON_PRESSED, press, true); + } + } else { + // normal press/release of a button or release of a long-press button + if (!button.shifting) button.handler(button.client, event, press, button.long_press); + // button is a copy, so need to go to real context + button.self->shifting = false; + } + } else if (xActivatedMember == rotary.queue) { + rotary_encoder_event_t event = {0}; + + // received a rotary event + xQueueReceive(rotary.queue, &event, 0); + + ESP_LOGD(TAG, "Event: position %d, direction %s", event.state.position, + event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET"); + + rotary.handler(rotary.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? ROTARY_RIGHT : ROTARY_LEFT, false); + } else { + // this is IR + active = infrared_receive(infrared.rb, infrared.handler); + } - ESP_LOGD(TAG, "Event: position %d, direction %s", event.state.position, - event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET"); - - rotary.handler(rotary.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? - ROTARY_RIGHT : ROTARY_LEFT, false); - } else { - // this is IR - active = infrared_receive(infrared.rb, infrared.handler); - } - // mark the last activity if (active) buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); } -} - +} + /**************************************************************************************** * dummy button handler - */ -void dummy_handler(void *id, button_event_e event, button_press_e press) { - ESP_LOGW(TAG, "should not be here"); -} + */ +void dummy_handler(void* id, button_event_e event, button_press_e press) { ESP_LOGW(TAG, "should not be here"); } /**************************************************************************************** - * Create buttons + * Create buttons */ -void button_create(void *client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) { - if (n_buttons >= MAX_BUTTONS) return; +void button_create(void* client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) { + if (n_buttons >= MAX_BUTTONS) return; - ESP_LOGI(TAG, "Creating button using GPIO %u, type %u, pull-up/down %u, long press %u shifter %d", gpio, type, pull, long_press, shifter_gpio); + ESP_LOGI(TAG, "Creating button using GPIO %u, type %s, %s pull-up/down, long press %u shifter %d", gpio, + sys_gpio_lvl_name(type == 0 ? sys_gpio_lvl_LOW : sys_gpio_lvl_HIGH), pull?"with":"without", long_press, shifter_gpio); - if (!n_buttons) { - button_queue = xQueueCreate(BUTTON_QUEUE_LEN, sizeof(struct button_s)); - common_task_init(); - xQueueAddToSet( button_queue, common_queue_set ); - } - - // just in case this structure is allocated in a future release - memset(buttons + n_buttons, 0, sizeof(struct button_s)); + if (!n_buttons) { + ESP_LOGD(TAG,"Creating new buttton message queue with a length of %d entries",BUTTON_QUEUE_LEN); + button_queue = xQueueCreate(BUTTON_QUEUE_LEN, sizeof(struct button_s)); + common_task_init(); + xQueueAddToSet(button_queue, common_queue_set); + } - // set mandatory parameters - buttons[n_buttons].client = client; - buttons[n_buttons].gpio = gpio; - buttons[n_buttons].debounce = debounce ? debounce: DEBOUNCE; - buttons[n_buttons].handler = handler; - buttons[n_buttons].long_press = long_press; - buttons[n_buttons].shifter_gpio = shifter_gpio; - buttons[n_buttons].type = type; - buttons[n_buttons].timer = xTimerCreate("buttonTimer", buttons[n_buttons].debounce / portTICK_RATE_MS, pdFALSE, (void *) &buttons[n_buttons], buttons_timer_handler); - buttons[n_buttons].self = buttons + n_buttons; + // just in case this structure is allocated in a future release + memset(buttons + n_buttons, 0, sizeof(struct button_s)); - for (int i = 0; i < n_buttons; i++) { - // first try to find our shifter - if (buttons[i].gpio == shifter_gpio) { - buttons[n_buttons].shifter = buttons + i; - // a shifter must have a long-press handler - if (!buttons[i].long_press) buttons[i].long_press = -1; - } - // then try to see if we are a non-assigned shifter - if (buttons[i].shifter_gpio == gpio) { - buttons[i].shifter = buttons + n_buttons; - ESP_LOGI(TAG, "post-assigned shifter gpio %u", buttons[i].gpio); - } - } + // set mandatory parameters + buttons[n_buttons].client = client; + buttons[n_buttons].gpio = gpio; + buttons[n_buttons].debounce = debounce ? debounce : DEBOUNCE; + buttons[n_buttons].handler = handler; + buttons[n_buttons].long_press = long_press; + buttons[n_buttons].shifter_gpio = shifter_gpio; + buttons[n_buttons].type = type; + buttons[n_buttons].timer = + xTimerCreate("buttonTimer", buttons[n_buttons].debounce / portTICK_RATE_MS, pdFALSE, (void*)&buttons[n_buttons], buttons_timer_handler); + buttons[n_buttons].self = buttons + n_buttons; - gpio_pad_select_gpio_x(gpio); - gpio_set_direction_x(gpio, GPIO_MODE_INPUT); + for (int i = 0; i < n_buttons; i++) { + // first try to find our shifter + if (buttons[i].gpio == shifter_gpio) { + buttons[n_buttons].shifter = buttons + i; + // a shifter must have a long-press handler + if (!buttons[i].long_press) buttons[i].long_press = -1; + } + // then try to see if we are a non-assigned shifter + if (buttons[i].shifter_gpio == gpio) { + buttons[i].shifter = buttons + n_buttons; + ESP_LOGI(TAG, "post-assigned shifter gpio %u", buttons[i].gpio); + } + } - // do we need pullup or pulldown - if (pull) { - if (GPIO_IS_VALID_OUTPUT_GPIO(gpio) || gpio >= GPIO_NUM_MAX) { - if (type == BUTTON_LOW) gpio_set_pull_mode_x(gpio, GPIO_PULLUP_ONLY); - else gpio_set_pull_mode_x(gpio, GPIO_PULLDOWN_ONLY); - } else { - ESP_LOGW(TAG, "cannot set pull up/down for gpio %u", gpio); - } - } - - // and initialize level ... - buttons[n_buttons].level = gpio_get_level_x(gpio); - - // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated - for (int i = 0; polled_gpio[i].gpio != -1; i++) if (polled_gpio[i].gpio == gpio) { - if (!polled_timer) { - polled_timer = xTimerCreate("buttonsPolling", 100 / portTICK_RATE_MS, pdTRUE, polled_gpio, buttons_polling); - xTimerStart(polled_timer, portMAX_DELAY); - } - - polled_gpio[i].button = buttons + n_buttons; - polled_gpio[i].level = gpio_get_level(gpio); - ESP_LOGW(TAG, "creating polled gpio %u, level %u", gpio, polled_gpio[i].level); - - gpio = -1; - break; - } - - // only create ISR if this is not a polled gpio - if (gpio != -1) { - // we need any edge detection - gpio_set_intr_type_x(gpio, GPIO_INTR_ANYEDGE); - gpio_isr_handler_add_x(gpio, gpio_isr_handler, buttons + n_buttons); - gpio_intr_enable_x(gpio); - } + gpio_pad_select_gpio_x(gpio); + gpio_set_direction_x(gpio, GPIO_MODE_INPUT); - n_buttons++; -} + // do we need pullup or pulldown + if (pull) { + if (GPIO_IS_VALID_OUTPUT_GPIO(gpio) || gpio >= GPIO_NUM_MAX) { + if (type == BUTTON_LOW) + gpio_set_pull_mode_x(gpio, GPIO_PULLUP_ONLY); + else + gpio_set_pull_mode_x(gpio, GPIO_PULLDOWN_ONLY); + } else { + ESP_LOGW(TAG, "cannot set pull up/down for gpio %u", gpio); + } + } -/**************************************************************************************** - * Get stored id - */ -void *button_get_client(int gpio) { - for (int i = 0; i < n_buttons; i++) { - if (buttons[i].gpio == gpio) return buttons[i].client; - } - return NULL; + // and initialize level ... + buttons[n_buttons].level = gpio_get_level_x(gpio); + + // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated + for (int i = 0; polled_gpio[i].gpio != -1; i++) + if (polled_gpio[i].gpio == gpio) { + if (!polled_timer) { + polled_timer = xTimerCreate("buttonsPolling", 100 / portTICK_RATE_MS, pdTRUE, polled_gpio, buttons_polling); + xTimerStart(polled_timer, portMAX_DELAY); + } + + polled_gpio[i].button = buttons + n_buttons; + polled_gpio[i].level = gpio_get_level(gpio); + ESP_LOGW(TAG, "creating polled gpio %u, level %u", gpio, polled_gpio[i].level); + + gpio = -1; + break; + } + + // only create ISR if this is not a polled gpio + if (gpio != -1) { + // we need any edge detection + gpio_set_intr_type_x(gpio, GPIO_INTR_ANYEDGE); + gpio_isr_handler_add_x(gpio, gpio_isr_handler, buttons + n_buttons); + gpio_intr_enable_x(gpio); + } + + n_buttons++; } /**************************************************************************************** * Get stored id */ -bool button_is_pressed(int gpio, void *client) { - for (int i = 0; i < n_buttons; i++) { - if (gpio != -1 && buttons[i].gpio == gpio) return buttons[i].level == buttons[i].type; - else if (client && buttons[i].client == client) return buttons[i].level == buttons[i].type; - } - return false; +void* button_get_client(int gpio) { + for (int i = 0; i < n_buttons; i++) { + if (buttons[i].gpio == gpio) return buttons[i].client; + } + return NULL; } /**************************************************************************************** - * Update buttons + * Get stored id */ -void *button_remap(void *client, int gpio, button_handler handler, int long_press, int shifter_gpio) { - int i; - struct button_s *button = NULL; - void *prev_client; - - ESP_LOGI(TAG, "remapping GPIO %u, long press %u shifter %u", gpio, long_press, shifter_gpio); +bool button_is_pressed(int gpio, void* client) { + for (int i = 0; i < n_buttons; i++) { + if (gpio != -1 && buttons[i].gpio == gpio) + return buttons[i].level == buttons[i].type; + else if (client && buttons[i].client == client) + return buttons[i].level == buttons[i].type; + } + return false; +} - // find button - for (i = 0; i < n_buttons; i++) { - if (buttons[i].gpio == gpio) { - button = buttons + i; - break; - } - } - - // don't know what we are doing here - if (!button) return NULL; - - prev_client = button->client; - button->client = client; - button->handler = handler; - button->long_press = long_press; - button->shifter_gpio = shifter_gpio; +/**************************************************************************************** + * Update buttons + */ +void* button_remap(void* client, int gpio, button_handler handler, int long_press, int shifter_gpio) { + int i; + struct button_s* button = NULL; + void* prev_client; - // find our shifter (if any) - for (i = 0; shifter_gpio != -1 && i < n_buttons; i++) { - if (buttons[i].gpio == shifter_gpio) { - button->shifter = buttons + i; - // a shifter must have a long-press handler - if (!buttons[i].long_press) buttons[i].long_press = -1; - break; - } - } - - return prev_client; + ESP_LOGI(TAG, "remapping GPIO %u, long press %u shifter %u", gpio, long_press, shifter_gpio); + + // find button + for (i = 0; i < n_buttons; i++) { + if (buttons[i].gpio == gpio) { + button = buttons + i; + break; + } + } + + // don't know what we are doing here + if (!button) return NULL; + + prev_client = button->client; + button->client = client; + button->handler = handler; + button->long_press = long_press; + button->shifter_gpio = shifter_gpio; + + // find our shifter (if any) + for (i = 0; shifter_gpio != -1 && i < n_buttons; i++) { + if (buttons[i].gpio == shifter_gpio) { + button->shifter = buttons + i; + // a shifter must have a long-press handler + if (!buttons[i].long_press) buttons[i].long_press = -1; + break; + } + } + + return prev_client; } /**************************************************************************************** * Rotary encoder handler */ -static void rotary_button_handler(void *id, button_event_e event, button_press_e mode, bool long_press) { - ESP_LOGI(TAG, "Rotary push-button %d", event); - rotary.handler(id, event == BUTTON_PRESSED ? ROTARY_PRESSED : ROTARY_RELEASED, long_press); +static void rotary_button_handler(void* id, button_event_e event, button_press_e mode, bool long_press) { + ESP_LOGI(TAG, "Rotary push-button %d", event); + rotary.handler(id, event == BUTTON_PRESSED ? ROTARY_PRESSED : ROTARY_RELEASED, long_press); } /**************************************************************************************** * Create rotary encoder */ -bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler) { - // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated - if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) { - ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B); - return false; - } +bool create_rotary(void* id, int A, int B, int SW, int long_press, rotary_handler handler) { + // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated + if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) { + ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B); + return false; + } + + rotary.A = A; + rotary.B = B; + rotary.SW = SW; + rotary.client = id; + rotary.handler = handler; - rotary.A = A; - rotary.B = B; - rotary.SW = SW; - rotary.client = id; - rotary.handler = handler; - // Initialise the rotary encoder device with the GPIOs for A and B signals rotary_encoder_init(&rotary.info, A, B); - + // Create a queue for events from the rotary encoder driver. rotary.queue = rotary_encoder_create_queue(); rotary_encoder_set_queue(&rotary.info, rotary.queue); - - common_task_init(); - xQueueAddToSet( rotary.queue, common_queue_set ); - // create companion button if rotary has a switch - if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1); - - ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW); - - return true; -} + common_task_init(); + xQueueAddToSet(rotary.queue, common_queue_set); + + // create companion button if rotary has a switch + if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1); + + ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW); + + return true; +} /**************************************************************************************** * Create Infrared */ bool create_infrared(int gpio, infrared_handler handler, infrared_mode_t mode) { - // initialize IR infrastructure - infrared_init(&infrared.rb, gpio, mode); - infrared.handler = handler; - - // join the queue set - common_task_init(); - xRingbufferAddToQueueSetRead(infrared.rb, common_queue_set); - - ESP_LOGI(TAG, "Created infrared receiver using GPIO %u", gpio); - - return (infrared.rb != NULL); -} + // initialize IR infrastructure + infrared_init(&infrared.rb, gpio, mode); + infrared.handler = handler; + + // join the queue set + common_task_init(); + xRingbufferAddToQueueSetRead(infrared.rb, common_queue_set); + + ESP_LOGI(TAG, "Created infrared receiver using GPIO %u", gpio); + + return (infrared.rb != NULL); +} diff --git a/components/services/globdefs.h b/components/services/globdefs.h index b3816e06..a5ae7039 100644 --- a/components/services/globdefs.h +++ b/components/services/globdefs.h @@ -10,14 +10,11 @@ #pragma once -#define I2C_SYSTEM_PORT 1 #define SPI_SYSTEM_HOST SPI2_HOST #define RMT_NEXT_TX_CHANNEL() rmt_system_base_tx_channel++; #define RMT_NEXT_RX_CHANNEL() rmt_system_base_rx_channel--; -extern int i2c_system_port; -extern int i2c_system_speed; extern int spi_system_host; extern int spi_system_dc_gpio; extern int rmt_system_base_tx_channel; diff --git a/components/services/gpio_exp.c b/components/services/gpio_exp.c index 2f86ff33..ea35180b 100644 --- a/components/services/gpio_exp.c +++ b/components/services/gpio_exp.c @@ -18,7 +18,7 @@ #include "driver/i2c.h" #include "driver/spi_master.h" #include "gpio_exp.h" - +#include "GPIO.pb.h" #define GPIO_EXP_INTR 0x100 #define GPIO_EXP_WRITE 0x200 @@ -181,7 +181,6 @@ gpio_exp_t* gpio_exp_create(const gpio_exp_config_t *config) { ESP_LOGE(TAG, "Cannot create GPIO expander %s, check i2c/spi configuration", config->model); return NULL; } - n_expanders++; expander->first = config->base; expander->last = config->base + config->count - 1; @@ -197,6 +196,12 @@ gpio_exp_t* gpio_exp_create(const gpio_exp_config_t *config) { message_queue = xQueueCreate(4, sizeof(queue_request_t)); service_task = xTaskCreateStatic(service_handler, "gpio_expander", sizeof(xStack), NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer); } + if(config->phy.ena_pin>=0){ + ESP_LOGD(TAG,"Enabling expander with pin %d level %d",config->phy.ena_pin,config->phy.ena_lvl); + gpio_pad_select_gpio(config->phy.ena_pin); + gpio_set_direction(config->phy.ena_pin, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(config->phy.ena_pin, config->phy.ena_lvl); + } // set interrupt if possible if (config->intr >= 0) { @@ -222,7 +227,7 @@ gpio_exp_t* gpio_exp_create(const gpio_exp_config_t *config) { gpio_intr_enable(config->intr); } - ESP_LOGI(TAG, "Create GPIO expander %s at base %u with intr %d at @%x on port/host %d/%d", config->model, config->base, config->intr, config->phy.addr, config->phy.port, config->phy.host); + ESP_LOGI(TAG, "Create GPIO expander %s at base %u with intr %d at @%x on port/host %d/%d, enable pin: %d:%d", config->model, config->base, config->intr, config->phy.addr, config->phy.port, config->phy.host,config->phy.ena_pin,config->phy.ena_lvl); return expander; } @@ -377,6 +382,13 @@ esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, gpio_exp_t *ex /****************************************************************************** * Wrapper function */ + +void esp_rom_gpio_pad_select_gpio_x(uint32_t gpio){ + if (gpio < GPIO_NUM_MAX) { + esp_rom_gpio_pad_select_gpio(gpio); + } +} + esp_err_t gpio_set_pull_mode_x(int gpio, gpio_pull_mode_t mode) { if (gpio < GPIO_NUM_MAX) return gpio_set_pull_mode(gpio, mode); return gpio_exp_set_pull_mode(gpio, mode, NULL); diff --git a/components/services/gpio_exp.h b/components/services/gpio_exp.h index 91339880..1839caff 100644 --- a/components/services/gpio_exp.h +++ b/components/services/gpio_exp.h @@ -11,6 +11,7 @@ #include #include "freertos/FreeRTOS.h" #include "driver/gpio.h" +#include "esp_rom_gpio.h" struct gpio_exp_s; @@ -29,6 +30,8 @@ typedef struct { uint8_t host; uint8_t cs_pin; }; + int8_t ena_pin; // enable pin + int8_t ena_lvl; // enable level } phy; } gpio_exp_config_t; @@ -42,6 +45,7 @@ struct gpio_exp_s* gpio_exp_get_expander(int gpio); For all functions below when is provided, GPIO's can be numbered from 0. If is NULL, then GPIO must start from base OR be on-chip */ +void esp_rom_gpio_pad_select_gpio_x(uint32_t iopad_num); esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, struct gpio_exp_s *expander); esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, struct gpio_exp_s *expander); int gpio_exp_get_level(int gpio, int age, struct gpio_exp_s *expander); diff --git a/components/services/led.c b/components/services/led.c index 41242b77..3f2fa060 100644 --- a/components/services/led.c +++ b/components/services/led.c @@ -5,7 +5,10 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ - +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "led.h" +#include "Config.h" +#include "accessors.h" #include "driver/gpio.h" #include "driver/ledc.h" #include "driver/rmt.h" @@ -14,17 +17,14 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" +#include "globdefs.h" +#include "gpio_exp.h" +#include "services.h" #include #include #include #include #include -#include "Configurator.h" -#include "accessors.h" -#include "globdefs.h" -#include "gpio_exp.h" -#include "led.h" -#include "services.h" #define MAX_LED 8 #define BLOCKTIME 10 // up to portMAX_DELAY @@ -43,7 +43,7 @@ static int8_t led_rmt_channel = -1; static uint32_t scale24(uint32_t bright, uint8_t); static const struct rmt_led_param_s { - sys_LedTypesEnum type; + sys_led_types type; uint8_t bits; // number of ticks in nanoseconds converted in RMT_CLK ticks rmt_item32_t bit_0; @@ -51,7 +51,7 @@ static const struct rmt_led_param_s { uint32_t green, red; uint32_t (*scale)(uint32_t, uint8_t); } rmt_led_param[] = { - {sys_LedTypesEnum_LED_TYPE_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}}, + {sys_led_types_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}}, {{{1000 / RMT_CLK, 1, 350 / RMT_CLK, 0}}}, 0xff0000, 0x00ff00, scale24}, {.type = -1}}; @@ -73,15 +73,9 @@ static struct led_config_s { int gpio; int color; int bright; - sys_LedTypesEnum type; -} green = {.gpio = CONFIG_LED_GREEN_GPIO, - .color = 0, - .bright = -1, - .type = sys_LedTypesEnum_LED_TYPE_GPIO}, - red = {.gpio = CONFIG_LED_RED_GPIO, - .color = 0, - .bright = -1, - .type = sys_LedTypesEnum_LED_TYPE_GPIO}; + sys_led_types type; +} green = {.gpio = -1, .color = 0, .bright = -1, .type = sys_led_types_GPIO}, + red = {.gpio = -1, .color = 0, .bright = -1, .type = sys_led_types_GPIO}; static int led_max = 2; @@ -127,7 +121,7 @@ static void vCallbackFunction(TimerHandle_t xTimer) { if (!led->timer) return; led->on = !led->on; - ESP_EARLY_LOGD(TAG, "led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio, + ESP_EARLY_LOGV(TAG, "led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio, led->on, led->bright); set_level(led, led->on); @@ -231,12 +225,13 @@ int led_allocate(void) { /**************************************************************************************** * */ -bool led_config(int idx, sys_LED* led_config) { +bool led_config(int idx, sys_led_config* led_config) { if (!led_config->has_gpio) { + ESP_LOGD(TAG,"No GPIO configured for %s LED",idx == LED_GREEN ? "GREEN" : "RED"); return false; } if (led_config->gpio.pin < 0) { - ESP_LOGW(TAG, "LED GPIO -1 ignored"); + ESP_LOGD(TAG,"GPIO -1 ignored for %s LED",idx == LED_GREEN ? "GREEN" : "RED"); return false; } if (idx >= MAX_LED) return false; @@ -247,7 +242,7 @@ bool led_config(int idx, sys_LED* led_config) { leds[idx].rmt = NULL; leds[idx].bright = -1; - if (led_config->led_type != sys_LedTypesEnum_LED_TYPE_GPIO) { + if (led_config->led_type != sys_led_types_GPIO) { // first make sure we have a known addressable led for (const struct rmt_led_param_s* p = rmt_led_param; !leds[idx].rmt && p->type >= 0; p++) if (p->type == led_config->led_type) leds[idx].rmt = p; @@ -285,7 +280,7 @@ bool led_config(int idx, sys_LED* led_config) { set_level(leds + idx, false); ESP_LOGI(TAG, "Configuring LED %s %d (on:%d rmt:%s %d%% )", idx == LED_GREEN ? "GREEN" : "RED", - led_config->gpio.pin, led_config->gpio.level, sys_LedTypesEnum_name(led_config->led_type), + led_config->gpio.pin, led_config->gpio.level, sys_led_types_name(led_config->led_type), led_config->brightness); return true; } @@ -294,6 +289,7 @@ bool led_config(int idx, sys_LED* led_config) { * */ static void led_suspend(void) { + ESP_LOGD(TAG,"led_suspend: turning off leds"); led_off(LED_GREEN); led_off(LED_RED); } @@ -316,12 +312,12 @@ void set_led_gpio(int gpio, char* value) { while ((p = strchr(p, ':')) != NULL) { p++; if ((strcasestr(p, "ws2812")) != NULL) - config->type = sys_LedTypesEnum_LED_TYPE_WS2812; + config->type = sys_led_types_WS2812; else config->color = atoi(p); } - if (config->type != sys_LedTypesEnum_LED_TYPE_GPIO) { + if (config->type != sys_led_types_GPIO) { for (const struct rmt_led_param_s* p = rmt_led_param; p->type >= 0; p++) { if (p->type == config->type) { if (config == &green) @@ -335,18 +331,25 @@ void set_led_gpio(int gpio, char* value) { } void led_svc_init(void) { - sys_Gpios* gpios = NULL; + sys_gpios_config* gpios = NULL; + bool found = false; + if (!platform->has_gpios) { + ESP_LOGI(TAG, "No LED configured"); return; } + ESP_LOGI(TAG,"Setting up leds"); gpios = &platform->gpios; if (gpios->has_greenLED) { - led_config(LED_GREEN, &gpios->greenLED); + found = found | led_config(LED_GREEN, &gpios->greenLED); } if (gpios->has_redLED) { - led_config(LED_RED, &gpios->redLED); + found = found | led_config(LED_RED, &gpios->redLED); } - + ESP_LOGD(TAG,"Done setting up leds"); // make sure we switch off all leds (useful for gpio expanders) - services_sleep_setsuspend(led_suspend); + if (found) { + ESP_LOGD(TAG,"Switching leds off"); + services_sleep_setsuspend(led_suspend); + } } diff --git a/components/services/led.h b/components/services/led.h index 155d7637..2317897d 100644 --- a/components/services/led.h +++ b/components/services/led.h @@ -12,7 +12,7 @@ #ifndef LED_H #define LED_H #include "driver/gpio.h" -#include "Configurator.h" +#include "Config.h" enum { LED_GREEN = 0, LED_RED }; #define led_on(idx) led_blink_core(idx, 1, 0, false) @@ -21,7 +21,7 @@ enum { LED_GREEN = 0, LED_RED }; #define led_blink_pushed(idx, on, off) led_blink_core(idx, on, off, true) // if type is LED_GPIO then color set the GPIO logic value for "on" -bool led_config(int idx, sys_LED * led_config); +bool led_config(int idx, sys_led_config * led_config); bool led_brightness(int idx, int percent); bool led_blink_core(int idx, int ontime, int offtime, bool push); bool led_unpush(int idx); diff --git a/components/services/messaging.c b/components/services/messaging.c index b3d2770b..4d052210 100644 --- a/components/services/messaging.c +++ b/components/services/messaging.c @@ -1,20 +1,20 @@ - /** +/** * */ -#include // Required for libtelnet.h -#include -#include "stdbool.h" -#include -#include -#include -#include +#include "config.h" #include "esp_app_trace.h" #include "esp_attr.h" -#include "config.h" +#include "stdbool.h" +#include +#include +#include +#include +#include // Required for libtelnet.h +#include // #include "nvs_utilities.h" -#include "platform_esp32.h" #include "messaging.h" +#include "platform_esp32.h" #include "tools.h" /************************************ * Globals @@ -22,290 +22,293 @@ const static char tag[] = "messaging"; typedef struct { - struct messaging_list_t * next; - char * subscriber_name; - size_t max_count; - RingbufHandle_t buf_handle; + struct messaging_list_t* next; + char* subscriber_name; + size_t max_count; + RingbufHandle_t buf_handle; } messaging_list_t; static messaging_list_t top; #define MSG_LENGTH_AVG 1024 -messaging_list_t * get_struct_ptr(messaging_handle_t handle){ - return (messaging_list_t *)handle; -} -messaging_handle_t get_handle_ptr(messaging_list_t * handle){ - return (messaging_handle_t )handle; -} +messaging_list_t* get_struct_ptr(messaging_handle_t handle) { return (messaging_list_t*)handle; } +messaging_handle_t get_handle_ptr(messaging_list_t* handle) { return (messaging_handle_t)handle; } -RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count){ - RingbufHandle_t buf_handle = NULL; - StaticRingbuffer_t *buffer_struct = malloc_init_external(sizeof(StaticRingbuffer_t)); - if (buffer_struct != NULL) { - size_t buf_size = (size_t )(sizeof(single_message_t)+8+MSG_LENGTH_AVG)*(size_t )(max_count>0?max_count:5); // no-split buffer requires an additional 8 bytes - buf_size = buf_size - (buf_size % 4); - uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT); - if (buffer_storage== NULL) { - ESP_LOGE(tag,"buff alloc failed"); - } - else { - buf_handle = xRingbufferCreateStatic(buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct); - } - } - else { - ESP_LOGE(tag,"ringbuf alloc failed"); - } - return buf_handle; +RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count) { + RingbufHandle_t buf_handle = NULL; + StaticRingbuffer_t* buffer_struct = malloc_init_external(sizeof(StaticRingbuffer_t)); + if (buffer_struct != NULL) { + size_t buf_size = + (size_t)(sizeof(single_message_t) + 8 + MSG_LENGTH_AVG) * + (size_t)(max_count > 0 ? max_count + : 5); // no-split buffer requires an additional 8 bytes + buf_size = buf_size - (buf_size % 4); + uint8_t* buffer_storage = + (uint8_t*)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT); + if (buffer_storage == NULL) { + ESP_LOGE(tag, "buff alloc failed"); + } else { + buf_handle = xRingbufferCreateStatic( + buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct); + } + } else { + ESP_LOGE(tag, "ringbuf alloc failed"); + } + return buf_handle; } -void messaging_fill_messages(messaging_list_t * target_subscriber){ - single_message_t * message=NULL; +void messaging_fill_messages(messaging_list_t* target_subscriber) { + single_message_t* message = NULL; UBaseType_t uxItemsWaiting; - + if (!top.buf_handle) { + ESP_LOGE(tag, "Queue initialization error!"); + return; + } vRingbufferGetInfo(top.buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - for(size_t i=0;imsg_size); - // post to new subscriber - messaging_post_to_queue(get_handle_ptr(target_subscriber) , message, message->msg_size); - FREE_AND_NULL(message); - } + for (size_t i = 0; i < uxItemsWaiting; i++) { + message = messaging_retrieve_message(top.buf_handle); + if (message) { + // re-post to original queue so it is available to future subscribers + messaging_post_to_queue(get_handle_ptr(&top), message, message->msg_size); + // post to new subscriber + messaging_post_to_queue(get_handle_ptr(target_subscriber), message, message->msg_size); + FREE_AND_NULL(message); + } } } -messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name){ - messaging_list_t * cur=⊤ - while(cur->next){ - cur = get_struct_ptr(cur->next); - } - cur->next=malloc_init_external(sizeof(messaging_list_t)); - if(!cur->next){ - ESP_LOGE(tag,"subscriber alloc failed"); - return NULL; - } - memset(cur->next,0x00,sizeof(messaging_list_t)); - cur = get_struct_ptr(cur->next); - cur->max_count=max_count; - cur->subscriber_name=strdup_psram(name); - cur->buf_handle = messaging_create_ring_buffer(max_count); - if(cur->buf_handle){ - messaging_fill_messages(cur); - } - return cur->buf_handle; +messaging_handle_t messaging_register_subscriber(uint8_t max_count, char* name) { + messaging_list_t* cur = ⊤ + while (cur->next) { + cur = get_struct_ptr(cur->next); + } + cur->next = malloc_init_external(sizeof(messaging_list_t)); + if (!cur->next) { + ESP_LOGE(tag, "subscriber alloc failed"); + return NULL; + } + memset(cur->next, 0x00, sizeof(messaging_list_t)); + cur = get_struct_ptr(cur->next); + cur->max_count = max_count; + cur->subscriber_name = strdup_psram(name); + cur->buf_handle = messaging_create_ring_buffer(max_count); + if (cur->buf_handle) { + messaging_fill_messages(cur); + } + return cur->buf_handle; } -void messaging_service_init(){ - size_t max_count=15; - top.buf_handle = messaging_create_ring_buffer(max_count); - if(!top.buf_handle){ - ESP_LOGE(tag, "messaging service init failed."); - } - else { - top.max_count = max_count; - top.subscriber_name = strdup_psram("messaging"); - } - return; +void messaging_service_init() { + size_t max_count = 15; + ESP_LOGI(tag, "Setting up messaging"); + top.buf_handle = messaging_create_ring_buffer(max_count); + if (!top.buf_handle) { + ESP_LOGE(tag, "messaging service init failed."); + } else { + top.max_count = max_count; + top.subscriber_name = strdup_psram("messaging"); + } + return; } -const char * messaging_get_type_desc(messaging_types msg_type){ - switch (msg_type) { - CASE_TO_STR(MESSAGING_INFO); - CASE_TO_STR(MESSAGING_WARNING); - CASE_TO_STR(MESSAGING_ERROR); - default: - return "Unknown"; - break; - } +const char* messaging_get_type_desc(messaging_types msg_type) { + switch (msg_type) { + CASE_TO_STR(MESSAGING_INFO); + CASE_TO_STR(MESSAGING_WARNING); + CASE_TO_STR(MESSAGING_ERROR); + default: + return "Unknown"; + break; + } } -const char * messaging_get_class_desc(messaging_classes msg_class){ - switch (msg_class) { - CASE_TO_STR(MESSAGING_CLASS_OTA); - CASE_TO_STR(MESSAGING_CLASS_SYSTEM); - CASE_TO_STR(MESSAGING_CLASS_STATS); - CASE_TO_STR(MESSAGING_CLASS_CFGCMD); - CASE_TO_STR(MESSAGING_CLASS_BT); - default: - return "Unknown"; - break; - } +const char* messaging_get_class_desc(messaging_classes msg_class) { + switch (msg_class) { + CASE_TO_STR(MESSAGING_CLASS_OTA); + CASE_TO_STR(MESSAGING_CLASS_SYSTEM); + CASE_TO_STR(MESSAGING_CLASS_STATS); + CASE_TO_STR(MESSAGING_CLASS_CFGCMD); + CASE_TO_STR(MESSAGING_CLASS_BT); + default: + return "Unknown"; + break; + } } -cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){ - single_message_t * message=NULL; - cJSON * json_messages=cJSON_CreateArray(); - cJSON * json_message=NULL; - size_t item_size; +cJSON* messaging_retrieve_messages(RingbufHandle_t buf_handle) { + single_message_t* message = NULL; + cJSON* json_messages = cJSON_CreateArray(); + cJSON* json_message = NULL; + size_t item_size; UBaseType_t uxItemsWaiting; vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - for(int i = 0;imessage); - cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type)); - cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class)); - cJSON_AddNumberToObject(json_message,"sent_time",message->sent_time); - cJSON_AddNumberToObject(json_message,"current_time",esp_timer_get_time() / 1000); - cJSON_AddItemToArray(json_messages,json_message); - vRingbufferReturnItem(buf_handle, (void *)message); - } - } - return json_messages; + for (int i = 0; i < uxItemsWaiting; i++) { + message = (single_message_t*)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); + // Check received data + if (message == NULL) { + ESP_LOGE(tag, "received null ptr"); + } else { + json_message = cJSON_CreateObject(); + cJSON_AddStringToObject(json_message, "message", message->message); + cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type)); + cJSON_AddStringToObject( + json_message, "class", messaging_get_class_desc(message->msg_class)); + cJSON_AddNumberToObject(json_message, "sent_time", message->sent_time); + cJSON_AddNumberToObject(json_message, "current_time", esp_timer_get_time() / 1000); + cJSON_AddItemToArray(json_messages, json_message); + vRingbufferReturnItem(buf_handle, (void*)message); + } + } + return json_messages; } -single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle){ - single_message_t * message=NULL; - single_message_t * message_copy=NULL; - size_t item_size; +single_message_t* messaging_retrieve_message(RingbufHandle_t buf_handle) { + single_message_t* message = NULL; + single_message_t* message_copy = NULL; + size_t item_size; UBaseType_t uxItemsWaiting; vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - if(uxItemsWaiting>0){ - message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); - message_copy = clone_obj_psram(message,item_size); - vRingbufferReturnItem(buf_handle, (void *)message); - } - return message_copy; + if (uxItemsWaiting > 0) { + message = (single_message_t*)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); + message_copy = clone_obj_psram(message, item_size); + vRingbufferReturnItem(buf_handle, (void*)message); + } + return message_copy; } -esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size){ - size_t item_size=0; - messaging_list_t * subscriber=get_struct_ptr(subscriber_handle); - if(!subscriber->buf_handle){ - ESP_LOGE(tag,"post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name)); - return ESP_FAIL; - } - void * pItem=NULL; - UBaseType_t res=pdFALSE; - while(1){ - ESP_LOGD(tag,"Attempting to reserve %d bytes for %s",message_size, str_or_unknown(subscriber->subscriber_name)); - res = xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(50)); - if(res == pdTRUE && pItem){ - ESP_LOGD(tag,"Reserving complete for %s", str_or_unknown(subscriber->subscriber_name)); - memcpy(pItem,message,message_size); - xRingbufferSendComplete(subscriber->buf_handle, pItem); - break; - } - ESP_LOGD(tag,"Dropping for %s",str_or_unknown(subscriber->subscriber_name)); - single_message_t * dummy = (single_message_t *)xRingbufferReceive(subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50)); - if (dummy== NULL) { - ESP_LOGE(tag,"Dropping message failed"); - break; - } - else { - ESP_LOGD(tag,"Dropping message of %d bytes for %s",item_size, str_or_unknown(subscriber->subscriber_name)); - vRingbufferReturnItem(subscriber->buf_handle, (void *)dummy); - } - } - if (res != pdTRUE) { - ESP_LOGE(tag,"post to %s failed",str_or_unknown(subscriber->subscriber_name)); - return ESP_FAIL; - } - return ESP_OK; +esp_err_t messaging_post_to_queue( + messaging_handle_t subscriber_handle, single_message_t* message, size_t message_size) { + size_t item_size = 0; + messaging_list_t* subscriber = get_struct_ptr(subscriber_handle); + if (!subscriber->buf_handle) { + ESP_LOGE( + tag, "post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name)); + return ESP_FAIL; + } + void* pItem = NULL; + UBaseType_t res = pdFALSE; + while (1) { + ESP_LOGD(tag, "Attempting to reserve %d bytes for %s", message_size, + str_or_unknown(subscriber->subscriber_name)); + res = + xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(50)); + if (res == pdTRUE && pItem) { + ESP_LOGD(tag, "Reserving complete for %s", str_or_unknown(subscriber->subscriber_name)); + memcpy(pItem, message, message_size); + xRingbufferSendComplete(subscriber->buf_handle, pItem); + break; + } + ESP_LOGD(tag, "Dropping for %s", str_or_unknown(subscriber->subscriber_name)); + single_message_t* dummy = (single_message_t*)xRingbufferReceive( + subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50)); + if (dummy == NULL) { + ESP_LOGE(tag, "Dropping message failed"); + break; + } else { + ESP_LOGD(tag, "Dropping message of %d bytes for %s", item_size, + str_or_unknown(subscriber->subscriber_name)); + vRingbufferReturnItem(subscriber->buf_handle, (void*)dummy); + } + } + if (res != pdTRUE) { + ESP_LOGE(tag, "post to %s failed", str_or_unknown(subscriber->subscriber_name)); + return ESP_FAIL; + } + return ESP_OK; } - esp_err_t messaging_type_to_err_type(messaging_types type){ - switch (type) { - case MESSAGING_INFO: - return ESP_LOG_INFO; - break; - case MESSAGING_ERROR: - return ESP_LOG_ERROR; - break; - case MESSAGING_WARNING: - return ESP_LOG_WARN; - break; - default: - return ESP_LOG_DEBUG; - break; - } - return ESP_LOG_DEBUG; - } - -void messaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, ...){ +esp_err_t messaging_type_to_err_type(messaging_types type) { + switch (type) { + case MESSAGING_INFO: + return ESP_LOG_INFO; + break; + case MESSAGING_ERROR: + return ESP_LOG_ERROR; + break; + case MESSAGING_WARNING: + return ESP_LOG_WARN; + break; + default: + return ESP_LOG_DEBUG; + break; + } + return ESP_LOG_DEBUG; +} + +void messaging_post_message( + messaging_types type, messaging_classes msg_class, const char* fmt, ...) { va_list va; - va_start(va, fmt); + va_start(va, fmt); vmessaging_post_message(type, msg_class, fmt, va); va_end(va); } - -void vmessaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, va_list va){ - single_message_t * message=NULL; - size_t msg_size=0; - size_t ln =0; - messaging_list_t * cur=⊤ - ln = vsnprintf(NULL, 0, fmt, va)+1; - msg_size = sizeof(single_message_t)+ln; - message = (single_message_t *)malloc_init_external(msg_size); - vsprintf(message->message, fmt, va); - message->msg_size = msg_size; - message->type = type; - message->msg_class = msg_class; - message->sent_time = esp_timer_get_time() / 1000; - if(type==MESSAGING_WARNING) { - ESP_LOGW(tag,"%s",message->message); - } - else if(type==MESSAGING_ERROR) { - ESP_LOGE(tag,"%s",message->message); - } - else { - ESP_LOGD(tag,"Post: %s",message->message); - } - while(cur){ - messaging_post_to_queue(get_handle_ptr(cur), message, msg_size); - cur = get_struct_ptr(cur->next); - } - FREE_AND_NULL(message); - return; +void vmessaging_post_message( + messaging_types type, messaging_classes msg_class, const char* fmt, va_list va) { + single_message_t* message = NULL; + size_t msg_size = 0; + size_t ln = 0; + messaging_list_t* cur = ⊤ + ln = vsnprintf(NULL, 0, fmt, va) + 1; + msg_size = sizeof(single_message_t) + ln; + message = (single_message_t*)malloc_init_external(msg_size); + vsprintf(message->message, fmt, va); + message->msg_size = msg_size; + message->type = type; + message->msg_class = msg_class; + message->sent_time = esp_timer_get_time() / 1000; + if (type == MESSAGING_WARNING) { + ESP_LOGW(tag, "%s", message->message); + } else if (type == MESSAGING_ERROR) { + ESP_LOGE(tag, "%s", message->message); + } else { + ESP_LOGD(tag, "Post: %s", message->message); + } + while (cur) { + messaging_post_to_queue(get_handle_ptr(cur), message, msg_size); + cur = get_struct_ptr(cur->next); + } + FREE_AND_NULL(message); + return; } -char * messaging_alloc_format_string(const char *fmt, ...) { - va_list va; - va_start(va, fmt); - size_t ln = vsnprintf(NULL, 0, fmt, va)+1; - char * message_txt = malloc_init_external(ln); - if(message_txt){ - vsprintf(message_txt, fmt, va); - va_end(va); - } - else{ - ESP_LOGE(tag, "Memory allocation failed while sending message"); - } - return message_txt; +char* messaging_alloc_format_string(const char* fmt, ...) { + va_list va; + va_start(va, fmt); + size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; + char* message_txt = malloc_init_external(ln); + if (message_txt) { + vsprintf(message_txt, fmt, va); + va_end(va); + } else { + ESP_LOGE(tag, "Memory allocation failed while sending message"); + } + return message_txt; } -void log_send_messaging(messaging_types msgtype,const char *fmt, ...) { - va_list va; - va_start(va, fmt); - size_t ln = vsnprintf(NULL, 0, fmt, va)+1; - char * message_txt = malloc_init_external(ln); - if(message_txt){ - vsprintf(message_txt, fmt, va); - va_end(va); - ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype),tag, "%s",message_txt); - messaging_post_message(msgtype, MESSAGING_CLASS_SYSTEM, message_txt ); - free(message_txt); - } - else{ - ESP_LOGE(tag, "Memory allocation failed while sending message"); - } +void log_send_messaging(messaging_types msgtype, const char* fmt, ...) { + va_list va; + va_start(va, fmt); + size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; + char* message_txt = malloc_init_external(ln); + if (message_txt) { + vsprintf(message_txt, fmt, va); + va_end(va); + ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype), tag, "%s", message_txt); + messaging_post_message(msgtype, MESSAGING_CLASS_SYSTEM, message_txt); + free(message_txt); + } else { + ESP_LOGE(tag, "Memory allocation failed while sending message"); + } } -void cmd_send_messaging(const char * cmdname,messaging_types msgtype, const char *fmt, ...){ - va_list va; - va_start(va, fmt); - size_t cmd_len = strlen(cmdname)+1; - size_t ln = vsnprintf(NULL, 0, fmt, va)+1; - char * message_txt = malloc_init_external(ln+cmd_len); - if(message_txt){ - strcpy(message_txt,cmdname); - strcat(message_txt,"\n"); - vsprintf((message_txt+cmd_len), fmt, va); - va_end(va); - ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype),tag, "%s",message_txt); - messaging_post_message(msgtype, MESSAGING_CLASS_CFGCMD, message_txt ); - free(message_txt); - } - else{ - ESP_LOGE(tag, "Memory allocation failed while sending message"); - } +void cmd_send_messaging(const char* cmdname, messaging_types msgtype, const char* fmt, ...) { + va_list va; + va_start(va, fmt); + size_t cmd_len = strlen(cmdname) + 1; + size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; + char* message_txt = malloc_init_external(ln + cmd_len); + if (message_txt) { + strcpy(message_txt, cmdname); + strcat(message_txt, "\n"); + vsprintf((message_txt + cmd_len), fmt, va); + va_end(va); + ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype), tag, "%s", message_txt); + messaging_post_message(msgtype, MESSAGING_CLASS_CFGCMD, message_txt); + free(message_txt); + } else { + ESP_LOGE(tag, "Memory allocation failed while sending message"); + } } diff --git a/components/services/monitor.c b/components/services/monitor.c index 828166b0..d00080b5 100644 --- a/components/services/monitor.c +++ b/components/services/monitor.c @@ -5,7 +5,7 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ - +#define LOG_LOCAL_LEVEL ESP_LOG_INFO #include #include #include @@ -20,8 +20,6 @@ #include "buttons.h" #include "led.h" #include "globdefs.h" -// #include "Configurator.h" -// TODO: Add support for the commented code: search for TODO in the code below") #include "accessors.h" #include "messaging.h" #include "cJSON.h" @@ -163,7 +161,7 @@ static void jack_handler_default(void *id, button_event_e event, button_press_e * */ bool jack_inserted_svc (void) { - sys_GPIO * jack=NULL; + sys_gpio_config * jack=NULL; if(SYS_GPIOS_NAME(jack,jack)){ return button_is_pressed(jack->pin, NULL); } @@ -184,7 +182,7 @@ static void spkfault_handler_default(void *id, button_event_e event, button_pres * */ bool spkfault_svc (void) { - sys_GPIO * spkfault=NULL; + sys_gpio_config * spkfault=NULL; if(SYS_GPIOS_NAME(spkfault,spkfault)){ return button_is_pressed(spkfault->pin, NULL); } @@ -209,10 +207,10 @@ static void pseudo_idle(void *arg) { */ void monitor_svc_init(void) { ESP_LOGI(TAG, "Initializing monitoring"); - sys_Services * services = NULL; - sys_GPIO * gpio=NULL; + sys_services_config * services = NULL; + sys_gpio_config * gpio=NULL; if(SYS_GPIOS_NAME(jack,gpio) && gpio->pin>=0){ - ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", gpio->level ? "high" : "low", gpio->pin); + ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", sys_gpio_lvl_name(gpio->level), gpio->pin); button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1); } if(SYS_GPIOS_NAME(spkfault,gpio) && gpio->pin>=0){ @@ -220,7 +218,7 @@ void monitor_svc_init(void) { button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1); } // do we want stats - monitor_stats = SYS_SERVICES(services) && services->statistics; + monitor_stats = sys_services_config(services) && services->statistics; ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), diff --git a/components/services/monitor.h b/components/services/monitor.h index 427fce92..fb057410 100644 --- a/components/services/monitor.h +++ b/components/services/monitor.h @@ -1,4 +1,4 @@ -/* +/* * Squeezelite for esp32 * * (c) Philippe G. 2019, philippe_44@outlook.com @@ -7,8 +7,11 @@ * https://opensource.org/licenses/MIT * */ - + #pragma once +#ifdef __cplusplus +extern "C" { +#endif extern void (*pseudo_idle_svc)(uint32_t now); extern void (*jack_handler_svc)(bool inserted); @@ -20,3 +23,6 @@ extern bool spkfault_svc(void); extern void (*battery_handler_svc)(float value, int cells); extern float battery_value_svc(void); extern uint16_t battery_level_svc(void); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/services/services.c b/components/services/services.c index 871381e1..6067b445 100644 --- a/components/services/services.c +++ b/components/services/services.c @@ -5,44 +5,46 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ - -#include #include "freertos/FreeRTOS.h" #include "freertos/timers.h" +#include +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "Config.h" +#include "accessors.h" +#include "battery.h" +#include "buttons.h" +#include "driver/i2c.h" +#include "driver/ledc.h" +#include "driver/rmt.h" +#include "driver/rtc_io.h" #include "esp_log.h" #include "esp_sleep.h" -#include "driver/rtc_io.h" -#include "driver/ledc.h" -#include "driver/i2c.h" -#include "driver/rmt.h" -#include "Configurator.h" -#include "gpio_exp.h" -#include "battery.h" -#include "led.h" -#include "monitor.h" #include "globdefs.h" -#include "accessors.h" +#include "gpio_exp.h" +#include "led.h" #include "messaging.h" -#include "buttons.h" +#include "monitor.h" #include "services.h" +#include "tools.h" extern void battery_svc_init(void); extern void monitor_svc_init(void); extern void led_svc_init(void); -int i2c_system_port = I2C_SYSTEM_PORT; -int i2c_system_speed = 400000; int spi_system_host = SPI_SYSTEM_HOST; int spi_system_dc_gpio = -1; int rmt_system_base_tx_channel = RMT_CHANNEL_0; -int rmt_system_base_rx_channel = RMT_CHANNEL_MAX-1; +int rmt_system_base_rx_channel = RMT_CHANNEL_MAX - 1; pwm_system_t pwm_system = { - .timer = LEDC_TIMER_0, - .base_channel = LEDC_CHANNEL_0, - .max = (1 << LEDC_TIMER_13_BIT), + .timer = LEDC_TIMER_0, + .base_channel = LEDC_CHANNEL_0, + .max = (1 << LEDC_TIMER_13_BIT), }; -static sys_SleepService * sleep_config; +static sys_sleep_config* sleep_config; +static EXT_RAM_ATTR uint8_t gpio_exp_count = 0; +static EXT_RAM_ATTR bool spi_configured = false; +static EXT_RAM_ATTR bool i2c_configured = false; static EXT_RAM_ATTR struct { uint64_t wake_gpio, wake_level; uint64_t rtc_gpio, rtc_level; @@ -55,31 +57,93 @@ static EXT_RAM_ATTR struct { uint32_t (*sleeper[10])(void); } sleep_context; -static const char *TAG = "services"; +static const char* TAG = "services"; -void set_gpio_level(sys_GPIO*gpio,const char * name, gpio_mode_t mode){ +bool are_GPIOExp_equal(const sys_exp_config* exp1, const sys_exp_config* exp2) { + if (exp1 == NULL || exp2 == NULL) { + return false; // Safeguard against NULL pointers + } + + // Check if model, address, and base are the same + if (exp1->model != exp2->model || exp1->addr != exp2->addr || exp1->base != exp2->base) { + return false; + } + + // Check if intr structure (pin and level) are the same + if (exp1->intr != exp2->intr) { + return false; + } + + return true; +} + +bool sys_dev_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const pb_field_iter_t* field) { + ESP_LOGV(TAG, "Decoding/Encoding Devices, tag: %d", field->tag); + sys_exp_config** pExp = (sys_exp_config**)field->pData; + sys_exp_config* exp = NULL; + + if (istream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { + ESP_LOGD(TAG, "Decoding GPIO Expander #%d", gpio_exp_count + 1); + sys_exp_config entry = sys_exp_config_init_default; + if (!pb_decode(istream, &sys_exp_config_msg, &entry)) { + return false; + } + if (entry.model == sys_exp_models_UNSPECIFIED_EXP) { + ESP_LOGD(TAG, "Skipping GPIO Expander model %s", sys_exp_models_name(entry.model)); + return true; + } + // Don't add the expander if it was already decoded. This could + // happen if both the configuration and the platform configuration + // contain the definition. + for (int i = 0; i < gpio_exp_count; i++) { + if (are_GPIOExp_equal(&(*pExp)[i], &entry)) { + ESP_LOGW(TAG, "GPIO Expander entry already exists, skipping addition."); + return true; // Skip adding as it already exists + } + } + + gpio_exp_count++; + + *pExp = heap_caps_realloc(*pExp, sizeof(sys_exp_config) * gpio_exp_count, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + // Assert after realloc to ensure memory allocation was successful + assert(*pExp != NULL); + exp = (*pExp) + gpio_exp_count - 1; // Simplified pointer arithmetic + memcpy(exp, &entry, sizeof(entry)); + ESP_LOGD(TAG, "GPIO Expander #%d model %s", gpio_exp_count, sys_exp_models_name(entry.model)); + + } else if (ostream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { + ESP_LOGV(TAG, "Encoding %d GPIO Expanders", gpio_exp_count); + + for (int i = 0; i < gpio_exp_count; i++) { + if (!pb_encode_tag_for_field(ostream, field)) { + return false; + } + if (!pb_encode_submessage(ostream, &sys_exp_config_msg, &(*pExp)[i])) { + return false; + } + } + ESP_LOGV(TAG, "GPIO Expander encoding completed"); + } + + return true; +} + +void set_gpio_level(sys_gpio_config* gpio, const char* name, gpio_mode_t mode) { + ESP_LOGI(TAG, "set GPIO %u to %s, level %d", gpio->pin, name, gpio->level); + if (gpio->pin < 0) { + ESP_LOGW(TAG, "Invalid gpio %d for %s", gpio->pin, name); + return; + } gpio_pad_select_gpio(gpio->pin); gpio_set_direction(gpio->pin, mode); - gpio_set_level(gpio->pin, gpio->level); - ESP_LOGI(TAG, "set GPIO %u to %s, level %d", gpio->pin,name, gpio->level); -} -void set_chip_power_gpio(sys_Gpios*gpios) { - - if(gpios->has_power){ - gpios->power.level = 1; - set_gpio_level(&gpios->power,"vcc", GPIO_MODE_OUTPUT); - } - if(gpios->has_GND){ - gpios->GND.level = 0; - set_gpio_level(&gpios->GND,"gnd", GPIO_MODE_OUTPUT); - } - + gpio_set_level(gpio->pin, gpio->level); } /**************************************************************************************** * */ -static void sleep_gpio_handler(void *id, button_event_e event, button_press_e mode, bool long_press) { +static void sleep_gpio_handler(void* id, button_event_e event, button_press_e mode, bool long_press) { if (event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO); } @@ -96,7 +160,7 @@ static void sleep_timer(uint32_t now) { if (!first) first = now; // only query callbacks every 30s if we have at least one sleeper - if (!*sleep_context.sleeper || now < last + 30*1000) return; + if (!*sleep_context.sleeper || now < last + 30 * 1000) return; last = now; // time to evaluate if we had spurious wake-up @@ -151,12 +215,13 @@ static void sleep_battery(float level, int cells) { * */ void services_sleep_init(void) { - ESP_LOGD(TAG,"Initializing sleep services"); - if(!SYS_SERVICES_SLEEP(sleep_config)){ - ESP_LOGD(TAG,"No sleep service configured") ; + ESP_LOGD(TAG, "Initializing sleep services"); + if (!sys_services_config_SLEEP(sleep_config)) { + ESP_LOGD(TAG, "No sleep service configured"); + return; } // get the wake criteria - for(int i=0;iwake_count;i++){ + for (int i = 0; i < sleep_config->wake_count; i++) { if (!rtc_gpio_is_valid_gpio(sleep_config->wake[i].pin)) { ESP_LOGE(TAG, "invalid wake GPIO %d (not in RTC domain)", sleep_config->wake[i].pin); } else { @@ -165,7 +230,8 @@ void services_sleep_init(void) { sleep_context.wake_level |= sleep_config->wake[i].level << sleep_config->wake[i].pin; } } - // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done + // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can + // be done if (sleep_context.wake_gpio) { ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level); } @@ -177,7 +243,7 @@ void services_sleep_init(void) { battery_handler_svc = sleep_battery; ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level); } - for(int i = 0;irtc_count;i++){ + for (int i = 0; i < sleep_config->rtc_count; i++) { if (!rtc_gpio_is_valid_gpio(sleep_config->rtc[i].pin)) { ESP_LOGE(TAG, "invalid rtc GPIO %d", sleep_config->rtc[i].pin); } else { @@ -185,20 +251,21 @@ void services_sleep_init(void) { sleep_context.rtc_level |= sleep_config->rtc[i].level << sleep_config->rtc[i].pin; } } - // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can be done + // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can + // be done if (sleep_context.rtc_gpio) { ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level); } // get the GPIOs that activate sleep (we could check that we have a valid wake) - if(sleep_config->has_sleep && sleep_config->sleep.pin >=0 ){ - ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", sleep_config->sleep.pin, sleep_config->sleep.level); + if (sleep_config->has_sleep && sleep_config->sleep.pin >= 0) { + ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", sleep_config->sleep.pin, sleep_config->sleep.level); button_create(NULL, sleep_config->sleep.pin, sleep_config->sleep.level ? BUTTON_HIGH : BUTTON_LOW, true, 0, sleep_gpio_handler, 0, -1); } // do we want delay sleep - - sleep_context.delay = sleep_config->delay*60*1000; + + sleep_context.delay = sleep_config->delay * 60 * 1000; // now check why we woke-up esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); @@ -207,17 +274,19 @@ void services_sleep_init(void) { // find the type of wake-up uint64_t wake_gpio; - if (cause == ESP_SLEEP_WAKEUP_EXT0) wake_gpio = sleep_context.wake_gpio; - else wake_gpio = esp_sleep_get_ext1_wakeup_status(); + if (cause == ESP_SLEEP_WAKEUP_EXT0) + wake_gpio = sleep_context.wake_gpio; + else + wake_gpio = esp_sleep_get_ext1_wakeup_status(); // we might be woken up by infrared in which case we want a short sleep if (infrared_gpio() >= 0 && ((1LL << infrared_gpio()) & wake_gpio)) { sleep_context.spurious = 1; - if(sleep_config->spurious>0){ + if (sleep_config->spurious > 0) { sleep_context.spurious = sleep_config->spurious; } - sleep_context.spurious *= 60*1000; - + sleep_context.spurious *= 60 * 1000; + ESP_LOGI(TAG, "spurious wake-up detection during %d sec", sleep_context.spurious / 1000); } } @@ -226,7 +295,7 @@ void services_sleep_init(void) { if (sleep_context.delay || sleep_context.spurious) { sleep_context.idle_chain = pseudo_idle_svc; pseudo_idle_svc = sleep_timer; - if (sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60*1000)); + if (sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60 * 1000)); } } @@ -235,7 +304,8 @@ void services_sleep_init(void) { */ void services_sleep_activate(sleep_cause_e cause) { // call all sleep hooks that might want to do something - for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) (*suspend)(); + for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) + (*suspend)(); // isolate all possible GPIOs, except the wake-up and RTC-maintaines ones esp_sleep_config_gpio_isolate(); @@ -249,9 +319,11 @@ void services_sleep_activate(sleep_cause_e cause) { // do we need to maintain a pull-up or down of that GPIO if ((1LL << i) & sleep_context.rtc_gpio) { - if ((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i); - else rtc_gpio_pulldown_en(i); - // or is this not wake-up GPIO, just isolate it + if ((sleep_context.rtc_level >> i) & 0x01) + rtc_gpio_pullup_en(i); + else + rtc_gpio_pulldown_en(i); + // or is this not wake-up GPIO, just isolate it } else if (!((1LL << i) & sleep_context.wake_gpio)) { rtc_gpio_isolate(i); } @@ -261,10 +333,11 @@ void services_sleep_activate(sleep_cause_e cause) { if (sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) { ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_context.wake_gpio); #if defined(CONFIG_IDF_TARGET_ESP32S3) && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) - if (!sleep_context.wake_level) esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_LOW); + if (!sleep_context.wake_level) + esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_LOW); else #endif - esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH); + esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH); } else if (sleep_context.wake_gpio) { int gpio = __builtin_ctzll(sleep_context.wake_gpio); int level = (sleep_context.wake_level >> gpio) & 0x01; @@ -274,136 +347,186 @@ void services_sleep_activate(sleep_cause_e cause) { ESP_LOGW(TAG, "going to sleep cause %d, no wake-up option", cause); } - // we need to use a timer in case the same button is used for sleep and wake-up and it's "pressed" vs "released" selected - if (cause == SLEEP_ONKEY) xTimerStart(xTimerCreate("sleepTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, (void (*)(void*)) esp_deep_sleep_start), 0); - else esp_deep_sleep_start(); + // we need to use a timer in case the same button is used for sleep and wake-up and it's + // "pressed" vs "released" selected + if (cause == SLEEP_ONKEY) + xTimerStart(xTimerCreate("sleepTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, (void (*)(void*))esp_deep_sleep_start), 0); + else + esp_deep_sleep_start(); } - /**************************************************************************************** * */ -static void register_method(void **store, size_t size, void *method) { - for (int i = 0; i < size; i++, *store++) if (!*store) { - *store = method; - return; - } +static void register_method(void** store, size_t size, void* method) { + for (int i = 0; i < size; i++, *store++) + if (!*store) { + *store = method; + return; + } } /**************************************************************************************** * */ void services_sleep_setsuspend(void (*hook)(void)) { - register_method((void**) sleep_context.suspend, sizeof(sleep_context.suspend)/sizeof(*sleep_context.suspend), (void*) hook); + register_method((void**)sleep_context.suspend, sizeof(sleep_context.suspend) / sizeof(*sleep_context.suspend), (void*)hook); } /**************************************************************************************** * */ void services_sleep_setsleeper(uint32_t (*sleeper)(void)) { - register_method((void**) sleep_context.sleeper, sizeof(sleep_context.sleeper)/sizeof(*sleep_context.sleeper), (void*) sleeper); + register_method((void**)sleep_context.sleeper, sizeof(sleep_context.sleeper) / sizeof(*sleep_context.sleeper), (void*)sleeper); } +void services_ports_init(void) { + esp_err_t err = ESP_OK; + ESP_LOGI(TAG, "Initializing ports"); + gpio_install_isr_service(0); + ESP_LOGD(TAG, "Checking i2c port usage"); + if (platform->dev.dac.has_i2c && platform->dev.has_i2c && platform->dev.dac.i2c.port != sys_i2c_port_UNSPECIFIED && + platform->dev.dac.i2c.port == platform->dev.i2c.port) { + ESP_LOGE(TAG, "Port %s is used for internal DAC use. Switching to ", sys_i2c_port_name(platform->dev.dac.i2c.port)); + platform->dev.i2c.port = platform->dev.i2c.port == sys_i2c_port_PORT0 ? sys_i2c_port_PORT1 : sys_i2c_port_PORT0; + config_raise_changed(false); + } + + // shared I2C bus + ESP_LOGD(TAG, "Configuring I2C"); + const i2c_config_t* i2c_config = config_i2c_get(&platform->dev.i2c); + ESP_LOGD(TAG, "Stored I2C configuration [sda:%d scl:%d port:%s speed:%u]", i2c_config->sda_io_num, i2c_config->scl_io_num, + sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed); + if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) { + ESP_LOGI(TAG, "Configuring I2C sda:%d scl:%d port:%s speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, + sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed); + i2c_param_config(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config); + if ((err = i2c_driver_install(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config->mode, 0, 0, 0)) != ESP_OK) { + ESP_LOGE(TAG, "Error setting up i2c: %s", esp_err_to_name(err)); + } else { + i2c_configured = true; + } + } else { + if (platform->dev.has_display && platform->dev.display.has_common && platform->dev.display.which_dispType == sys_display_config_i2c_tag) { + ESP_LOGE(TAG, "I2C configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver)); + } else { + ESP_LOGI(TAG, "Shared I2C not configured"); + } + } + + const spi_bus_config_t* spi_config = config_spi_get((spi_host_device_t*)&spi_system_host); + ESP_LOGD(TAG, "Stored SPI configuration[mosi:%d miso:%d clk:%d host:%u dc:%d]", spi_config->mosi_io_num, spi_config->miso_io_num, + spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio); + if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) { + ESP_LOGI(TAG, "Configuring SPI mosi:%d miso:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->miso_io_num, + spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio); + if ((err = spi_bus_initialize(spi_system_host, spi_config, SPI_DMA_CH_AUTO)) != ESP_OK) { + ESP_LOGE(TAG, "Error setting up SPI bus: %s", esp_err_to_name(err)); + } else { + spi_configured = true; + } + if (spi_system_dc_gpio != -1) { + gpio_reset_pin(spi_system_dc_gpio); + gpio_set_direction(spi_system_dc_gpio, GPIO_MODE_OUTPUT); + gpio_set_level(spi_system_dc_gpio, 0); + } else { + ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work"); + } + } else { + spi_system_host = -1; + if (platform->dev.has_display && platform->dev.display.has_common && + platform->dev.display.common.driver != sys_display_drivers_UNSPECIFIED && + platform->dev.display.which_dispType == sys_display_config_spi_tag) { + ESP_LOGE(TAG, "SPI bus configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver)); + } else { + ESP_LOGI(TAG, "SPI bus not configured"); + } + } +} +void services_gpio_init(void) { + ESP_LOGI(TAG, "Initializing GPIOs"); + // set potential power GPIO on chip first in case expanders are power using these + sys_gpio_config* gpio = NULL; + if (SYS_GPIOS_NAME(power, gpio) && gpio->pin >= 0) { + ESP_LOGD(TAG, "Handling power gpio"); + gpio->level = sys_gpio_lvl_HIGH; + set_gpio_level(gpio, "power", GPIO_MODE_OUTPUT); + } else { + ESP_LOGD(TAG, "No power GPIO defined"); + } + + if (SYS_GPIOS_NAME(GND, gpio) && gpio->pin >= 0) { + ESP_LOGD(TAG, "Handling GND gpio"); + gpio->level = sys_gpio_lvl_LOW; + set_gpio_level(gpio, "GND", GPIO_MODE_OUTPUT); + } else { + ESP_LOGD(TAG, "No GND gpio defined"); + } + + // create GPIO expanders + gpio_exp_config_t gpio_exp_config; + if (platform->has_dev && gpio_exp_count > 0 && platform->dev.gpio_exp[0].model != sys_exp_models_UNSPECIFIED_EXP) { + ESP_LOGI(TAG, "Initializing %d GPIO Expander(s)", gpio_exp_count); + for (int count = 0; count < gpio_exp_count; count++) { + sys_exp_config* exp = &platform->dev.gpio_exp[count]; + if (exp->model == sys_exp_models_UNSPECIFIED_EXP) { + ESP_LOGD(TAG, "Skipping unknown model"); + continue; + } + gpio_exp_config.phy.ena_pin = -1; + gpio_exp_config.base = exp->base; + gpio_exp_config.count = exp->count; + gpio_exp_config.phy.addr = exp->addr; + gpio_exp_config.intr = exp->intr; + if (exp->has_ena && exp->ena.pin >= 0) { + gpio_exp_config.phy.ena_pin = exp->ena.pin; + gpio_exp_config.phy.ena_lvl = exp->ena.level; + } + if (exp->which_ExpType == sys_exp_config_spi_tag) { + if (!spi_configured) { + ESP_LOGE(TAG, "SPI bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model)); + continue; + } + gpio_exp_config.phy.cs_pin = exp->ExpType.spi.cs; + gpio_exp_config.phy.host = + (!platform->dev.has_spi || (platform->dev.has_spi && platform->dev.spi.host == sys_dev_common_hosts_NONE) ? sys_dev_common_hosts_Host0 : platform->dev.spi.host) - sys_dev_common_hosts_Host0; + gpio_exp_config.phy.speed = exp->ExpType.spi.speed > 0 ? exp->ExpType.spi.speed : 0; + } else { + if (!i2c_configured) { + ESP_LOGE(TAG, "I2C bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model)); + continue; + } + gpio_exp_config.phy.port = + ((!platform->dev.has_i2c || (platform->dev.has_i2c && platform->dev.i2c.port == sys_i2c_port_UNSPECIFIED) )? sys_dev_common_ports_SYSTEM : platform->dev.i2c.port) - sys_dev_common_ports_SYSTEM ; + } + strncpy(gpio_exp_config.model, sys_exp_models_name(exp->model), sizeof(gpio_exp_config.model) - 1); + gpio_exp_create(&gpio_exp_config); + } + } else if (gpio_exp_count > 0) { + ESP_LOGW(TAG, "GPIO Expander count %d but none is valid", gpio_exp_count); + } +} /**************************************************************************************** * */ void services_init(void) { - messaging_service_init(); - gpio_install_isr_service(0); - // todo: untangle i2c stuff -#ifdef CONFIG_I2C_LOCKED - if (i2c_system_port == 0) { - i2c_system_port = 1; - ESP_LOGE(TAG, "Port 0 is reserved for internal DAC use"); - } -#endif + ESP_LOGI(TAG, "Initializing services"); + esp_err_t err = ESP_OK; - // set potential power GPIO on chip first in case expanders are power using these - set_chip_power_gpio(&platform->gpios); - - // shared I2C bus - const i2c_config_t * i2c_config = config_i2c_get(&i2c_system_port); - ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, i2c_system_port, i2c_config->master.clk_speed); - - if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) { - i2c_param_config(i2c_system_port, i2c_config); - i2c_driver_install(i2c_system_port, i2c_config->mode, 0, 0, 0 ); - } else { - i2c_system_port = -1; - ESP_LOGW(TAG, "no I2C configured"); - } - - const spi_bus_config_t * spi_config = config_spi_get((spi_host_device_t*) &spi_system_host); - ESP_LOGI(TAG,"Configuring SPI mosi:%d miso:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->miso_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio); - - if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) { - spi_bus_initialize( spi_system_host, spi_config, SPI_DMA_CH_AUTO ); - if (spi_system_dc_gpio != -1) { - gpio_reset_pin(spi_system_dc_gpio); - gpio_set_direction( spi_system_dc_gpio, GPIO_MODE_OUTPUT ); - gpio_set_level( spi_system_dc_gpio, 0 ); - } else { - ESP_LOGW(TAG, "No DC GPIO set, SPI display will not work"); - } - } else { - spi_system_host = -1; - ESP_LOGW(TAG, "no SPI configured"); - } - - // create GPIO expanders - gpio_exp_config_t gpio_exp_config; - if(platform->has_dev && platform->dev.gpio_exp_count>0){ - for(int count = 0;countdev.gpio_exp_count;count++){ - sys_GPIOExp * exp = &platform->dev.gpio_exp[count]; - gpio_exp_config.base = exp->base; - gpio_exp_config.count = exp->count; - gpio_exp_config.phy.addr = exp->addr; - if(exp->has_intr){ - gpio_exp_config.intr = exp->intr.pin; - } - else { - ESP_LOGW(TAG,"Expander doesn't have intr pin"); - } - if(exp->which_ExpType == sys_GPIOExp_spi_tag){ - gpio_exp_config.phy.cs_pin= exp->ExpType.spi.cs.pin; - gpio_exp_config.phy.host = exp->ExpType.spi.host == sys_HostEnum_UNSPECIFIED_HOST ?sys_HostEnum_Host0:exp->ExpType.spi.host -1; - gpio_exp_config.phy.speed = exp->ExpType.spi.speed>0?exp->ExpType.spi.speed:0; - } - else { - gpio_exp_config.phy.port = exp->ExpType.i2c.port == sys_PortEnum_UNSPECIFIED_SYSTPORT?sys_PortEnum_SYSTEM:exp->ExpType.i2c.port -1; - } - strncpy(gpio_exp_config.model,sys_GPIOExpModelEnum_name(exp->model),sizeof(gpio_exp_config.model)-1); - gpio_exp_create(&gpio_exp_config); - } - } - if(platform->has_gpios ){ - // if(platform->gpios.has_GND){ - // platform->gpios.GND.level = 0; - // set_gpio_level(&platform->gpios.GND,"GND", GPIO_MODE_OUTPUT); - // } - // if(platform->gpios.has_Vcc){ - // platform->gpios.Vcc.level = 1; - // set_gpio_level(&platform->gpios.Vcc,"VCC", GPIO_MODE_OUTPUT); - // } - set_chip_power_gpio(&platform->gpios); - } - - - // system-wide PWM timer configuration - ledc_timer_config_t pwm_timer = { - .duty_resolution = LEDC_TIMER_13_BIT, - .freq_hz = 5000, + // system-wide PWM timer configuration + ledc_timer_config_t pwm_timer = { + .duty_resolution = LEDC_TIMER_13_BIT, + .freq_hz = 5000, #ifdef CONFIG_IDF_TARGET_ESP32S3 .speed_mode = LEDC_LOW_SPEED_MODE, #else - .speed_mode = LEDC_HIGH_SPEED_MODE, + .speed_mode = LEDC_HIGH_SPEED_MODE, #endif - .timer_num = pwm_system.timer, - }; + .timer_num = pwm_system.timer, + }; - ledc_timer_config(&pwm_timer); - - led_svc_init(); - battery_svc_init(); - monitor_svc_init(); + ledc_timer_config(&pwm_timer); + led_svc_init(); + battery_svc_init(); + monitor_svc_init(); } diff --git a/components/services/services.h b/components/services/services.h index 048edca8..b91ac3b3 100644 --- a/components/services/services.h +++ b/components/services/services.h @@ -7,7 +7,7 @@ * https://opensource.org/licenses/MIT * */ -#include "Configurator.h" +#include "Config.h" #include "driver/gpio.h" #pragma once @@ -17,4 +17,4 @@ void services_sleep_activate(sleep_cause_e cause); void services_sleep_setsuspend(void (*hook)(void)); void services_sleep_setsleeper(uint32_t (*sleeper)(void)); void services_sleep_init(void); -void set_gpio_level(sys_GPIO*gpio,const char * name, gpio_mode_t mode); +void set_gpio_level(sys_gpio_config*gpio,const char * name, gpio_mode_t mode); diff --git a/components/services/system_time.c b/components/services/system_time.c new file mode 100644 index 00000000..a04e857c --- /dev/null +++ b/components/services/system_time.c @@ -0,0 +1,44 @@ +/* LwIP SNTP example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "Config.h" +#include "esp_attr.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_sleep.h" +#include "esp_sntp.h" +#include "esp_system.h" +#include "tools.h" +#include +#include +#include +static const char* TAG = "system_time"; + +void system_time_init(void) { + char strftime_buf[64]; + time_t now; + struct tm timeinfo; + const char* timezone = + platform->has_services && platform->services.timezone && strlen(platform->services.timezone) > 0 ? platform->services.timezone : "EST5EDT,M3.2.0/2,M11.1.0"; + setenv("TZ", timezone, 1); + tzset(); + time(&now); + localtime_r(&now, &timeinfo); + // Is time set? If not, tm_year will be (1970 - 1900). + if (timeinfo.tm_year < (2016 - 1900)) { + ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP."); + sntp_servermode_dhcp(2); + esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL); + esp_sntp_setservername(0, "pool.ntp.org"); + esp_sntp_init(); + + } else { + strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); + ESP_LOGI(TAG, "Current date/time is: %s for time zone %s", strftime_buf, timezone); + } +} diff --git a/components/services/system_time.h b/components/services/system_time.h new file mode 100644 index 00000000..946514af --- /dev/null +++ b/components/services/system_time.h @@ -0,0 +1,2 @@ +#pragma once; +void system_time_init(void); \ No newline at end of file diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 625f2a73..81d7640a 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -29,9 +28,11 @@ #include "esp_http_server.h" #include "cspot_private.h" #include "cspot_sink.h" -#include "Configurator.h" +#include "Config.h" #include "tools.h" #include "accessors.h" +#include "tools_http_utils.h" + static class cspotPlayer *player; static const struct { @@ -69,7 +70,7 @@ private: void enableZeroConf(void); void runTask(); - sys_Spotify * cspot_config = NULL; + sys_spotify_config * cspot_config = NULL; public: typedef enum {TRACK_INIT, TRACK_NOTIFY, TRACK_STREAM, TRACK_END} TrackStatus; @@ -86,7 +87,7 @@ cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspo serverHandle(server), serverPort(port), cmdHandler(cmdHandler), dataHandler(dataHandler) { - if(!SYS_SERVICES_SPOTIFY(cspot_config)){ + if(!sys_services_config_SPOTIFY(cspot_config)){ return; } volume = cspot_config->volume; @@ -360,8 +361,8 @@ void cspotPlayer::runTask() { // we might have been forced to use zeroConf, so store credentials and reset zeroConf usage if (!zeroConf) { useZeroConf = false; - if(configurator_set_string(&sys_State_msg,sys_State_cspot_credentials_tag,sys_state,credentials.c_str())){ - configurator.RaiseStateModified(); + if(system_set_string(&sys_state_data_msg,sys_state_data_cspot_credentials_tag,sys_state,credentials.c_str())){ + config_raise_state_changed(); } } @@ -416,7 +417,7 @@ void cspotPlayer::runTask() { if (state == DISCO) { // update volume then cspot_config->volume = volume; - configurator_raise_changed(); + config_raise_changed(false); // in ZeroConf mod, stay connected (in this loop) if (!zeroConf) state = LINKED; } diff --git a/components/spotify/cspot/bell/external/nanopb/generator/nanopb_generator.py b/components/spotify/cspot/bell/external/nanopb/generator/nanopb_generator.py index e40f18b6..e609f65f 100644 --- a/components/spotify/cspot/bell/external/nanopb/generator/nanopb_generator.py +++ b/components/spotify/cspot/bell/external/nanopb/generator/nanopb_generator.py @@ -1754,6 +1754,9 @@ class ProtoFile: for extension in self.extensions: yield extension.extension_decl() yield '\n' + yield '#ifdef __cplusplus\n' + yield 'extern "C" {\n' + yield '#endif\n\n' if self.enums: yield '/* Helper constants for enums */\n' @@ -1761,9 +1764,6 @@ class ProtoFile: yield enum.auxiliary_defines() + '\n' yield '\n' - yield '#ifdef __cplusplus\n' - yield 'extern "C" {\n' - yield '#endif\n\n' if self.messages: yield '/* Initializer values for message structs */\n' diff --git a/components/spotify/cspot/bell/external/nanopb/pb_decode.c b/components/spotify/cspot/bell/external/nanopb/pb_decode.c index d69be7f7..29cf3179 100644 --- a/components/spotify/cspot/bell/external/nanopb/pb_decode.c +++ b/components/spotify/cspot/bell/external/nanopb/pb_decode.c @@ -17,6 +17,24 @@ #include "pb_decode.h" #include "pb_common.h" #include +#include // Include this header for PRIu64 + + +// Macros for debugging encode/decode +// #define DUMP_PB_ENABLE 1 +#ifdef DUMP_PB_ENABLE +#define DUMP_PB_FIELD(iter,msg) dump_pb_field(iter,msg, __FUNCTION__, __LINE__) +#define DUMP_PB_HEAD(iter,msg) dump_pb_head(iter,msg, __FUNCTION__, __LINE__) +#define DUMP_PB_MARK(msg) printf("MRK\t%-30s\t%-20s\t%-5d\n",msg, __FUNCTION__, __LINE__) +#define WRITE_DEBUG_HEADER() write_debug_header() +#else +#define DUMP_PB_FIELD(iter,msg) +#define DUMP_PB_HEAD(iter,msg) +#define DUMP_PB_MARK(msg) +#define WRITE_DEBUG_HEADER() +#endif + + /************************************** * Declarations internal to this file * **************************************/ @@ -122,13 +140,13 @@ void dump_pb_field(const pb_field_iter_t* iter, const char* msg, const char* fun "| %-20s" "| %-20s" "| %-20s" - "| %-10zu|\n", + "| %-10zu| %-20zu|\n", "FLD", msg, func, line, "","","", iter->submessage_index,iter->index, iter->field_info_index, iter->required_field_index, iter->tag, iter->data_size, iter->array_size, pb_ltype_description(iter->type), pb_htype_description(iter->type), pb_atype_description(iter->type), - iter->type); + iter->type,PB_LTYPE(iter->type)==PB_LTYPE_STRING && iter->pData && strlen(iter->pData)>0?iter->pData:""); } void dump_pb_head(const pb_msgdesc_t* desc, const char* msg, const char* func, int line) { if (!desc) { @@ -160,18 +178,7 @@ void dump_pb_head(const pb_msgdesc_t* desc, const char* msg, const char* func, i ""); } -// Macros for convenience -#ifdef DUMP_PB_ENABLE -#define DUMP_PB_FIELD(iter,msg) dump_pb_field(iter,msg, __FUNCTION__, __LINE__) -#define DUMP_PB_HEAD(iter,msg) dump_pb_head(iter,msg, __FUNCTION__, __LINE__) -#define DUMP_PB_MARK(msg) printf("MRK\t%-30s\t%-20s\t%-5d\n",msg, __FUNCTION__, __LINE__) -#define WRITE_DEBUG_HEADER write_debug_header() -#else -#define DUMP_PB_FIELD(iter,msg) -#define DUMP_PB_HEAD(iter,msg) -#define DUMP_PB_MARK(msg) -#define WRITE_DEBUG_HEADER() -#endif + static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); @@ -1282,7 +1289,7 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { - DUMP_PB_FIELD("Mark field as seen",&iter); + DUMP_PB_FIELD(&iter,"Mark field as seen"); uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); fields_seen.bitfield[iter.required_field_index >> 5] |= tmp; } @@ -1595,6 +1602,7 @@ static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t return pb_decode_bool(stream, (bool*)field->pData); } + static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field) { if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) @@ -1615,8 +1623,11 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_ else PB_RETURN_ERROR(stream, "invalid data_size"); - if (clamped != value) - PB_RETURN_ERROR(stream, "integer too large"); +if (clamped != value) { + printf("Clamped value: %" PRIu64 ", Original value: %" PRIu64 "\n", clamped, value); + PB_RETURN_ERROR(stream, "integer too large"); +} + return true; } @@ -1660,8 +1671,10 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_ else PB_RETURN_ERROR(stream, "invalid data_size"); - if (clamped != svalue) + if (clamped != svalue){ + printf("Clamped value: %" PRIi64 ", Original value: %" PRIi64 "\n", clamped, svalue); PB_RETURN_ERROR(stream, "integer too large"); + } return true; } @@ -1749,12 +1762,11 @@ static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_ if (!pb_read(stream, dest, (size_t)size)) return false; - #ifdef PB_VALIDATE_UTF8 if (!pb_validate_utf8((const char*)dest)) PB_RETURN_ERROR(stream, "invalid utf8"); #endif - + DUMP_PB_FIELD(field,"String"); return true; } diff --git a/components/spotify/cspot_sink.c b/components/spotify/cspot_sink.c index 5876fbfe..791d0cd5 100644 --- a/components/spotify/cspot_sink.c +++ b/components/spotify/cspot_sink.c @@ -6,7 +6,7 @@ #include "esp_console.h" #include "esp_pthread.h" #include "esp_system.h" -#include "Configurator.h" +#include "Config.h" #include "audio_controls.h" #include "display.h" #include "accessors.h" @@ -15,6 +15,7 @@ #include "tools.h" #include "cspot_private.h" #include "cspot_sink.h" +#include "tools_http_utils.h" char EXT_RAM_ATTR deviceId[16]; diff --git a/components/squeezelite-ota/component.mk b/components/squeezelite-ota/component.mk deleted file mode 100644 index d0d6918e..00000000 --- a/components/squeezelite-ota/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) - -# todo: add support for https -COMPONENT_ADD_INCLUDEDIRS := . -CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO -DCONFIG_OTA_ALLOW_HTTP=1 - - diff --git a/components/squeezelite-ota/github.pem b/components/squeezelite-ota/github.pem deleted file mode 100644 index c26fea0b..00000000 --- a/components/squeezelite-ota/github.pem +++ /dev/null @@ -1,41 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1 -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVk -IFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEy -MDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB -BAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQF -Ewc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG -A1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYD -VQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -xjyq8jyXDDrBTyitcnB90865tWBzpHSbindG/XqYQkzFMBlXmqkzC+FdTRBYyneZ -w5Pz+XWQvL+74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj -/4x+ogEG3dF/U5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero+5ZAKfYVMLUE -sMwFtoTDJFmVf6JlkOWwsxp1WcQ/MRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQ -xbcaI+GwfQL1FB7Jy+h+KjME9lE/UpgV6Qt2R1xNSmvFCBWu+NFX6epwFP/JRbkM -fLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdag -re7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV+rJfQmzQ84mqhJ6kipMCUG -A1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB/wQE -AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0 -oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcy -LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2Vy -dmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG/WwCATAqMCgGCCsGAQUFBwIB -FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEF -BQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBS -BggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 -U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAA -MIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWY -BPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe/uPT -Wnsu/m4BEC2+dIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFg -U5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAE -AwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51 -vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d+8H4pxtZOUI5eqkntHOFeV -CqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N+XcqcK0OJYrN -8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxG -eOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW/ip2oJ5grAH8mqQfaunuCVE+v -ac+88lkDK/LVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vN -HnXVUGw+yxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVB -Kqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc/2z2shNoDvxvFUYyY1Oe67xINk -myQKc+ygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma+FXsXBIq -WUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna/teik= ------END CERTIFICATE----- diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index a2058cbd..ebea0548 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -21,7 +21,7 @@ #include "esp_err.h" #include "squeezelite-ota.h" #include "esp_netif.h" -#include "Configurator.h" +#include "Config.h" #include #include #include @@ -40,6 +40,7 @@ #include "lwip/sockets.h" #include "globdefs.h" #include "tools.h" +#include "bootstate.h" #define IF_DISPLAY(x) if(display) { x; } @@ -685,8 +686,8 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t if(bin_url){ ESP_LOGI(TAG,"Processing recovery OTA for url %s",STR_OR_ALT(bin_url,"N/A")); ota_thread_parms.url =strdup_psram(bin_url); - configurator_set_string(&sys_State_msg,sys_State_ota_url_tag,sys_state,NULL); - configurator_raise_state_changed(); + system_set_string(&sys_state_data_msg,sys_state_data_ota_url_tag,sys_state,NULL); + config_raise_state_changed(); ESP_LOGD(TAG, "Starting ota on core %u for : %s", OTA_CORE,ota_thread_parms.url); } else { @@ -769,3 +770,19 @@ in_addr_t discover_ota_server(int max) { return s.sin_addr.s_addr; } + +// Callback to handle ota when an IP address is obtained +void cb_handle_ota(nm_state_t new_state, int sub_state) { + if (sys_state && sys_state->ota_url && strlen(sys_state->ota_url)) { + ESP_LOGD(TAG, "Found OTA URL %s", sys_state->ota_url); + if (is_recovery_running) { + ESP_LOGI(TAG, "Updating firmware from link: %s", sys_state->ota_url); +#if defined(CONFIG_WITH_METRICS) + metrics_event("fw_update"); +#endif + start_ota(sys_state->ota_url, NULL, 0); + } else { + ESP_LOGE(TAG, "Restarted to application partition. We're not going to perform OTA!"); + } + } +} \ No newline at end of file diff --git a/components/squeezelite-ota/squeezelite-ota.h b/components/squeezelite-ota/squeezelite-ota.h index d92c6545..459c6a8e 100644 --- a/components/squeezelite-ota/squeezelite-ota.h +++ b/components/squeezelite-ota/squeezelite-ota.h @@ -9,7 +9,7 @@ #include "esp_attr.h" #include "esp_image_format.h" #include "esp_ota_ops.h" -// +#include "network_services.h" // ERASE BLOCK needs to be a multiple of sector size. If a different multiple is passed // the OTA process will adjust. Here, we need to strike the balance between speed and @@ -32,3 +32,6 @@ uint8_t ota_get_pct_complete(); esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length); in_addr_t discover_ota_server(int max); + +// Callback to handle ota when an IP address is obtained +void cb_handle_ota(nm_state_t new_state, int sub_state); \ No newline at end of file diff --git a/components/squeezelite/CMakeLists.txt b/components/squeezelite/CMakeLists.txt index 66fede4e..7d5d3033 100644 --- a/components/squeezelite/CMakeLists.txt +++ b/components/squeezelite/CMakeLists.txt @@ -3,19 +3,19 @@ if(IDF_TARGET STREQUAL "esp32") set(target_requires "driver_bt" "platform_config") endif() -idf_component_register( SRC_DIRS . external ac101 tas57xx wm8978 +idf_component_register( SRC_DIRS . external ac101 tas57xx wm8978 cs4265 INCLUDE_DIRS . ac101 PRIV_REQUIRES codecs newlib esp_common esp-dsp + tools platform_config services spotify raop display - tools audio led_strip _override diff --git a/components/squeezelite/ac101/ac101.c b/components/squeezelite/ac101/ac101.c index 34458d45..fc619efb 100644 --- a/components/squeezelite/ac101/ac101.c +++ b/components/squeezelite/ac101/ac101.c @@ -32,7 +32,7 @@ #include #include "adac.h" #include "ac101.h" -#include "Configurator.h" +#include "Config.h" static const char TAG[] = "AC101"; #define SPKOUT_EN ((1 << 9) | (1 << 11) | (1 << 7) | (1 << 5)) @@ -48,13 +48,13 @@ static const char TAG[] = "AC101"; return b;\ } -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck); static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode); -const struct adac_s dac_ac101 = { sys_DACModelEnum_AC101, init, adac_deinit, power, speaker, headset, volume }; +const struct adac_s dac_ac101 = { sys_dac_models_AC101, init, adac_deinit, power, speaker, headset, volume }; static void ac101_start(ac_module_t mode); static void ac101_stop(void); @@ -64,11 +64,11 @@ static void ac101_set_spk_volume(uint8_t volume); /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck) { - adac_init(config, i2c_port); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck) { + adac_init(config); if (adac_read_word(AC101_ADDR, CHIP_AUDIO_RS) == 0xffff) { ESP_LOGW(TAG, "No AC101 detected"); - i2c_driver_delete(i2c_port); + i2c_driver_delete(config->i2c.port-sys_i2c_port_PORT0); return false; } diff --git a/components/squeezelite/adac.h b/components/squeezelite/adac.h index 53631e5e..35c1efbd 100644 --- a/components/squeezelite/adac.h +++ b/components/squeezelite/adac.h @@ -12,12 +12,12 @@ #include "freertos/FreeRTOS.h" #include "driver/i2s.h" #include "driver/i2c.h" -#include "Configurator.h" +#include "Config.h" typedef enum { ADAC_ON = 0, ADAC_STANDBY, ADAC_OFF } adac_power_e; struct adac_s { - sys_DACModelEnum model; - bool (*init)(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck); + sys_dac_models model; + bool (*init)(sys_dac_config *config,i2s_config_t *i2s_config, bool *mck); void (*deinit)(void); void (*power)(adac_power_e mode); void (*speaker)(bool active); @@ -29,9 +29,10 @@ extern const struct adac_s dac_tas57xx; extern const struct adac_s dac_tas5713; extern const struct adac_s dac_ac101; extern const struct adac_s dac_wm8978; +extern const struct adac_s dac_cs4265; extern const struct adac_s dac_external; -int adac_init(char *config, int i2c_port); +int adac_init(sys_dac_config *config); void adac_deinit(void); esp_err_t adac_write(int i2c_addr, uint8_t reg, uint8_t *data, size_t count); esp_err_t adac_write_byte(int i2c_addr, uint8_t reg, uint8_t val); diff --git a/components/squeezelite/adac_core.c b/components/squeezelite/adac_core.c index ea72450c..ee920829 100644 --- a/components/squeezelite/adac_core.c +++ b/components/squeezelite/adac_core.c @@ -23,16 +23,13 @@ } while (0) static const char TAG[] = "DAC core"; -static int i2c_port = -1; - +i2c_port_t i2c_port = -1; /**************************************************************************************** * init */ -int adac_init(char *config, int i2c_port_num) { +int adac_init(sys_dac_config *config) { int i2c_addr = 0; - i2c_port = i2c_port_num; - // configure i2c i2c_config_t i2c_config = { .mode = I2C_MODE_MASTER, @@ -42,17 +39,19 @@ int adac_init(char *config, int i2c_port_num) { .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 250000, }; - - PARSE_PARAM(config, "i2c", '=', i2c_addr); - PARSE_PARAM(config, "sda", '=', i2c_config.sda_io_num); - PARSE_PARAM(config, "scl", '=', i2c_config.scl_io_num); + i2c_addr = config->addr; + if(config->has_i2c){ + i2c_config.sda_io_num = config->i2c.sda; + i2c_config.scl_io_num = config->i2c.scl; + i2c_config.master.clk_speed = config->i2c.speed>0?config->i2c.speed:i2c_config.master.clk_speed; + } if (i2c_config.sda_io_num == -1 || i2c_config.scl_io_num == -1) { ESP_LOGW(TAG, "DAC does not use i2c"); return i2c_addr; } - - ESP_LOGI(TAG, "DAC uses I2C port:%d, sda:%d, scl:%d", i2c_port, i2c_config.sda_io_num, i2c_config.scl_io_num); + i2c_port = config->i2c.port-sys_i2c_port_PORT0; + ESP_LOGI(TAG, "DAC uses I2C port:%s, sda:%d, scl:%d", sys_i2c_port_name(config->i2c.port), i2c_config.sda_io_num, i2c_config.scl_io_num); // we have an I2C configured i2c_param_config(i2c_port, &i2c_config); diff --git a/components/squeezelite/controls.c b/components/squeezelite/controls.c index bb6b815b..52115451 100644 --- a/components/squeezelite/controls.c +++ b/components/squeezelite/controls.c @@ -7,7 +7,7 @@ */ #include "squeezelite.h" -// #include "Configurator.h" +// #include "Config.h" #pragma message("fixme: look for TODO below") #include "audio_controls.h" @@ -54,7 +54,7 @@ static u16_t server_cport; static int cli_sock = -1; static u8_t mac[6]; static void (*chained_notify)(in_addr_t, u16_t, u16_t); -static bool raw_mode; +static bool raw_mode=false; static void cli_send_cmd(char *cmd); @@ -244,15 +244,16 @@ static bool ir_handler(u16_t addr, u16_t cmd) { */ void sb_controls_init(void) { // TODO: Add support for the commented code + #pragma message("sb_controls_init needs to be implemented") // char *p = config_alloc_get_default(NVS_TYPE_STR, "lms_ctrls_raw", "n", 0); // raw_mode = p && (*p == '1' || *p == 'Y' || *p == 'y'); // free(p); - // LOG_INFO("initializing audio (buttons/rotary/ir) controls (raw:%u)", raw_mode); + LOG_INFO("initializing audio (buttons/rotary/ir) controls (raw:%u)", raw_mode); - // get_mac(mac); - // actrls_set_default(LMS_controls, raw_mode, NULL, ir_handler); + get_mac(mac); + actrls_set_default(LMS_controls, raw_mode, NULL, ir_handler); - // chained_notify = server_notify; - // server_notify = notify; + chained_notify = server_notify; + server_notify = notify; } diff --git a/components/squeezelite/cs4265/cs4265.c b/components/squeezelite/cs4265/cs4265.c index eae8cea8..2c5290cd 100644 --- a/components/squeezelite/cs4265/cs4265.c +++ b/components/squeezelite/cs4265/cs4265.c @@ -1,4 +1,4 @@ -/* +/* * Squeezelite for esp32 * * (c) Sebastien 2019 @@ -8,21 +8,21 @@ * https://opensource.org/licenses/MIT * */ - + #include -//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "Config.h" +#include "adac.h" +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "driver/i2s.h" +#include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "driver/i2s.h" -#include "driver/i2c.h" -#include "driver/gpio.h" -#include "esp_log.h" -#include "adac.h" -#include "stdio.h" #include "math.h" -#include "Configurator.h" -#define CS4265_PULL_UP (0x4F ) -#define CS4265_PULL_DOWN (0x4E ) +#include "stdio.h" +#define CS4265_PULL_UP (0x4F) +#define CS4265_PULL_DOWN (0x4E) #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -30,188 +30,181 @@ static const char TAG[] = "CS4265"; -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); +static bool init(sys_dac_config * config, i2s_config_t* i2s_config, bool* mck); static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode); -static esp_err_t cs4265_update_bit(uint8_t reg_no,uint8_t mask,uint8_t val ); +static esp_err_t cs4265_update_bit(uint8_t reg_no, uint8_t mask, uint8_t val); static esp_err_t set_clock(); -const struct adac_s dac_cs4265 = { sys_DACModelEnum_CS4265, init, adac_deinit, power, speaker, headset, volume }; +const struct adac_s dac_cs4265 = { + sys_dac_models_CS4265, init, adac_deinit, power, speaker, headset, volume}; struct cs4265_cmd_s { - uint8_t reg; - uint8_t value; + uint8_t reg; + uint8_t value; }; struct cs4265_private { - uint8_t format; - uint32_t sysclk; - i2s_config_t *i2s_config; - int i2c_port; -}; + uint8_t format; + uint32_t sysclk; + i2s_config_t* i2s_config; + i2c_port_t port; + }; struct cs4265_private cs4265; -#define CS4265_CHIP_ID 0x1 -#define CS4265_CHIP_ID_VAL 0xD0 -#define CS4265_CHIP_ID_MASK 0xF0 -#define CS4265_REV_ID_MASK 0x0F +#define CS4265_CHIP_ID 0x1 +#define CS4265_CHIP_ID_VAL 0xD0 +#define CS4265_CHIP_ID_MASK 0xF0 +#define CS4265_REV_ID_MASK 0x0F -#define CS4265_PWRCTL 0x02 -#define CS4265_PWRCTL_PDN (1 << 0) -#define CS4265_PWRCTL_PDN_DAC (1 << 1) -#define CS4265_PWRCTL_PDN_ADC (1 << 2) -#define CS4265_PWRCTL_PDN_MIC (1 << 3) -#define CS4265_PWRCTL_FREEZE (1 << 7) -#define CS4265_PWRCTL_PDN_ALL CS4265_PWRCTL_PDN | CS4265_PWRCTL_PDN_ADC | CS4265_PWRCTL_PDN_DAC | CS4265_PWRCTL_PDN_MIC +#define CS4265_PWRCTL 0x02 +#define CS4265_PWRCTL_PDN (1 << 0) +#define CS4265_PWRCTL_PDN_DAC (1 << 1) +#define CS4265_PWRCTL_PDN_ADC (1 << 2) +#define CS4265_PWRCTL_PDN_MIC (1 << 3) +#define CS4265_PWRCTL_FREEZE (1 << 7) +#define CS4265_PWRCTL_PDN_ALL \ + CS4265_PWRCTL_PDN | CS4265_PWRCTL_PDN_ADC | CS4265_PWRCTL_PDN_DAC | CS4265_PWRCTL_PDN_MIC - - -#define CS4265_DAC_CTL 0x3 +#define CS4265_DAC_CTL 0x3 // De-Emphasis Control (Bit 1) // The standard 50/15 i2s digital de-emphasis filter response may be implemented for a sample -// rate of 44.1 kHz when the DeEmph bit is set. NOTE: De-emphasis is available only in Single-Speed Mode. -#define CS4265_DAC_CTL_DEEMPH (1 << 1) +// rate of 44.1 kHz when the DeEmph bit is set. NOTE: De-emphasis is available only in Single-Speed +// Mode. +#define CS4265_DAC_CTL_DEEMPH (1 << 1) // MUTE DAC -// The DAC outputs will mute and the MUTEC pin will become active when this bit is set. Though this bit is -// active high, it should be noted that the MUTEC pin is active low. The common mode voltage on the outputs -// will be retained when this bit is set. The muting function is effected, similar to attenuation changes, by the -// DACSoft and DACZero bits in the DAC Control 2 register. -#define CS4265_DAC_CTL_MUTE (1 << 2) -// The required relationship between LRCK, SCLK and SDIN for the DAC is defined by the DAC Digital Interface -// DAC_DIF1 DAC_DIF0 Description Format Figure -// 0 0 Left Justified, up to 24-bit data (default) 0 5 -// 0 1 I²S, up to 24-bit data 1 6 +// The DAC outputs will mute and the MUTEC pin will become active when this bit is set. Though this +// bit is active high, it should be noted that the MUTEC pin is active low. The common mode voltage +// on the outputs will be retained when this bit is set. The muting function is effected, similar to +// attenuation changes, by the DACSoft and DACZero bits in the DAC Control 2 register. +#define CS4265_DAC_CTL_MUTE (1 << 2) +// The required relationship between LRCK, SCLK and SDIN for the DAC is defined by the DAC Digital +// Interface DAC_DIF1 DAC_DIF0 Description Format Figure 0 0 Left +// Justified, up to 24-bit data (default) 0 5 0 1 I²S, up to 24-bit data 1 6 // 1 0 Right-Justified, 16-bit Data 2 7 // 1 1 Right-Justified, 24-bit Data 3 7 -#define CS4265_DAC_CTL_DIF0 (1 << 4) -// The required relationship between LRCK, SCLK and SDIN for the DAC is defined by the DAC Digital Interface -// DAC_DIF1 DAC_DIF0 Description Format Figure -// 0 0 Left Justified, up to 24-bit data (default) 0 5 -// 0 1 I²S, up to 24-bit data 1 6 +#define CS4265_DAC_CTL_DIF0 (1 << 4) +// The required relationship between LRCK, SCLK and SDIN for the DAC is defined by the DAC Digital +// Interface DAC_DIF1 DAC_DIF0 Description Format Figure 0 0 Left +// Justified, up to 24-bit data (default) 0 5 0 1 I²S, up to 24-bit data 1 6 // 1 0 Right-Justified, 16-bit Data 2 7 // 1 1 Right-Justified, 24-bit Data 3 7 -#define CS4265_DAC_CTL_DIF1 (1 << 5) +#define CS4265_DAC_CTL_DIF1 (1 << 5) +#define CS4265_ADC_CTL 0x4 +#define CS4265_ADC_MASTER 1 +#define CS4265_ADC_CTL_MUTE (1 << 2) +#define CS4265_ADC_DIF (1 << 4) +#define CS4265_ADC_FM (3 << 6) -#define CS4265_ADC_CTL 0x4 -#define CS4265_ADC_MASTER 1 - -#define CS4265_ADC_CTL_MUTE (1 << 2) -#define CS4265_ADC_DIF (1 << 4) -#define CS4265_ADC_FM (3 << 6) - -//Master Clock Dividers (Bits 6:4) -//Sets the frequency of the supplied MCLK signal. +// Master Clock Dividers (Bits 6:4) +// Sets the frequency of the supplied MCLK signal. // -//MCLK Divider MCLK Freq2 MCLK Freq1 MCLK Freq0 -// ÷ 1 0 0 0 -// ÷ 1.5 0 0 1 -// ÷ 2 0 1 0 -// ÷ 3 0 1 1 -// ÷ 4 1 0 0 -// NA 1 0 1 -// NA 1 1 x -#define CS4265_MCLK_FREQ 0x5 -#define CS4265_MCLK_FREQ_1_0X (0b000<<4 ) -#define CS4265_MCLK_FREQ_1_5X (0b001<<4 ) -#define CS4265_MCLK_FREQ_2_0X (0b010<<4 ) -#define CS4265_MCLK_FREQ_3_0X (0b011<<4 ) -#define CS4265_MCLK_FREQ_4_0X (0b100<<4 ) +// MCLK Divider MCLK Freq2 MCLK Freq1 MCLK Freq0 +// ÷ 1 0 0 0 +// ÷ 1.5 0 0 1 +// ÷ 2 0 1 0 +// ÷ 3 0 1 1 +// ÷ 4 1 0 0 +// NA 1 0 1 +// NA 1 1 x +#define CS4265_MCLK_FREQ 0x5 +#define CS4265_MCLK_FREQ_1_0X (0b000 << 4) +#define CS4265_MCLK_FREQ_1_5X (0b001 << 4) +#define CS4265_MCLK_FREQ_2_0X (0b010 << 4) +#define CS4265_MCLK_FREQ_3_0X (0b011 << 4) +#define CS4265_MCLK_FREQ_4_0X (0b100 << 4) +#define CS4265_MCLK_FREQ_MASK (7 << 4) -#define CS4265_MCLK_FREQ_MASK (7 << 4) - -#define CS4265_SIG_SEL 0x6 -#define CS4265_SIG_SEL_LOOP (1 << 1) -#define CS4265_SIG_SEL_SDIN2 (1 << 7) -#define CS4265_SIG_SEL_SDIN1 (0 << 7) +#define CS4265_SIG_SEL 0x6 +#define CS4265_SIG_SEL_LOOP (1 << 1) +#define CS4265_SIG_SEL_SDIN2 (1 << 7) +#define CS4265_SIG_SEL_SDIN1 (0 << 7) // Sets the gain or attenuation for the ADC input PGA stage. The gain may be adjusted from -12 dB to -// +12 dB in 0.5 dB steps. The gain bits are in two’s complement with the Gain0 bit set for a 0.5 dB step. -// Register settings outside of the ±12 dB range are reserved and must not be used. See Table 13 for example settings -#define CS4265_CHB_PGA_CTL 0x7 +// +12 dB in 0.5 dB steps. The gain bits are in two’s complement with the Gain0 bit set for a 0.5 dB +// step. Register settings outside of the ±12 dB range are reserved and must not be used. See Table +// 13 for example settings +#define CS4265_CHB_PGA_CTL 0x7 // Sets the gain or attenuation for the ADC input PGA stage. The gain may be adjusted from -12 dB to -// +12 dB in 0.5 dB steps. The gain bits are in two’s complement with the Gain0 bit set for a 0.5 dB step. -// Register settings outside of the ±12 dB range are reserved and must not be used. See Table 13 for example settings -#define CS4265_CHA_PGA_CTL 0x8 +// +12 dB in 0.5 dB steps. The gain bits are in two’s complement with the Gain0 bit set for a 0.5 dB +// step. Register settings outside of the ±12 dB range are reserved and must not be used. See Table +// 13 for example settings +#define CS4265_CHA_PGA_CTL 0x8 // Gain[5:0] Setting // 101000 -12 dB // 000000 0 dB // 011000 +12 dB +#define CS4265_ADC_CTL2 0x9 -#define CS4265_ADC_CTL2 0x9 - -// The digital volume control allows the user to attenuate the signal in 0.5 dB increments from 0 to -127 dB. -// The Vol0 bit activates a 0.5 dB attenuation when set, and no attenuation when cleared. The Vol[7:1] bits -// activate attenuation equal to their decimal equivalent (in dB). -//Binary Code Volume Setting -//00000000 0 dB -//00000001 -0.5 dB -//00101000 -20 dB -//00101001 -20.5 dB -//11111110 -127 dB -//11111111 -127.5 dB -#define CS4265_DAC_CHA_VOL 0xA -// The digital volume control allows the user to attenuate the signal in 0.5 dB increments from 0 to -127 dB. -// The Vol0 bit activates a 0.5 dB attenuation when set, and no attenuation when cleared. The Vol[7:1] bits -// activate attenuation equal to their decimal equivalent (in dB). -//Binary Code Volume Setting -//00000000 0 dB -//00000001 -0.5 dB -//00101000 -20 dB -//00101001 -20.5 dB -//11111110 -127 dB -//11111111 -127.5 dB -#define CS4265_DAC_CHB_VOL 0xB -#define CS4265_DAC_VOL_ATT_000_0 0b00000000 -#define CS4265_DAC_VOL_ATT_000_5 0b00000001 -#define CS4265_DAC_VOL_ATT_020_0 0b00101000 -#define CS4265_DAC_VOL_ATT_020_5 0b00101001 -#define CS4265_DAC_VOL_ATT_127_0 0b11111110 -#define CS4265_DAC_VOL_ATT_127_5 0b11111111 +// The digital volume control allows the user to attenuate the signal in 0.5 dB increments from 0 to +// -127 dB. The Vol0 bit activates a 0.5 dB attenuation when set, and no attenuation when cleared. +// The Vol[7:1] bits activate attenuation equal to their decimal equivalent (in dB). +// Binary Code Volume Setting +// 00000000 0 dB +// 00000001 -0.5 dB +// 00101000 -20 dB +// 00101001 -20.5 dB +// 11111110 -127 dB +// 11111111 -127.5 dB +#define CS4265_DAC_CHA_VOL 0xA +// The digital volume control allows the user to attenuate the signal in 0.5 dB increments from 0 to +// -127 dB. The Vol0 bit activates a 0.5 dB attenuation when set, and no attenuation when cleared. +// The Vol[7:1] bits activate attenuation equal to their decimal equivalent (in dB). +// Binary Code Volume Setting +// 00000000 0 dB +// 00000001 -0.5 dB +// 00101000 -20 dB +// 00101001 -20.5 dB +// 11111110 -127 dB +// 11111111 -127.5 dB +#define CS4265_DAC_CHB_VOL 0xB +#define CS4265_DAC_VOL_ATT_000_0 0b00000000 +#define CS4265_DAC_VOL_ATT_000_5 0b00000001 +#define CS4265_DAC_VOL_ATT_020_0 0b00101000 +#define CS4265_DAC_VOL_ATT_020_5 0b00101001 +#define CS4265_DAC_VOL_ATT_127_0 0b11111110 +#define CS4265_DAC_VOL_ATT_127_5 0b11111111 // DAC Soft Ramp or Zero Cross Enable (Bits 7:6) // // Soft Ramp Enable -// Soft Ramp allows level changes, both muting and attenuation, to be implemented by incrementally ramping, in 1/8 dB steps, from the current level to the new level at a rate of 1 dB per 8 left/right clock periods. -// See Table 17. -// Zero Cross Enable -// Zero Cross Enable dictates that signal-level changes, either by attenuation changes or muting, will occur -// on a signal zero crossing to minimize audible artifacts. The requested level change will occur after a timeout period between 512 and 1024 sample periods (10.7 ms to 21.3 ms at 48 kHz sample rate) if the signal -// does not encounter a zero crossing. The zero cross function is independently monitored and implemented -// for each channel. See Table 17. -// Soft Ramp and Zero Cross Enable -// Soft Ramp and Zero Cross Enable dictate that signal-level changes, either by attenuation changes or muting, will occur in 1/8 dB steps and be implemented on a signal zero crossing. The 1/8 dB level change will -// occur after a time-out period between 512 and 1024 sample periods (10.7 ms to 21.3 ms at 48 kHz sample rate) if the signal does not encounter a zero crossing. The zero cross function is independently monitored and implemented for each channel -// DACSoft DACZeroCross Mode -// 0 0 Changes to affect immediately -// 0 1 Zero Cross enabled -// 1 0 Soft Ramp enabled -// 1 1 Soft Ramp and Zero Cross enabled (default) -#define CS4265_DAC_CTL2 0xC -#define CS4265_DAC_CTL2_ZERO_CROSS_EN (uint8_t)(0b01 <<7) -#define CS4265_DAC_CTL2_SOFT_RAMP_EN (uint8_t)(0b10 <<7) -#define CS4265_DAC_CTL2_SOFT_RAMP_ZERO_CROSS_EN (uint8_t)(0b11 <<7) +// Soft Ramp allows level changes, both muting and attenuation, to be implemented by incrementally +// ramping, in 1/8 dB steps, from the current level to the new level at a rate of 1 dB per 8 +// left/right clock periods. See Table 17. Zero Cross Enable Zero Cross Enable dictates that +// signal-level changes, either by attenuation changes or muting, will occur on a signal zero +// crossing to minimize audible artifacts. The requested level change will occur after a timeout +// period between 512 and 1024 sample periods (10.7 ms to 21.3 ms at 48 kHz sample rate) if the +// signal does not encounter a zero crossing. The zero cross function is independently monitored and +// implemented for each channel. See Table 17. Soft Ramp and Zero Cross Enable Soft Ramp and Zero +// Cross Enable dictate that signal-level changes, either by attenuation changes or muting, will +// occur in 1/8 dB steps and be implemented on a signal zero crossing. The 1/8 dB level change will +// occur after a time-out period between 512 and 1024 sample periods (10.7 ms to 21.3 ms at 48 kHz +// sample rate) if the signal does not encounter a zero crossing. The zero cross function is +// independently monitored and implemented for each channel DACSoft DACZeroCross Mode 0 0 Changes to +// affect immediately 0 1 Zero Cross enabled 1 0 Soft Ramp enabled 1 1 Soft Ramp and Zero Cross +// enabled (default) +#define CS4265_DAC_CTL2 0xC +#define CS4265_DAC_CTL2_ZERO_CROSS_EN (uint8_t)(0b01 << 7) +#define CS4265_DAC_CTL2_SOFT_RAMP_EN (uint8_t)(0b10 << 7) +#define CS4265_DAC_CTL2_SOFT_RAMP_ZERO_CROSS_EN (uint8_t)(0b11 << 7) +#define CS4265_INT_STATUS 0xD +#define CS4265_INT_STATUS_ADC_UNDF (1 << 0) +#define CS4265_INT_STATUS_ADC_OVF (1 << 1) +#define CS4265_INT_STATUS_CLKERR (1 << 3) -#define CS4265_INT_STATUS 0xD -#define CS4265_INT_STATUS_ADC_UNDF (1<<0) -#define CS4265_INT_STATUS_ADC_OVF (1<<1) -#define CS4265_INT_STATUS_CLKERR (1<<3) +#define CS4265_INT_MASK 0xE +#define CS4265_STATUS_MODE_MSB 0xF +#define CS4265_STATUS_MODE_LSB 0x10 +// Transmitter Control 1 - Address 11h +#define CS4265_SPDIF_CTL1 0x11 -#define CS4265_INT_MASK 0xE -#define CS4265_STATUS_MODE_MSB 0xF -#define CS4265_STATUS_MODE_LSB 0x10 - -//Transmitter Control 1 - Address 11h -#define CS4265_SPDIF_CTL1 0x11 - - - -#define CS4265_SPDIF_CTL2 0x12 +#define CS4265_SPDIF_CTL2 0x12 // Transmitter Digital Interface Format (Bits 7:6) // Function: // The required relationship between LRCK, SCLK and SDIN for the transmitter is defined @@ -220,343 +213,348 @@ struct cs4265_private cs4265; // 0 1 I²S, up to 24-bit data 1 6 // 1 0 Right-Justified, 16-bit Data 2 7 // 1 1 Right-Justified, 24-bit Data 3 7 -#define CS4265_SPDIF_CTL2_MMTLR (1<<0) -#define CS4265_SPDIF_CTL2_MMTCS (1<<1) -#define CS4265_SPDIF_CTL2_MMT (1<<2) -#define CS4265_SPDIF_CTL2_V (1<<3) -#define CS4265_SPDIF_CTL2_TXMUTE (1<<4) -#define CS4265_SPDIF_CTL2_TXOFF (1<<5) -#define CS4265_SPDIF_CTL2_MUTE (1 << 4) -#define CS4265_SPDIF_CTL2_DIF (3 << 6) -#define CS4265_SPDIF_CTL2_DIF0 (1 << 6) -#define CS4265_SPDIF_CTL2_DIF1 (1 << 7) +#define CS4265_SPDIF_CTL2_MMTLR (1 << 0) +#define CS4265_SPDIF_CTL2_MMTCS (1 << 1) +#define CS4265_SPDIF_CTL2_MMT (1 << 2) +#define CS4265_SPDIF_CTL2_V (1 << 3) +#define CS4265_SPDIF_CTL2_TXMUTE (1 << 4) +#define CS4265_SPDIF_CTL2_TXOFF (1 << 5) +#define CS4265_SPDIF_CTL2_MUTE (1 << 4) +#define CS4265_SPDIF_CTL2_DIF (3 << 6) +#define CS4265_SPDIF_CTL2_DIF0 (1 << 6) +#define CS4265_SPDIF_CTL2_DIF1 (1 << 7) - - - - - -#define CS4265_C_DATA_BUFF 0x13 -#define CS4265_MAX_REGISTER 0x2A +#define CS4265_C_DATA_BUFF 0x13 +#define CS4265_MAX_REGISTER 0x2A struct cs4265_clk_para { - uint32_t mclk; - uint32_t rate; - uint8_t fm_mode; /* values 1, 2, or 4 */ - uint8_t mclkdiv; + uint32_t mclk; + uint32_t rate; + uint8_t fm_mode; /* values 1, 2, or 4 */ + uint8_t mclkdiv; }; static const struct cs4265_clk_para clk_map_table[] = { - /*32k*/ - {8192000, 32000, 0, 0}, - {12288000, 32000, 0, 1}, - {16384000, 32000, 0, 2}, - {24576000, 32000, 0, 3}, - {32768000, 32000, 0, 4}, + /*32k*/ + {8192000, 32000, 0, 0}, + {12288000, 32000, 0, 1}, + {16384000, 32000, 0, 2}, + {24576000, 32000, 0, 3}, + {32768000, 32000, 0, 4}, - /*44.1k*/ - {11289600, 44100, 0, 0}, - {16934400, 44100, 0, 1}, - {22579200, 44100, 0, 2}, - {33868000, 44100, 0, 3}, - {45158400, 44100, 0, 4}, + /*44.1k*/ + {11289600, 44100, 0, 0}, + {16934400, 44100, 0, 1}, + {22579200, 44100, 0, 2}, + {33868000, 44100, 0, 3}, + {45158400, 44100, 0, 4}, - /*48k*/ - {12288000, 48000, 0, 0}, - {18432000, 48000, 0, 1}, - {24576000, 48000, 0, 2}, - {36864000, 48000, 0, 3}, - {49152000, 48000, 0, 4}, + /*48k*/ + {12288000, 48000, 0, 0}, + {18432000, 48000, 0, 1}, + {24576000, 48000, 0, 2}, + {36864000, 48000, 0, 3}, + {49152000, 48000, 0, 4}, - /*64k*/ - {8192000, 64000, 1, 0}, - {12288000, 64000, 1, 1}, - {16934400, 64000, 1, 2}, - {24576000, 64000, 1, 3}, - {32768000, 64000, 1, 4}, + /*64k*/ + {8192000, 64000, 1, 0}, + {12288000, 64000, 1, 1}, + {16934400, 64000, 1, 2}, + {24576000, 64000, 1, 3}, + {32768000, 64000, 1, 4}, - /* 88.2k */ - {11289600, 88200, 1, 0}, - {16934400, 88200, 1, 1}, - {22579200, 88200, 1, 2}, - {33868000, 88200, 1, 3}, - {45158400, 88200, 1, 4}, + /* 88.2k */ + {11289600, 88200, 1, 0}, + {16934400, 88200, 1, 1}, + {22579200, 88200, 1, 2}, + {33868000, 88200, 1, 3}, + {45158400, 88200, 1, 4}, - /* 96k */ - {12288000, 96000, 1, 0}, - {18432000, 96000, 1, 1}, - {24576000, 96000, 1, 2}, - {36864000, 96000, 1, 3}, - {49152000, 96000, 1, 4}, + /* 96k */ + {12288000, 96000, 1, 0}, + {18432000, 96000, 1, 1}, + {24576000, 96000, 1, 2}, + {36864000, 96000, 1, 3}, + {49152000, 96000, 1, 4}, - /* 128k */ - {8192000, 128000, 2, 0}, - {12288000, 128000, 2, 1}, - {16934400, 128000, 2, 2}, - {24576000, 128000, 2, 3}, - {32768000, 128000, 2, 4}, + /* 128k */ + {8192000, 128000, 2, 0}, + {12288000, 128000, 2, 1}, + {16934400, 128000, 2, 2}, + {24576000, 128000, 2, 3}, + {32768000, 128000, 2, 4}, - /* 176.4k */ - {11289600, 176400, 2, 0}, - {16934400, 176400, 2, 1}, - {22579200, 176400, 2, 2}, - {33868000, 176400, 2, 3}, - {49152000, 176400, 2, 4}, + /* 176.4k */ + {11289600, 176400, 2, 0}, + {16934400, 176400, 2, 1}, + {22579200, 176400, 2, 2}, + {33868000, 176400, 2, 3}, + {49152000, 176400, 2, 4}, - /* 192k */ - {12288000, 192000, 2, 0}, - {18432000, 192000, 2, 1}, - {24576000, 192000, 2, 2}, - {36864000, 192000, 2, 3}, - {49152000, 192000, 2, 4}, + /* 192k */ + {12288000, 192000, 2, 0}, + {18432000, 192000, 2, 1}, + {24576000, 192000, 2, 2}, + {36864000, 192000, 2, 3}, + {49152000, 192000, 2, 4}, }; static const struct cs4265_cmd_s cs4265_init_sequence[] = { - {CS4265_PWRCTL, CS4265_PWRCTL_PDN_ADC | CS4265_PWRCTL_FREEZE | CS4265_PWRCTL_PDN_DAC | CS4265_PWRCTL_PDN_MIC}, - {CS4265_DAC_CTL, CS4265_DAC_CTL_DIF0 | CS4265_DAC_CTL_MUTE}, - {CS4265_SIG_SEL, CS4265_SIG_SEL_SDIN1},/// SDIN1 - {CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_DIF0 },// - {CS4265_ADC_CTL, 0x00 },// // Set the serial audio port in slave mode - {CS4265_MCLK_FREQ, CS4265_MCLK_FREQ_1_0X },// // no divider - {CS4265_CHB_PGA_CTL, 0x00 },// // sets the gain to 0db on channel B - {CS4265_CHA_PGA_CTL, 0x00 },// // sets the gain to 0db on channel A - {CS4265_ADC_CTL2, 0x19 },// - {CS4265_DAC_CHA_VOL,CS4265_DAC_VOL_ATT_000_0 },// Full volume out - {CS4265_DAC_CHB_VOL, CS4265_DAC_VOL_ATT_000_0 },// // Full volume out - {CS4265_DAC_CTL2, CS4265_DAC_CTL2_SOFT_RAMP_ZERO_CROSS_EN },// - {CS4265_SPDIF_CTL1, 0x00 },// - {CS4265_INT_MASK, 0x00 },// - {CS4265_STATUS_MODE_MSB, 0x00 },// - {CS4265_STATUS_MODE_LSB, 0x00 },// - {0xff,0xff} -}; - + {CS4265_PWRCTL, CS4265_PWRCTL_PDN_ADC | CS4265_PWRCTL_FREEZE | CS4265_PWRCTL_PDN_DAC | + CS4265_PWRCTL_PDN_MIC}, + {CS4265_DAC_CTL, CS4265_DAC_CTL_DIF0 | CS4265_DAC_CTL_MUTE}, + {CS4265_SIG_SEL, CS4265_SIG_SEL_SDIN1}, /// SDIN1 + {CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_DIF0}, // + {CS4265_ADC_CTL, 0x00}, // // Set the serial audio port in slave mode + {CS4265_MCLK_FREQ, CS4265_MCLK_FREQ_1_0X}, // // no divider + {CS4265_CHB_PGA_CTL, 0x00}, // // sets the gain to 0db on channel B + {CS4265_CHA_PGA_CTL, 0x00}, // // sets the gain to 0db on channel A + {CS4265_ADC_CTL2, 0x19}, // + {CS4265_DAC_CHA_VOL, CS4265_DAC_VOL_ATT_000_0}, // Full volume out + {CS4265_DAC_CHB_VOL, CS4265_DAC_VOL_ATT_000_0}, // // Full volume out + {CS4265_DAC_CTL2, CS4265_DAC_CTL2_SOFT_RAMP_ZERO_CROSS_EN}, // + {CS4265_SPDIF_CTL1, 0x00}, // + {CS4265_INT_MASK, 0x00}, // + {CS4265_STATUS_MODE_MSB, 0x00}, // + {CS4265_STATUS_MODE_LSB, 0x00}, // + {0xff, 0xff}}; // matching orders -typedef enum { cs4265_ACTIVE = 0, cs4265_STANDBY, cs4265_DOWN, cs4265_ANALOGUE_OFF, cs4265_ANALOGUE_ON, cs4265_VOLUME } dac_cmd_e; - - +typedef enum { + cs4265_ACTIVE = 0, + cs4265_STANDBY, + cs4265_DOWN, + cs4265_ANALOGUE_OFF, + cs4265_ANALOGUE_ON, + cs4265_VOLUME +} dac_cmd_e; static int cs4265_addr; static void dac_cmd(dac_cmd_e cmd, ...); static int cs4265_detect(void); -static uint32_t calc_rnd_mclk_freq(){ - float m_scale = (cs4265.i2s_config->sample_rate > 96000 && cs4265.i2s_config->bits_per_sample > 16) ? 4 : 8; - float num_channels = cs4265.i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1; - return (uint32_t) round(cs4265.i2s_config->bits_per_sample*i2s_get_clk(cs4265.i2c_port)* m_scale*num_channels/100)*100; +static uint32_t calc_rnd_mclk_freq() { + float m_scale = + (cs4265.i2s_config->sample_rate > 96000 && cs4265.i2s_config->bits_per_sample > 16) ? 4 : 8; + float num_channels = cs4265.i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1; + return (uint32_t)round(cs4265.i2s_config->bits_per_sample * i2s_get_clk(cs4265.port) * + m_scale * num_channels / 100) * + 100; } -static int cs4265_get_clk_index(int mclk, int rate) -{ - for (int i = 0; i < ARRAY_SIZE(clk_map_table); i++) { - if (clk_map_table[i].rate == rate && - clk_map_table[i].mclk == mclk) - return i; - } - return -1; +static int cs4265_get_clk_index(int mclk, int rate) { + for (int i = 0; i < ARRAY_SIZE(clk_map_table); i++) { + if (clk_map_table[i].rate == rate && clk_map_table[i].mclk == mclk) return i; + } + return -1; } -static esp_err_t set_clock(){ +static esp_err_t set_clock() { esp_err_t err = ESP_OK; - uint32_t mclk = calc_rnd_mclk_freq(); - int index = cs4265_get_clk_index(mclk,cs4265.i2s_config->sample_rate ); - if (index >= 0) { - ESP_LOGD(TAG, "Setting clock for mclk %u, rate %u (fm mode:%u, clk div:%u))", mclk,cs4265.i2s_config->sample_rate,clk_map_table[index].fm_mode,clk_map_table[index].mclkdiv); - err=cs4265_update_bit(CS4265_ADC_CTL,CS4265_ADC_FM, clk_map_table[index].fm_mode << 6); - err|=cs4265_update_bit( CS4265_MCLK_FREQ,CS4265_MCLK_FREQ_MASK,clk_map_table[index].mclkdiv << 4); - } else { - ESP_LOGE(TAG,"can't get correct mclk for "); - return -1; - } + uint32_t mclk = calc_rnd_mclk_freq(); + int index = cs4265_get_clk_index(mclk, cs4265.i2s_config->sample_rate); + if (index >= 0) { + ESP_LOGD(TAG, "Setting clock for mclk %u, rate %u (fm mode:%u, clk div:%u))", mclk, + cs4265.i2s_config->sample_rate, clk_map_table[index].fm_mode, + clk_map_table[index].mclkdiv); + err = cs4265_update_bit(CS4265_ADC_CTL, CS4265_ADC_FM, clk_map_table[index].fm_mode << 6); + err |= cs4265_update_bit( + CS4265_MCLK_FREQ, CS4265_MCLK_FREQ_MASK, clk_map_table[index].mclkdiv << 4); + } else { + ESP_LOGE(TAG, "can't get correct mclk for "); + return -1; + } return err; } - -static void get_status(){ - uint8_t sts1= adac_read_byte(cs4265_addr, CS4265_INT_STATUS); - ESP_LOGD(TAG,"Status: %s",sts1&CS4265_INT_STATUS_CLKERR?"CLK Error":"CLK OK"); +static void get_status() { + uint8_t sts1 = adac_read_byte(cs4265_addr, CS4265_INT_STATUS); + ESP_LOGD(TAG, "Status: %s", sts1 & CS4265_INT_STATUS_CLKERR ? "CLK Error" : "CLK OK"); } - /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) { - // find which TAS we are using (if any) - cs4265_addr = adac_init(config, i2c_port); - cs4265.i2s_config = i2s_config; - cs4265.i2c_port=i2c_port; - if (!cs4265_addr) cs4265_addr = cs4265_detect(); - if (!cs4265_addr) { - ESP_LOGE(TAG, "No cs4265 detected"); - adac_deinit(); - return false; - } - #if BYTES_PER_FRAME == 8 - ESP_LOGE(TAG,"The CS4265 does not support 32 bits mode. "); - adac_deinit(); - return false; - #endif - // configure MLK - ESP_LOGD(TAG, "Configuring MCLK on GPIO0"); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); - REG_WRITE(PIN_CTRL, 0xFFFFFFF0); - i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); - for (int i = 0; cs4265_init_sequence[i].reg != 0xff; i++) { - i2c_master_start(i2c_cmd); - i2c_master_write_byte(i2c_cmd, (cs4265_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, cs4265_init_sequence[i].reg, I2C_MASTER_NACK); - i2c_master_write_byte(i2c_cmd, cs4265_init_sequence[i].value, I2C_MASTER_NACK); - ESP_LOGD(TAG, "i2c write %x at %u", cs4265_init_sequence[i].reg, cs4265_init_sequence[i].value); - } +static bool init(sys_dac_config * config, i2s_config_t* i2s_config, bool* mck) { - i2c_master_stop(i2c_cmd); - esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_RATE_MS); + // find which CS4265 we are using (if any) + cs4265_addr = adac_init(config); + cs4265.i2s_config = i2s_config; + if (!cs4265_addr) cs4265_addr = cs4265_detect(); + if (!cs4265_addr) { + ESP_LOGE(TAG, "No cs4265 detected"); + adac_deinit(); + return false; + } + cs4265.port = config->i2c.port-sys_i2c_port_PORT0; +#if BYTES_PER_FRAME == 8 + ESP_LOGE(TAG, "The CS4265 does not support 32 bits mode. "); + adac_deinit(); + return false; +#endif + // we need mclk for this DAC + *mck = true; + + // Initialize the chip + i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create(); + for (int i = 0; cs4265_init_sequence[i].reg != 0xff; i++) { + i2c_master_start(i2c_cmd); + i2c_master_write_byte(i2c_cmd, (cs4265_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(i2c_cmd, cs4265_init_sequence[i].reg, I2C_MASTER_NACK); + i2c_master_write_byte(i2c_cmd, cs4265_init_sequence[i].value, I2C_MASTER_NACK); + ESP_LOGD( + TAG, "i2c write %x at %u", cs4265_init_sequence[i].reg, cs4265_init_sequence[i].value); + } + + i2c_master_stop(i2c_cmd); + esp_err_t res = i2c_master_cmd_begin(cs4265.port, i2c_cmd, 500 / portTICK_RATE_MS); i2c_cmd_link_delete(i2c_cmd); + if (res != ESP_OK) { + ESP_LOGE(TAG, "could not intialize cs4265 %d", res); + return false; + } - if (res != ESP_OK) { - ESP_LOGE(TAG, "could not intialize cs4265 %d", res); - return false; - } - - return true; + return true; +} -} - -static esp_err_t cs4265_update_bit(uint8_t reg_no,uint8_t mask,uint8_t val ){ - esp_err_t ret=ESP_OK; - uint8_t old= adac_read_byte(cs4265_addr, reg_no); +static esp_err_t cs4265_update_bit(uint8_t reg_no, uint8_t mask, uint8_t val) { + esp_err_t ret = ESP_OK; + uint8_t old = adac_read_byte(cs4265_addr, reg_no); uint8_t newval = (old & ~mask) | (val & mask); - bool change = old != newval; - if (change){ - ret = adac_write_byte(cs4265_addr, reg_no, newval); - if(ret != ESP_OK){ - ESP_LOGE(TAG,"Unable to change dac register 0x%02x [0x%02x->0x%02x] from value 0x%02x, mask 0x%02x ",reg_no,old,newval,val,mask); - } - else { - ESP_LOGD(TAG,"Changed dac register 0x%02x [0x%02x->0x%02x] from value 0x%02x, mask 0x%02x ",reg_no,old,newval,val,mask); - } - } - + bool change = old != newval; + if (change) { + ret = adac_write_byte(cs4265_addr, reg_no, newval); + if (ret != ESP_OK) { + ESP_LOGE(TAG, + "Unable to change dac register 0x%02x [0x%02x->0x%02x] from value 0x%02x, mask " + "0x%02x ", + reg_no, old, newval, val, mask); + } else { + ESP_LOGD(TAG, + "Changed dac register 0x%02x [0x%02x->0x%02x] from value 0x%02x, mask 0x%02x ", + reg_no, old, newval, val, mask); + } + } + return ret; } /**************************************************************************************** * change volume */ -static bool volume(unsigned left, unsigned right) { - return false; -} +static bool volume(unsigned left, unsigned right) { return false; } /**************************************************************************************** * power */ static void power(adac_power_e mode) { - switch(mode) { - case ADAC_STANDBY: - dac_cmd(cs4265_STANDBY); - break; - case ADAC_ON: - dac_cmd(cs4265_ACTIVE); - break; - case ADAC_OFF: - dac_cmd(cs4265_DOWN); - break; - default: - ESP_LOGW(TAG, "unknown DAC command"); - break; - } + switch (mode) { + case ADAC_STANDBY: + dac_cmd(cs4265_STANDBY); + break; + case ADAC_ON: + dac_cmd(cs4265_ACTIVE); + break; + case ADAC_OFF: + dac_cmd(cs4265_DOWN); + break; + default: + ESP_LOGW(TAG, "unknown DAC command"); + break; + } } /**************************************************************************************** * speaker */ static void speaker(bool active) { - if (active) dac_cmd(cs4265_ANALOGUE_ON); - else dac_cmd(cs4265_ANALOGUE_OFF); -} + if (active) + dac_cmd(cs4265_ANALOGUE_ON); + else + dac_cmd(cs4265_ANALOGUE_OFF); +} /**************************************************************************************** * headset */ -static void headset(bool active) { } - +static void headset(bool active) {} + /**************************************************************************************** * DAC specific commands */ void dac_cmd(dac_cmd_e cmd, ...) { - va_list args; - esp_err_t ret = ESP_OK; - - va_start(args, cmd); + va_list args; + esp_err_t ret = ESP_OK; - switch(cmd) { - case cs4265_VOLUME: - ESP_LOGE(TAG, "DAC volume not handled yet"); - break; + va_start(args, cmd); + + switch (cmd) { + case cs4265_VOLUME: + ESP_LOGE(TAG, "DAC volume not handled yet"); + break; case cs4265_ACTIVE: - ESP_LOGD(TAG, "Activating DAC"); - adac_write_byte(cs4265_addr, CS4265_PWRCTL,0); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXOFF,0); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXMUTE,0); - cs4265_update_bit(CS4265_DAC_CTL,CS4265_DAC_CTL_MUTE,0); - break; + ESP_LOGD(TAG, "Activating DAC"); + adac_write_byte(cs4265_addr, CS4265_PWRCTL, 0); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXOFF, 0); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXMUTE, 0); + cs4265_update_bit(CS4265_DAC_CTL, CS4265_DAC_CTL_MUTE, 0); + break; case cs4265_STANDBY: - ESP_LOGD(TAG, "DAC Stand-by"); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXOFF,CS4265_SPDIF_CTL2_TXOFF); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXMUTE,CS4265_SPDIF_CTL2_TXMUTE); - cs4265_update_bit(CS4265_DAC_CTL,CS4265_DAC_CTL_MUTE,CS4265_DAC_CTL_MUTE); - break; + ESP_LOGD(TAG, "DAC Stand-by"); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXOFF, CS4265_SPDIF_CTL2_TXOFF); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXMUTE, CS4265_SPDIF_CTL2_TXMUTE); + cs4265_update_bit(CS4265_DAC_CTL, CS4265_DAC_CTL_MUTE, CS4265_DAC_CTL_MUTE); + break; case cs4265_DOWN: - ESP_LOGD(TAG, "DAC Power Down"); - adac_write_byte(cs4265_addr, CS4265_PWRCTL,CS4265_PWRCTL_PDN_ALL); - break; + ESP_LOGD(TAG, "DAC Power Down"); + adac_write_byte(cs4265_addr, CS4265_PWRCTL, CS4265_PWRCTL_PDN_ALL); + break; case cs4265_ANALOGUE_OFF: - ESP_LOGD(TAG, "DAC Analog off"); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXOFF,CS4265_SPDIF_CTL2_TXOFF); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXMUTE,CS4265_SPDIF_CTL2_TXMUTE); - cs4265_update_bit(CS4265_DAC_CTL,CS4265_DAC_CTL_MUTE,CS4265_DAC_CTL_MUTE); - break; + ESP_LOGD(TAG, "DAC Analog off"); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXOFF, CS4265_SPDIF_CTL2_TXOFF); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXMUTE, CS4265_SPDIF_CTL2_TXMUTE); + cs4265_update_bit(CS4265_DAC_CTL, CS4265_DAC_CTL_MUTE, CS4265_DAC_CTL_MUTE); + break; case cs4265_ANALOGUE_ON: - ESP_LOGD(TAG, "DAC Analog on"); - adac_write_byte(cs4265_addr, CS4265_PWRCTL,0); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXOFF,0); - cs4265_update_bit(CS4265_SPDIF_CTL2,CS4265_SPDIF_CTL2_TXMUTE,0); - cs4265_update_bit(CS4265_DAC_CTL,CS4265_DAC_CTL_MUTE,0); - break; - } - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "could not use cs4265 %d", ret); - } - get_status(); - // now set the clock - ret=set_clock(cs4265.i2s_config,cs4265.i2c_port); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "could not set the cs4265's clock %d", ret); - } + ESP_LOGD(TAG, "DAC Analog on"); + adac_write_byte(cs4265_addr, CS4265_PWRCTL, 0); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXOFF, 0); + cs4265_update_bit(CS4265_SPDIF_CTL2, CS4265_SPDIF_CTL2_TXMUTE, 0); + cs4265_update_bit(CS4265_DAC_CTL, CS4265_DAC_CTL_MUTE, 0); + break; + } - va_end(args); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "could not use cs4265 %d", ret); + } + get_status(); + // now set the clock + ret = set_clock(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "could not set the cs4265's clock %d", ret); + } + + va_end(args); } /**************************************************************************************** * TAS57 detection */ static int cs4265_detect(void) { - uint8_t addr[] = {CS4265_PULL_DOWN,CS4265_PULL_UP}; - - for (int i = 0; i < sizeof(addr); i++) { - ESP_LOGI(TAG,"Looking for CS4265 @0x%x",addr[i]); - uint8_t reg=adac_read_byte(addr[i], CS4265_CHIP_ID); - if(reg==255){ - continue; - } - // found a device at that address - uint8_t devid = reg & CS4265_CHIP_ID_MASK; - if (devid != CS4265_CHIP_ID_VAL) { - ESP_LOGE(TAG,"CS4265 Device ID (%X). Expected %X",devid, CS4265_CHIP_ID); - return 0; - } - ESP_LOGI(TAG,"Found DAC @0x%x, Version %x",addr[i], reg & CS4265_REV_ID_MASK); - return addr[i]; - } - return 0; + uint8_t addr[] = {CS4265_PULL_DOWN, CS4265_PULL_UP}; + ESP_LOGD(TAG, "Detecting chip connection type/address"); + for (int i = 0; i < sizeof(addr); i++) { + ESP_LOGI(TAG, "Looking for CS4265 @0x%x", addr[i]); + uint8_t reg = adac_read_byte(addr[i], CS4265_CHIP_ID); + if (reg == 255) { + ESP_LOGD(TAG, "Nothing there"); + continue; + } + // found a device at that address + ESP_LOGD(TAG, "Found a device. Check signature"); + uint8_t devid = reg & CS4265_CHIP_ID_MASK; + if (devid != CS4265_CHIP_ID_VAL) { + ESP_LOGE(TAG, "CS4265 Device ID (%X). Expected %X", devid, CS4265_CHIP_ID); + return 0; + } + ESP_LOGI(TAG, "Found DAC @0x%x, Version %x", addr[i], reg & CS4265_REV_ID_MASK); + return addr[i]; + } + return 0; } - diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index a0ff1d95..a64eb10f 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -1,4 +1,4 @@ -/* +/* * Squeezelite for esp32 * * (c) Sebastien 2019 @@ -11,14 +11,16 @@ #include #ifdef ESP_PLATFORM +#include "Services.pb.h" +#include "Squeezelite.pb.h" #include "freertos/FreeRTOS.h" #include "freertos/timers.h" +extern sys_squeezelite_config* get_profile(const char* name); #endif -#include "Configurator.h" +#include "Config.h" #include "accessors.h" #include "squeezelite.h" - #if CONFIG_BT_SINK #include "bt_app_sink.h" static bool enable_bt_sink; @@ -34,91 +36,93 @@ static bool enable_cspot; static bool enable_airplay; #define RAOP_OUTPUT_SIZE (((RAOP_SAMPLE_RATE * BYTES_PER_FRAME * 2 * 120) / 100) & ~BYTES_PER_FRAME) -#define SYNC_WIN_SLOW 32 -#define SYNC_WIN_CHECK 8 -#define SYNC_WIN_FAST 2 +#define SYNC_WIN_SLOW 32 +#define SYNC_WIN_CHECK 8 +#define SYNC_WIN_FAST 2 -static raop_event_t raop_state; -static sys_Squeezelite * squeezelite; +static raop_event_t raop_state; +static sys_squeezelite_config* squeezelite; static EXT_RAM_ATTR struct { - bool enabled; - int sum, count, win, errors[SYNC_WIN_SLOW]; - s32_t len; - u32_t start_time, playtime; + bool enabled; + int sum, count, win, errors[SYNC_WIN_SLOW]; + s32_t len; + u32_t start_time, playtime; } raop_sync; #endif static enum { SINK_RUNNING, SINK_ABORT, SINK_DISCARD } sink_state; -#define LOCK_O mutex_lock(outputbuf->mutex) +#define LOCK_O mutex_lock(outputbuf->mutex) #define UNLOCK_O mutex_unlock(outputbuf->mutex) -#define LOCK_D mutex_lock(decode.mutex); +#define LOCK_D mutex_lock(decode.mutex); #define UNLOCK_D mutex_unlock(decode.mutex); enum { DECODE_BT = 1, DECODE_RAOP, DECODE_CSPOT }; extern struct outputstate output; extern struct decodestate decode; -extern struct buffer *outputbuf; +extern struct buffer* outputbuf; // this is the only system-wide loglevel variable extern log_level loglevel; /**************************************************************************************** * Common sink data handler */ -static uint32_t sink_data_handler(const uint8_t *data, uint32_t len, int retries) -{ +static uint32_t sink_data_handler(const uint8_t* data, uint32_t len, int retries) { size_t bytes, space; - uint32_t written = 0; - int wait = retries + 1; - - // would be better to lock output, but really, it does not matter - if (!output.external) { - LOG_SDEBUG("Cannot use external sink while LMS is controlling player"); - return 0; - } + uint32_t written = 0; + int wait = retries + 1; - LOCK_O; - if (sink_state == SINK_ABORT) sink_state = SINK_RUNNING; + // would be better to lock output, but really, it does not matter + if (!output.external) { + LOG_SDEBUG("Cannot use external sink while LMS is controlling player"); + return 0; + } - // there will always be room at some point - while (len && wait && sink_state == SINK_RUNNING) { - bytes = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / (BYTES_PER_FRAME / 4); - bytes = min(len, bytes); + LOCK_O; + if (sink_state == SINK_ABORT) sink_state = SINK_RUNNING; + + // there will always be room at some point + while (len && wait && sink_state == SINK_RUNNING) { + bytes = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / (BYTES_PER_FRAME / 4); + bytes = min(len, bytes); #if BYTES_PER_FRAME == 4 - memcpy(outputbuf->writep, data, bytes); + memcpy(outputbuf->writep, data, bytes); #else - { - s16_t *iptr = (s16_t*) data; - ISAMPLE_T *optr = (ISAMPLE_T *) outputbuf->writep; - size_t n = bytes / 2; - while (n--) *optr++ = *iptr++ << 16; - } -#endif - _buf_inc_writep(outputbuf, bytes * BYTES_PER_FRAME / 4); - space = _buf_space(outputbuf); + { + s16_t* iptr = (s16_t*)data; + ISAMPLE_T* optr = (ISAMPLE_T*)outputbuf->writep; + size_t n = bytes / 2; + while (n--) + *optr++ = *iptr++ << 16; + } +#endif + _buf_inc_writep(outputbuf, bytes * BYTES_PER_FRAME / 4); + space = _buf_space(outputbuf); - len -= bytes; - data += bytes; + len -= bytes; + data += bytes; written += bytes; - - // allow i2s to empty the buffer if needed - if (len && !space) { - if (!retries) break; - wait--; - UNLOCK_O; usleep(50000); LOCK_O; - } - } - if (!wait) { + // allow i2s to empty the buffer if needed + if (len && !space) { + if (!retries) break; + wait--; + UNLOCK_O; + usleep(50000); + LOCK_O; + } + } + + if (!wait) { // re-align the buffer according to what we threw away _buf_inc_writep(outputbuf, outputbuf->size - (BYTES_PER_FRAME - (len % BYTES_PER_FRAME))); - LOG_WARN("Waited too long, dropping frames %d", len); - } - + LOG_WARN("Waited too long, dropping frames %d", len); + } + UNLOCK_O; - + return written; } @@ -126,77 +130,77 @@ static uint32_t sink_data_handler(const uint8_t *data, uint32_t len, int retries * BT sink data handler */ #if CONFIG_BT_SINK -static void bt_sink_data_handler(const uint8_t *data, uint32_t len) { +static void bt_sink_data_handler(const uint8_t* data, uint32_t len) { sink_data_handler(data, len, 10); -} +} /**************************************************************************************** * BT sink command handler */ -static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) -{ - // don't LOCK_O as there is always a chance that LMS takes control later anyway - if (output.external != DECODE_BT && output.state > OUTPUT_STOPPED) { - LOG_WARN("Cannot use BT sink while LMS/AirPlay/CSpot are controlling player %d", output.external); - return false; - } +static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) { + // don't LOCK_O as there is always a chance that LMS takes control later anyway + if (output.external != DECODE_BT && output.state > OUTPUT_STOPPED) { + LOG_WARN("Cannot use BT sink while LMS/AirPlay/CSpot are controlling player %d", + output.external); + return false; + } - LOCK_D; + LOCK_D; - if (cmd != BT_SINK_VOLUME) LOCK_O; - - switch(cmd) { - case BT_SINK_AUDIO_STARTED: - _buf_flush(outputbuf); - _buf_limit(outputbuf, 0); - output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t); - output.external = DECODE_BT; - output.state = OUTPUT_STOPPED; - output.frames_played = 0; - if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; - LOG_INFO("BT sink started"); - break; - case BT_SINK_AUDIO_STOPPED: - if (output.external == DECODE_BT) { - if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; - output.external = 0; - output.stop_time = gettime_ms(); - LOG_INFO("BT sink stopped"); - } - break; - case BT_SINK_PLAY: - output.state = OUTPUT_RUNNING; - LOG_INFO("BT play"); - break; - case BT_SINK_STOP: - _buf_flush(outputbuf); - output.state = OUTPUT_STOPPED; - output.stop_time = gettime_ms(); - sink_state = SINK_ABORT; - LOG_INFO("BT stop"); - break; - case BT_SINK_PAUSE: - output.stop_time = gettime_ms(); - LOG_INFO("BT pause, just silence"); - break; - case BT_SINK_RATE: - output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t); - LOG_INFO("Setting BT sample rate %u", output.next_sample_rate); - break; - case BT_SINK_VOLUME: { - u32_t volume = va_arg(args, u32_t); - volume = 65536 * powf(volume / 128.0f, 3); - set_volume(volume, volume); - break; - default: - break; - } - } - - if (cmd != BT_SINK_VOLUME) UNLOCK_O; - UNLOCK_D; + if (cmd != BT_SINK_VOLUME) LOCK_O; - return true; + switch (cmd) { + case BT_SINK_AUDIO_STARTED: + _buf_flush(outputbuf); + _buf_limit(outputbuf, 0); + output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t); + output.external = DECODE_BT; + output.state = OUTPUT_STOPPED; + output.frames_played = 0; + if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; + LOG_INFO("BT sink started"); + break; + case BT_SINK_AUDIO_STOPPED: + if (output.external == DECODE_BT) { + if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; + output.external = 0; + output.stop_time = gettime_ms(); + LOG_INFO("BT sink stopped"); + } + break; + case BT_SINK_PLAY: + output.state = OUTPUT_RUNNING; + LOG_INFO("BT play"); + break; + case BT_SINK_STOP: + _buf_flush(outputbuf); + output.state = OUTPUT_STOPPED; + output.stop_time = gettime_ms(); + sink_state = SINK_ABORT; + LOG_INFO("BT stop"); + break; + case BT_SINK_PAUSE: + output.stop_time = gettime_ms(); + LOG_INFO("BT pause, just silence"); + break; + case BT_SINK_RATE: + output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t); + LOG_INFO("Setting BT sample rate %u", output.next_sample_rate); + break; + case BT_SINK_VOLUME: { + u32_t volume = va_arg(args, u32_t); + volume = 65536 * powf(volume / 128.0f, 3); + set_volume(volume, volume); + break; + default: + break; + } + } + + if (cmd != BT_SINK_VOLUME) UNLOCK_O; + UNLOCK_D; + + return true; } #endif @@ -204,144 +208,154 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) * raop sink data handler */ #if CONFIG_AIRPLAY_SINK -static void raop_sink_data_handler(const uint8_t *data, uint32_t len, u32_t playtime) { - - raop_sync.playtime = playtime; - raop_sync.len = len; +static void raop_sink_data_handler(const uint8_t* data, uint32_t len, u32_t playtime) { - sink_data_handler(data, len, 10); -} + raop_sync.playtime = playtime; + raop_sync.len = len; + + sink_data_handler(data, len, 10); +} /**************************************************************************************** * AirPlay sink command handler */ -static bool raop_sink_cmd_handler(raop_event_t event, va_list args) -{ - // don't LOCK_O as there is always a chance that LMS takes control later anyway - if (output.external != DECODE_RAOP && output.state > OUTPUT_STOPPED) { - LOG_WARN("Cannot use Airplay sink while LMS/BT/CSpot are controlling player %d", output.external); - return false; - } +static bool raop_sink_cmd_handler(raop_event_t event, va_list args) { + // don't LOCK_O as there is always a chance that LMS takes control later anyway + if (output.external != DECODE_RAOP && output.state > OUTPUT_STOPPED) { + LOG_WARN("Cannot use Airplay sink while LMS/BT/CSpot are controlling player %d", + output.external); + return false; + } - LOCK_D; - - if (event != RAOP_VOLUME) LOCK_O; - - // this is async, so player might have been deleted - switch (event) { - case RAOP_TIMING: { - if (!raop_sync.enabled || output.state != OUTPUT_RUNNING || output.frames_played_dmp < output.device_frames) break; + LOCK_D; - u32_t ms, now = gettime_ms(); - u32_t level = _buf_used(outputbuf); - int error; - - // in how many ms will the most recent block play - ms = (((s32_t)(level - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + output.frames_in_process) * 10) / (RAOP_SAMPLE_RATE / 100) - (s32_t) (now - output.updated); - - // when outputbuf is empty, it means we have a network black-out or something - error = level ? (raop_sync.playtime - now) - ms : 0; - - if (loglevel == lDEBUG || !level) { - LOG_INFO("head local:%d, remote:%d (delta:%d)", ms, raop_sync.playtime - now, error); - LOG_INFO("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process); - } - - // calculate sum, error and update sliding window - raop_sync.errors[raop_sync.count++ % raop_sync.win] = error; - raop_sync.sum += error; - error = raop_sync.sum / min(raop_sync.count, raop_sync.win); + if (event != RAOP_VOLUME) LOCK_O; - // wait till we have enough data or there is a strong deviation - if ((raop_sync.count >= raop_sync.win && abs(error) > 10) || (raop_sync.count >= SYNC_WIN_CHECK && abs(error) > 100)) { - if (error < 0) { - output.skip_frames = -(error * RAOP_SAMPLE_RATE) / 1000; - output.state = OUTPUT_SKIP_FRAMES; - LOG_INFO("skipping %u frames (count:%d)", output.skip_frames, raop_sync.count); - } else { - output.pause_frames = (error * RAOP_SAMPLE_RATE) / 1000; - output.state = OUTPUT_PAUSE_FRAMES; - LOG_INFO("pausing for %u frames (count: %d)", output.pause_frames, raop_sync.count); - } - - raop_sync.sum = raop_sync.count = 0; - memset(raop_sync.errors, 0, sizeof(raop_sync.errors)); - } - - // move to normal mode if possible - if (raop_sync.win == 1) { - raop_sync.win = SYNC_WIN_FAST; - LOG_INFO("backend played %u, desired %u, (delta:%d)", ms, raop_sync.playtime - now, error); - } else if (raop_sync.win == SYNC_WIN_FAST && raop_sync.count >= SYNC_WIN_FAST && abs(error) < 10) { - raop_sync.win = SYNC_WIN_SLOW; - LOG_INFO("switching to slow sync mode %u", raop_sync.win); - } + // this is async, so player might have been deleted + switch (event) { + case RAOP_TIMING: { + if (!raop_sync.enabled || output.state != OUTPUT_RUNNING || + output.frames_played_dmp < output.device_frames) + break; - break; - } - case RAOP_SETUP: { - uint8_t **buffer = va_arg(args, uint8_t**); - size_t *size = va_arg(args, size_t*); + u32_t ms, now = gettime_ms(); + u32_t level = _buf_used(outputbuf); + int error; - // steal buffer tail from outputbuf but do not reallocate - *size = _buf_limit(outputbuf, RAOP_OUTPUT_SIZE); - *buffer = outputbuf->writep + RAOP_OUTPUT_SIZE; + // in how many ms will the most recent block play + ms = (((s32_t)(level - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + + output.frames_in_process) * + 10) / + (RAOP_SAMPLE_RATE / 100) - + (s32_t)(now - output.updated); - output.frames_played = 0; - output.external = DECODE_RAOP; - output.state = OUTPUT_STOPPED; - if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; - LOG_INFO("resizing buffer %u", outputbuf->size); - break; - } - case RAOP_STREAM: - LOG_INFO("Stream", NULL); - raop_state = event; - raop_sync.win = 1; - raop_sync.sum = raop_sync.count = 0; - memset(raop_sync.errors, 0, sizeof(raop_sync.errors)); - raop_sync.enabled = !strcasestr(output.device, "BT"); - output.next_sample_rate = output.current_sample_rate = RAOP_SAMPLE_RATE; - break; - case RAOP_STALLED: - case RAOP_STOP: - output.external = 0; - __attribute__ ((fallthrough)); - case RAOP_FLUSH: - LOG_INFO("%s", event == RAOP_FLUSH ? "Flush" : "Stop"); - _buf_flush(outputbuf); - raop_state = event; - if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; - sink_state = SINK_ABORT; - output.frames_played = 0; - output.stop_time = gettime_ms(); - break; - case RAOP_PLAY: { - LOG_INFO("Play", NULL); - if (raop_state != RAOP_PLAY) { - output.state = OUTPUT_START_AT; - output.start_at = va_arg(args, u32_t); - raop_sync.start_time = output.start_at; - LOG_INFO("Starting at %u (in %d ms)", output.start_at, output.start_at - gettime_ms()); - } - raop_state = event; - break; - } - case RAOP_VOLUME: { - float volume = va_arg(args, double); - LOG_INFO("Volume[0..1] %0.4f", volume); - volume = 65536 * powf(volume, 3); - set_volume(volume, volume); - break; - } - default: - break; - } - - if (event != RAOP_VOLUME) UNLOCK_O; - - UNLOCK_D; - return true; + // when outputbuf is empty, it means we have a network black-out or something + error = level ? (raop_sync.playtime - now) - ms : 0; + + if (loglevel == lDEBUG || !level) { + LOG_INFO("head local:%d, remote:%d (delta:%d)", ms, raop_sync.playtime - now, error); + LOG_INFO("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), + raop_sync.len, output.device_frames, output.frames_in_process); + } + + // calculate sum, error and update sliding window + raop_sync.errors[raop_sync.count++ % raop_sync.win] = error; + raop_sync.sum += error; + error = raop_sync.sum / min(raop_sync.count, raop_sync.win); + + // wait till we have enough data or there is a strong deviation + if ((raop_sync.count >= raop_sync.win && abs(error) > 10) || + (raop_sync.count >= SYNC_WIN_CHECK && abs(error) > 100)) { + if (error < 0) { + output.skip_frames = -(error * RAOP_SAMPLE_RATE) / 1000; + output.state = OUTPUT_SKIP_FRAMES; + LOG_INFO("skipping %u frames (count:%d)", output.skip_frames, raop_sync.count); + } else { + output.pause_frames = (error * RAOP_SAMPLE_RATE) / 1000; + output.state = OUTPUT_PAUSE_FRAMES; + LOG_INFO("pausing for %u frames (count: %d)", output.pause_frames, raop_sync.count); + } + + raop_sync.sum = raop_sync.count = 0; + memset(raop_sync.errors, 0, sizeof(raop_sync.errors)); + } + + // move to normal mode if possible + if (raop_sync.win == 1) { + raop_sync.win = SYNC_WIN_FAST; + LOG_INFO( + "backend played %u, desired %u, (delta:%d)", ms, raop_sync.playtime - now, error); + } else if (raop_sync.win == SYNC_WIN_FAST && raop_sync.count >= SYNC_WIN_FAST && + abs(error) < 10) { + raop_sync.win = SYNC_WIN_SLOW; + LOG_INFO("switching to slow sync mode %u", raop_sync.win); + } + + break; + } + case RAOP_SETUP: { + uint8_t** buffer = va_arg(args, uint8_t**); + size_t* size = va_arg(args, size_t*); + + // steal buffer tail from outputbuf but do not reallocate + *size = _buf_limit(outputbuf, RAOP_OUTPUT_SIZE); + *buffer = outputbuf->writep + RAOP_OUTPUT_SIZE; + + output.frames_played = 0; + output.external = DECODE_RAOP; + output.state = OUTPUT_STOPPED; + if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; + LOG_INFO("resizing buffer %u", outputbuf->size); + break; + } + case RAOP_STREAM: + LOG_INFO("Stream", NULL); + raop_state = event; + raop_sync.win = 1; + raop_sync.sum = raop_sync.count = 0; + memset(raop_sync.errors, 0, sizeof(raop_sync.errors)); + raop_sync.enabled = !strcasestr(output.device, "BT"); + output.next_sample_rate = output.current_sample_rate = RAOP_SAMPLE_RATE; + break; + case RAOP_STALLED: + case RAOP_STOP: + output.external = 0; + __attribute__((fallthrough)); + case RAOP_FLUSH: + LOG_INFO("%s", event == RAOP_FLUSH ? "Flush" : "Stop"); + _buf_flush(outputbuf); + raop_state = event; + if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; + sink_state = SINK_ABORT; + output.frames_played = 0; + output.stop_time = gettime_ms(); + break; + case RAOP_PLAY: { + LOG_INFO("Play", NULL); + if (raop_state != RAOP_PLAY) { + output.state = OUTPUT_START_AT; + output.start_at = va_arg(args, u32_t); + raop_sync.start_time = output.start_at; + LOG_INFO("Starting at %u (in %d ms)", output.start_at, output.start_at - gettime_ms()); + } + raop_state = event; + break; + } + case RAOP_VOLUME: { + float volume = va_arg(args, double); + LOG_INFO("Volume[0..1] %0.4f", volume); + volume = 65536 * powf(volume, 3); + set_volume(volume, volume); + break; + } + default: + break; + } + + if (event != RAOP_VOLUME) UNLOCK_O; + + UNLOCK_D; + return true; } #endif @@ -349,98 +363,98 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) * cspot sink data handler */ #if CONFIG_CSPOT_SINK -static uint32_t cspot_sink_data_handler(const uint8_t *data, uint32_t len) { +static uint32_t cspot_sink_data_handler(const uint8_t* data, uint32_t len) { return sink_data_handler(data, len, 0); -} +} /**************************************************************************************** * cspot sink command handler */ -static bool cspot_cmd_handler(cspot_event_t cmd, va_list args) -{ - // don't LOCK_O as there is always a chance that LMS takes control later anyway - if (output.external != DECODE_CSPOT && output.state > OUTPUT_STOPPED) { - LOG_WARN("Cannot use CSpot sink while LMS/BT/Airplay are controlling player %d", output.external); - return false; - } +static bool cspot_cmd_handler(cspot_event_t cmd, va_list args) { + // don't LOCK_O as there is always a chance that LMS takes control later anyway + if (output.external != DECODE_CSPOT && output.state > OUTPUT_STOPPED) { + LOG_WARN("Cannot use CSpot sink while LMS/BT/Airplay are controlling player %d", + output.external); + return false; + } - LOCK_D; - - if (cmd != CSPOT_VOLUME) LOCK_O; + LOCK_D; - switch(cmd) { - case CSPOT_START: - output.current_sample_rate = output.next_sample_rate = va_arg(args, u32_t); - output.external = DECODE_CSPOT; - output.frames_played = 0; + if (cmd != CSPOT_VOLUME) LOCK_O; + + switch (cmd) { + case CSPOT_START: + output.current_sample_rate = output.next_sample_rate = va_arg(args, u32_t); + output.external = DECODE_CSPOT; + output.frames_played = 0; // in 1/10 of seconds output.threshold = 25; - output.state = OUTPUT_STOPPED; + output.state = OUTPUT_STOPPED; sink_state = SINK_ABORT; - _buf_flush(outputbuf); - if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; - LOG_INFO("CSpot start track"); - break; - case CSPOT_DISC: - _buf_flush(outputbuf); - sink_state = SINK_ABORT; - output.external = 0; - output.state = OUTPUT_STOPPED; - output.stop_time = gettime_ms(); - LOG_INFO("CSpot disconnected"); - break; - case CSPOT_PLAY: - sink_state = SINK_RUNNING; - output.state = OUTPUT_RUNNING; - LOG_INFO("CSpot play"); - break; - case CSPOT_SEEK: - _buf_flush(outputbuf); - sink_state = SINK_ABORT; - LOG_INFO("CSpot seek by %d", va_arg(args, uint32_t)); - break; - case CSPOT_FLUSH: - _buf_flush(outputbuf); - sink_state = SINK_DISCARD; - output.state = OUTPUT_STOPPED; - LOG_INFO("CSpot flush"); - break; - case CSPOT_PAUSE: - output.state = OUTPUT_STOPPED; - output.stop_time = gettime_ms(); - LOG_INFO("CSpot pause"); - break; + _buf_flush(outputbuf); + if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; + LOG_INFO("CSpot start track"); + break; + case CSPOT_DISC: + _buf_flush(outputbuf); + sink_state = SINK_ABORT; + output.external = 0; + output.state = OUTPUT_STOPPED; + output.stop_time = gettime_ms(); + LOG_INFO("CSpot disconnected"); + break; + case CSPOT_PLAY: + sink_state = SINK_RUNNING; + output.state = OUTPUT_RUNNING; + LOG_INFO("CSpot play"); + break; + case CSPOT_SEEK: + _buf_flush(outputbuf); + sink_state = SINK_ABORT; + LOG_INFO("CSpot seek by %d", va_arg(args, uint32_t)); + break; + case CSPOT_FLUSH: + _buf_flush(outputbuf); + sink_state = SINK_DISCARD; + output.state = OUTPUT_STOPPED; + LOG_INFO("CSpot flush"); + break; + case CSPOT_PAUSE: + output.state = OUTPUT_STOPPED; + output.stop_time = gettime_ms(); + LOG_INFO("CSpot pause"); + break; case CSPOT_TRACK_MARK: output.track_start = outputbuf->writep; break; case CSPOT_QUERY_REMAINING: { - uint32_t *remaining = va_arg(args, uint32_t*); + uint32_t* remaining = va_arg(args, uint32_t*); *remaining = (_buf_used(outputbuf) * 1000) / (output.current_sample_rate * BYTES_PER_FRAME); - break; + break; } case CSPOT_QUERY_STARTED: { - uint32_t *started = va_arg(args, uint32_t*); + uint32_t* started = va_arg(args, uint32_t*); *started = output.track_started; // this is a read_and_clear event output.track_started = false; - break; + break; } - case CSPOT_VOLUME: { - u32_t volume = va_arg(args, u32_t); - LOG_INFO("CSpot volume %u", volume); - volume = 65536 * powf(volume / 65536.0f, 4); - set_volume(volume, volume); - break; - default: - break; - } - } - - if (cmd != CSPOT_VOLUME) UNLOCK_O; - UNLOCK_D; - - return true; + case CSPOT_VOLUME: { + u32_t volume = va_arg(args, u32_t); + LOG_INFO("CSpot volume %u", volume); + volume = 65536 * powf(volume / 65536.0f, 4); + set_volume(volume, volume); + break; + default: + break; + } + } + + if (cmd != CSPOT_VOLUME) UNLOCK_O; + UNLOCK_D; + + return true; } #endif @@ -448,80 +462,79 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args) * We provide the generic codec register option */ void register_external(void) { - sys_BluetoothSink * bt_sink; - sys_AirPlay * airplay; - sys_Spotify * spotify; + squeezelite = get_profile(NULL); // get the active profile #if CONFIG_BT_SINK - enable_bt_sink= (SYS_SERVICES_BTSINK(bt_sink) && bt_sink->enabled); - if ( enable_bt_sink) { - #pragma message ("Is the BT sink logic correct?") - if(SYS_SERVICES_SQUEEZELITE(squeezelite) && squeezelite->output_type == sys_OutputTypeEnum_OUTPUT_Bluetooth ){ - LOG_ERROR("BT Sink cannot be enabled with Bluetooth output"); - } - else { - bt_sink_init(bt_sink_cmd_handler, bt_sink_data_handler); - } - } -#endif + sys_services_bt_sink* bt_sink; + enable_bt_sink = (sys_services_config_BTSINK(bt_sink) && bt_sink->enabled); + if (enable_bt_sink && squeezelite) { +#pragma message("Is the BT sink logic correct?") + if (squeezelite->output_type == sys_squeezelite_outputs_BT) { + LOG_ERROR("BT Sink cannot be enabled with Bluetooth output"); + } else { + bt_sink_init(bt_sink_cmd_handler, bt_sink_data_handler); + } + } +#endif #if CONFIG_AIRPLAY_SINK - enable_airplay = SYS_SERVICES_AIRPLAY(airplay) && airplay->enabled; - if (enable_airplay){ - raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler); - LOG_INFO("Initializing AirPlay sink"); - } - -#endif - -#if CONFIG_CSPOT_SINK - enable_cspot = SYS_SERVICES_SPOTIFY(spotify) && spotify->enabled; - if (enable_cspot){ - cspot_sink_init(cspot_cmd_handler, cspot_sink_data_handler); - LOG_INFO("Initializing CSpot sink"); - } -#endif + sys_airplay_config* airplay; + enable_airplay = sys_services_config_AIRPLAY(airplay) && airplay->enabled; + if (enable_airplay) { + raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler); + LOG_INFO("Initializing AirPlay sink"); + } +#endif + +#if CONFIG_CSPOT_SINK + sys_spotify_config* spotify; + enable_cspot = sys_services_config_SPOTIFY(spotify) && spotify->enabled; + if (enable_cspot) { + cspot_sink_init(cspot_cmd_handler, cspot_sink_data_handler); + LOG_INFO("Initializing CSpot sink"); + } +#endif } void deregister_external(void) { #if CONFIG_BT_SINK - sys_Squeezelite * squeezelite; - if(SYS_SERVICES_SQUEEZELITE(squeezelite) && squeezelite->output_type != sys_OutputTypeEnum_OUTPUT_Bluetooth && enable_bt_sink ){ - bt_sink_deinit(); - } + squeezelite = get_profile(NULL); // get the active profile + if (squeezelite && squeezelite->output_type == sys_squeezelite_outputs_BT && enable_bt_sink) { + bt_sink_deinit(); + } #endif #if CONFIG_AIRPLAY_SINK - if (enable_airplay){ - LOG_INFO("Stopping AirPlay sink"); - raop_sink_deinit(); - } + if (enable_airplay) { + LOG_INFO("Stopping AirPlay sink"); + raop_sink_deinit(); + } #endif #if CONFIG_CSPOT_SINK - if (enable_cspot){ - LOG_INFO("Stopping CSpot sink"); - cspot_sink_deinit(); - } + if (enable_cspot) { + LOG_INFO("Stopping CSpot sink"); + cspot_sink_deinit(); + } #endif } void decode_restore(int external) { - switch (external) { -#if CONFIG_BT_SINK - case DECODE_BT: - bt_disconnect(); - break; + switch (external) { +#if CONFIG_BT_SINK + case DECODE_BT: + bt_disconnect(); + break; #endif #if CONFIG_AIRPLAY_SINK - case DECODE_RAOP: - raop_disconnect(); - break; + case DECODE_RAOP: + raop_disconnect(); + break; #endif #if CONFIG_CSPOT_SINK - case DECODE_CSPOT: - cspot_disconnect(); - break; -#endif - } + case DECODE_CSPOT: + cspot_disconnect(); + break; +#endif + } } diff --git a/components/squeezelite/embedded.c b/components/squeezelite/embedded.c index b2156c08..25046a46 100644 --- a/components/squeezelite/embedded.c +++ b/components/squeezelite/embedded.c @@ -17,13 +17,13 @@ #include "esp_wifi.h" #include "esp_log.h" #include "monitor.h" -#include "Configurator.h" +#include "Config.h" #include "messaging.h" #include "gpio_exp.h" #include "accessors.h" static const char TAG[] = "embedded"; -static sys_GPIO * power=NULL; +static sys_gpio_config * power=NULL; extern void sb_controls_init(void); extern bool sb_displayer_init(void); @@ -69,7 +69,9 @@ uint32_t _gettime_ms_(void) { int embedded_init(void) { mutex_create(slimp_mutex); + ESP_LOGI(TAG,"Initializing controls"); sb_controls_init(); + ESP_LOGI(TAG,"Initializing displayer"); custom_player_id = sb_displayer_init() ? 100 : 101; @@ -88,10 +90,11 @@ void embedded_exit(int code) { } void powering(bool on) { - if (power->pin != -1) { + if (SYS_GPIOS_NAME(power,power) && power->pin != -1) { ESP_LOGI(TAG, "powering player %s", on ? "ON" : "OFF"); gpio_set_level_x(power->pin, on ? power->level : !power->level); } + } u16_t get_RSSI(void) { diff --git a/components/squeezelite/equalizer.c b/components/squeezelite/equalizer.c index fec2e60c..144c7abf 100644 --- a/components/squeezelite/equalizer.c +++ b/components/squeezelite/equalizer.c @@ -9,7 +9,7 @@ */ #include "math.h" -#include "Configurator.h" +#include "Config.h" #include "squeezelite.h" #include "equalizer.h" #include "esp_equalizer.h" @@ -24,7 +24,7 @@ static EXT_RAM_ATTR struct { float volume; float loudness_gain[EQ_BANDS]; bool update; - sys_Equalizer *state; + sys_equalizer_config *state; } equalizer; @@ -83,19 +83,18 @@ static void calculate_loudness(void) { * initialize equalizer */ void equalizer_init(void) { - sys_Services * services; - sys_Equalizer blank_eq = sys_Equalizer_init_default; - + sys_services_config * services; + sys_equalizer_config blank_eq = sys_equalizer_config_init_default; equalizer.state = &sys_state->equalizer; if(!sys_state->has_equalizer ){ sys_state->has_equalizer = true; - if(SYS_SERVICES(services) && services->has_equalizer){ - memcpy(equalizer.state,&services->equalizer,sizeof(sys_Equalizer)); + if(sys_services_config(services) && services->has_equalizer){ + memcpy(equalizer.state,&services->equalizer,sizeof(sys_equalizer_config)); } else { - memcpy(equalizer.state,&blank_eq,sizeof(sys_Equalizer)); + memcpy(equalizer.state,&blank_eq,sizeof(sys_equalizer_config)); } - configurator_raise_state_changed(); + config_raise_state_changed(); } } @@ -160,7 +159,7 @@ void equalizer_set_gain(int8_t *gain) { // update only if something changed if (!memcmp(&equalizer.state->gains, gain, EQ_BANDS)) { equalizer.update = true; - configurator_raise_state_changed(); + config_raise_state_changed(); } LOG_INFO("equalizer gain %s", config); @@ -178,7 +177,7 @@ void equalizer_set_loudness(uint8_t loudness) { // update loudness gains as a factor of loudness and volume if (equalizer.state->loudness != loudness / 10.0) { equalizer.state->loudness = loudness / 10.0; - configurator_raise_state_changed(); + config_raise_state_changed(); calculate_loudness(); equalizer.update = true; } diff --git a/components/squeezelite/esp32_main.c b/components/squeezelite/esp32_main.c index fc3fe4b1..f7e938af 100644 --- a/components/squeezelite/esp32_main.c +++ b/components/squeezelite/esp32_main.c @@ -1,34 +1,20 @@ /* - * Squeezelite - lightweight headless squeezebox emulator + * Squeezelite for esp32 * - * (c) Adrian Smith 2012-2015, triode1@btinternet.com - * Ralph Irving 2015-2017, ralph_irving@hotmail.com + * (c) Sebastien 2024 + * Philippe G. 2024, philippe_44@outlook.com * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additions (c) Paul Hermann, 2015-2017 under the same license terms - * -Control of Raspberry pi GPIO for amplifier power - * -Launch script on power status change from LMS */ - +#include "Config.h" #include "squeezelite.h" #include -#include "Configurator.h" extern bool user_rates; static unsigned int rates[MAX_SUPPORTED_SAMPLERATES] = {0}; -sys_Squeezelite* config; +sys_squeezelite_config* config; log_level loglevel = lDEBUG; static void sighandler(int signum) { slimproto_stop(); @@ -38,8 +24,8 @@ static void sighandler(int signum) { } unsigned int* get_rates() { - unsigned int ref[] TEST_RATES; - sys_RatesOption* ratescfg = &config->rates; + unsigned int ref[] TEST_RATES; + sys_squeezelite_rates_opt* ratescfg = &config->rates; if (!config->has_rates || ((ratescfg->list_count == 0 || ratescfg->list[0] == 0) && ratescfg->min == 0 && ratescfg->max == 0)) { user_rates = false; @@ -71,73 +57,105 @@ unsigned int* get_rates() { user_rates = true; return rates; } -log_level log_level_from_sys_level(sys_DebugLevelEnum level) { +log_level log_level_from_sys_level(sys_squeezelite_debug_levels level) { switch (level) { - case sys_DebugLevelEnum_DEFAULT: + case sys_squeezelite_debug_levels_DEFAULT: return lWARN; break; - case sys_DebugLevelEnum_INFO: + case sys_squeezelite_debug_levels_INFO: return lINFO; break; - case sys_DebugLevelEnum_ERROR: + case sys_squeezelite_debug_levels_ERROR: return lERROR; break; - case sys_DebugLevelEnum_WARN: + case sys_squeezelite_debug_levels_WARN: return lWARN; break; - case sys_DebugLevelEnum_DEBUG: + case sys_squeezelite_debug_levels_DEBUG: return lDEBUG; break; - case sys_DebugLevelEnum_SDEBUG: + case sys_squeezelite_debug_levels_SDEBUG: return lSDEBUG; break; default: return lWARN; } } -void build_codec_string(sys_CodexEnum* list, size_t count, char* buffer, size_t buf_size) { - const char* prefix = STR(sys_CodexEnum) "_c_"; +void build_codec_string(sys_squeezelite_codecs* list, size_t count, char* buffer, size_t buf_size) { + const char* prefix = STR(sys_squeezelite_codecs) "_c_"; const char* name = NULL; for (int i = 0; i < count; i++) { if (i > 0) { strncat(buffer, ", ", buf_size); } - name = sys_CodexEnum_name(list[i]) + strlen(prefix); + name = sys_squeezelite_codecs_name(list[i]) + strlen(prefix); LOG_INFO("Found codec: %s ", name); strncat(buffer, name, buf_size); } LOG_INFO("Codec list: %s ", buffer); } + +sys_squeezelite_config* get_profile(const char* name) { + const char* resolved_name = name && strlen(name) > 0 ? name : platform->services.current_profile; + LOG_DEBUG("get_profile called with name: %s, resolved to: %s", + name ? name : "NULL", + resolved_name ? resolved_name : "NULL or EMPTY"); + + if (!platform->has_services || platform->services.squeezelite_profiles_count <= 0) { + LOG_ERROR("No squeezelite profiles available"); + return NULL; + } + + if (!resolved_name || strlen(resolved_name) == 0) { + LOG_WARN("No specific profile requested, using the first available profile"); + return &platform->services.squeezelite_profiles[0].profile; + } + + for (int i = 0; i < platform->services.squeezelite_profiles_count; i++) { + LOG_DEBUG("Checking profile: %s", platform->services.squeezelite_profiles[i].name); + if (strcmp(platform->services.squeezelite_profiles[i].name, resolved_name) == 0) { + LOG_DEBUG("Profile matched: %s", platform->services.squeezelite_profiles[i].name); + return &platform->services.squeezelite_profiles[i].profile; + } + } + if(platform->services.squeezelite_profiles[0].name && strlen(platform->services.squeezelite_profiles[0].name)>0){ + LOG_WARN("Could not find profile %s. Falling back to %s", resolved_name,platform->services.squeezelite_profiles[0].name); + return &platform->services.squeezelite_profiles[0].profile; + } + + LOG_ERROR("Profile '%s' not found", resolved_name); + return NULL; +} + int squeezelite_main_start() { u8_t mac[6]; unsigned output_buf_size = 0; + LOG_INFO("Starting squeezelite"); char include_codecs[101] = {0}; char exclude_codecs[101] = {0}; - config = platform->has_services && platform->services.has_squeezelite - ? &platform->services.squeezelite - : NULL; + config = get_profile(NULL); // get the active profile if (!config) { LOG_ERROR("Squeezelite not configured"); - return -1; + return -2; } - + LOG_INFO("Running embedded init"); int err = embedded_init(); if (err) return err; get_mac(mac); - unsigned int * rates = get_rates(); + unsigned int* rates = get_rates(); - signal(SIGINT, sighandler); - signal(SIGTERM, sighandler); - #if defined(SIGQUIT) - signal(SIGQUIT, sighandler); - #endif - #if defined(SIGHUP) - signal(SIGHUP, sighandler); - #endif - output_buf_size = config->buffers.output; + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); +#if defined(SIGQUIT) + signal(SIGQUIT, sighandler); +#endif +#if defined(SIGHUP) + signal(SIGHUP, sighandler); +#endif + output_buf_size = config->buffers.output*1024; - // set the output buffer size if not specified on the command line, take account of resampling - if (!output_buf_size) { + // set the output buffer size if not specified in the parameters, take account of resampling + if (output_buf_size == 0) { output_buf_size = OUTPUTBUF_SIZE; if (strlen(config->resample) > 0) { unsigned scale = 8; @@ -151,32 +169,37 @@ int squeezelite_main_start() { } build_codec_string(config->excluded_codex, config->excluded_codex_count, exclude_codecs, sizeof(exclude_codecs)); - build_codec_string( - config->included_codex, config->included_codex, include_codecs, sizeof(include_codecs)); + build_codec_string(config->included_codex, config->included_codex_count, include_codecs, + sizeof(include_codecs)); - unsigned int stream_buf_size = - config->buffers.stream > 0 ? config->buffers.stream : STREAMBUF_SIZE; - stream_init( - log_level_from_sys_level(platform->services.squeezelite.log.stream), stream_buf_size); + unsigned int stream_buf_size =STREAMBUF_SIZE; + if(config->buffers.stream > 0){ + stream_buf_size = config->buffers.stream *1024; + LOG_DEBUG("Found stream buffer configuration: %d (%d)",config->buffers.stream,stream_buf_size); + } + else { + LOG_DEBUG("Using default stream buffer: %d",stream_buf_size); + } + stream_init(log_level_from_sys_level(config->log.stream), stream_buf_size); output_init_embedded(); - decode_init(log_level_from_sys_level(platform->services.squeezelite.log.decode), include_codecs, - exclude_codecs); + decode_init(log_level_from_sys_level(config->log.decode), + strlen(include_codecs) > 0 ? include_codecs : NULL, exclude_codecs); #if RESAMPLE || RESAMPLE16 - if (strlen(config->resample) > 0) { + if (config->resample && strlen(config->resample) > 0) { process_init(config->resample); } #endif if (!config->enabled) { - LOG_ERROR("LMS is disabled"); + LOG_WARN("LMS is disabled"); while (1) sleep(3600); } char* name = strlen(platform->names.squeezelite) > 0 ? platform->names.squeezelite : platform->names.device; - slimproto(log_level_from_sys_level(platform->services.squeezelite.log.slimproto), - config->server_name_ip, mac, name, NULL, NULL, config->max_rate); + slimproto(log_level_from_sys_level(config->log.slimproto), config->server_name_ip, mac, name, + NULL, NULL, config->max_rate); decode_close(); stream_close(); diff --git a/components/squeezelite/external/dac_external.c b/components/squeezelite/external/dac_external.c index 4bce7173..55f3f854 100644 --- a/components/squeezelite/external/dac_external.c +++ b/components/squeezelite/external/dac_external.c @@ -1,4 +1,4 @@ -/* +/* * Squeezelite for esp32 * * (c) Sebastien 2019 @@ -8,18 +8,19 @@ * https://opensource.org/licenses/MIT * */ - -#include -#include -#include +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "Config.h" +#include "adac.h" +#include "cJSON.h" #include "driver/i2c.h" #include "esp_log.h" +#include "esp_check.h" #include "gpio_exp.h" -#include "cJSON.h" +#include "inttypes.h" #include "string.h" -// #include "Configurator.h" -#pragma message("fixme: look for TODO below") -#include "adac.h" +#include +#include +#include static const char TAG[] = "DAC external"; @@ -27,159 +28,167 @@ static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right) { return false; } static void power(adac_power_e mode); -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck); +static bool init(sys_dac_config* config, i2s_config_t* i2s_config, bool* mck); -static bool i2c_json_execute(char *set); +// static bool i2c_json_execute(char *set); +static bool i2c_execute_cmd(sys_dac_control_type cmd_type); -const struct adac_s dac_external = { sys_DACModelEnum_I2S, init, adac_deinit, power, speaker, headset, volume }; -static cJSON *i2c_json; +const struct adac_s dac_external = {sys_dac_models_I2S, init, adac_deinit, power, speaker, headset, volume}; static int i2c_addr; - -static const struct { - char *model; - bool mclk; - char *controlset; -} codecs[] = { - { "es8388", true, - "{\"init\":[ \ - {\"reg\":8,\"val\":0}, {\"reg\":2,\"val\":243}, {\"reg\":43,\"val\":128}, {\"reg\":0,\"val\":5}, \ - {\"reg\":1,\"val\":64}, {\"reg\":4,\"val\":60}," -#if BYTES_PER_FRAME == 8 - "{\"reg\":23,\"val\":32}," -#else - "{\"reg\":23,\"val\":24}," -#endif - "{\"reg\":24,\"val\":2}, \ - {\"reg\":26,\"val\":0}, {\"reg\":27,\"val\":0}, {\"reg\":25,\"val\":50}, {\"reg\":38,\"val\":0}, \ - {\"reg\":39,\"val\":184}, {\"reg\":42,\"val\":184}, {\"reg\":46,\"val\":30}, {\"reg\":47,\"val\":30}, \ - {\"reg\":48,\"val\":30}, {\"reg\":49,\"val\":30}, {\"reg\":2,\"val\":170}]}" }, - { NULL, false, NULL } -}; +extern sys_dac_default_sets* default_dac_sets; +static EXT_RAM_ATTR sys_dac_control_set* i2c_default_controlset = NULL; +static EXT_RAM_ATTR sys_dac_control_set* i2c_controlset = NULL; /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck) { - char *p=NULL; - void * dummy = &codecs; - // i2c_addr = adac_init(config, i2c_port_num); - // if (!i2c_addr) return true; - - // ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr); - - // p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL); +static bool init(sys_dac_config* config, i2s_config_t* i2s_config, bool* mck) { - // if ((!p || !*p) && (p = strcasestr(config, "model")) != NULL) { - // char model[32] = ""; - // int i; - // sscanf(p, "%*[^=]=%31[^,]", model); - // for (i = 0; *model && ((p = codecs[i].controlset) != NULL) && strcasecmp(codecs[i].model, model); i++); - // if (p) *mck = codecs[i].mclk; - // } +#ifdef BYTES_PER_FRAME + uint32_t bytes_per_frame = BYTES_PER_FRAME; +#else + uint32_t bytes_per_frame = 4; +#endif + i2c_addr = adac_init(config); + if (!i2c_addr) return true; + ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr); + ESP_LOGD(TAG, "Checkinf if there's a default control set for DAC %s in the list of %d presets", sys_dac_models_name(config->model), + default_dac_sets->sets_count); - // i2c_json = cJSON_Parse(p); - - // if (!i2c_json) { - // ESP_LOGW(TAG, "no i2c controlset found"); - // return true; - // } - - // if (!i2c_json_execute("init")) { - // ESP_LOGE(TAG, "could not intialize DAC"); - // return false; - // } - // TODO: Add support for the commented code + for (int i = 0; i < default_dac_sets->sets_count; i++) { + ESP_LOGD(TAG, "Checkinf if preset #%d (%s[%d]) matches %s[%d]", i + 1, sys_dac_models_name(default_dac_sets->sets[i].model), + default_dac_sets->sets[i].bytes_per_frame, sys_dac_models_name(config->model), bytes_per_frame); + if (default_dac_sets->sets[i].bytes_per_frame == bytes_per_frame && default_dac_sets->sets[i].model == config->model) { + if (!default_dac_sets->sets[i].valid) { + ESP_LOGE(TAG, "DAC %s is unsupported with %d bytes per frame", sys_dac_models_name(config->model), bytes_per_frame); + return false; + } + i2c_default_controlset = &default_dac_sets->sets[i].set; + } + } - return true; -} + if (config->has_daccontrolset && config->daccontrolset.commands_count > 0) { + i2c_controlset = &config->daccontrolset; + } + if (!i2c_controlset && !i2c_default_controlset) { + ESP_LOGE(TAG, "DAC configuration invalid for %s", sys_dac_models_name(config->model)); + return false; + } + if (mck) { + *mck = i2c_controlset != NULL ? i2c_controlset->mclk_needed : i2c_default_controlset->mclk_needed; + ESP_LOGD(TAG, "Master clock is %s", (*mck) ? "NEEDED" : "NOT NEEDED"); + } + if (!i2c_execute_cmd(sys_dac_control_type_INIT)) { + ESP_LOGE(TAG, "could not intialize DAC"); + return false; + } + + return true; +} /**************************************************************************************** * power */ static void power(adac_power_e mode) { - if (mode == ADAC_STANDBY || mode == ADAC_OFF) i2c_json_execute("poweroff"); - else i2c_json_execute("poweron"); + if (mode == ADAC_STANDBY || mode == ADAC_OFF) + i2c_execute_cmd(sys_dac_control_type_POWER_OFF); + else + i2c_execute_cmd(sys_dac_control_type_POWER_ON); } /**************************************************************************************** * speaker */ static void speaker(bool active) { - if (active) i2c_json_execute("speakeron"); - else i2c_json_execute("speakeroff"); -} + if (active) + i2c_execute_cmd(sys_dac_control_type_SPEAKER_ON); + else + i2c_execute_cmd(sys_dac_control_type_SPEAKER_OFF); +} /**************************************************************************************** * headset */ static void headset(bool active) { - if (active) i2c_json_execute("headseton"); - else i2c_json_execute("headsetoff"); + if (active) + i2c_execute_cmd(sys_dac_control_type_HEADSET_ON); + else + i2c_execute_cmd(sys_dac_control_type_HEADSET_OFF); } /**************************************************************************************** - * + * */ -bool i2c_json_execute(char *set) { - cJSON *json_set = cJSON_GetObjectItemCaseSensitive(i2c_json, set); - cJSON *item; - - if (!json_set) return true; - - cJSON_ArrayForEach(item, json_set) { - cJSON *action; - - // is this a delay - if ((action = cJSON_GetObjectItemCaseSensitive(item, "delay")) != NULL) { - vTaskDelay(pdMS_TO_TICKS(action->valueint)); - ESP_LOGI(TAG, "DAC waiting %d ms", action->valueint); - continue; +static const sys_dac_control_itm* i2c_get_controlset_cmd(sys_dac_control_set* set, sys_dac_control_type cmd_type, pb_size_t* items_count) { + ESP_RETURN_ON_FALSE(set!=NULL,NULL,TAG,"Invalid set"); + ESP_RETURN_ON_FALSE(items_count!=NULL,NULL,TAG,"Invalid items count"); + ESP_LOGD(TAG,"Looking for command %s in control from a list of %d commands",sys_dac_control_type_name(cmd_type),set->commands_count); + *items_count = 0; + for (int i = 0; i < set->commands_count; i++) { + if (set->commands[i].type == cmd_type) { + *items_count = set->commands[i].items_count; + return set->commands[i].items; } - - // is this a gpio toggle - if ((action = cJSON_GetObjectItemCaseSensitive(item, "gpio")) != NULL) { - cJSON *level = cJSON_GetObjectItemCaseSensitive(item, "level"); - ESP_LOGI(TAG, "set GPIO %d at %d", action->valueint, level->valueint); - gpio_set_direction_x(action->valueint, GPIO_MODE_OUTPUT); - gpio_set_level_x(action->valueint, level->valueint); - continue; + } + ESP_LOGD(TAG,"No control set found for command %s",sys_dac_control_type_name(cmd_type)); + return NULL; +} + +/**************************************************************************************** + * + */ +bool i2c_execute_cmd(sys_dac_control_type cmd_type) { + pb_size_t items_count; + const sys_dac_control_itm* cmd = NULL; + esp_err_t err = ESP_OK; + ESP_LOGD(TAG, "Getting control set for command %s", sys_dac_control_type_name(cmd_type)); + if(i2c_controlset){ + cmd = i2c_get_controlset_cmd(i2c_controlset, cmd_type, &items_count); + } + if (!cmd || items_count == 0) { + ESP_LOGD(TAG, "Not found. Checking if defaults are known %s", sys_dac_control_type_name(cmd_type)); + cmd = i2c_get_controlset_cmd(i2c_default_controlset, cmd_type, &items_count); + } + if (!cmd || items_count == 0) { + ESP_LOGD(TAG, "No commands for %s", sys_dac_control_type_name(cmd_type)); + return true; + } + for (pb_size_t i = 0; i < items_count && err==ESP_OK; i++) { + switch (cmd->which_item_type) { + case sys_dac_control_itm_reg_action_tag: + ESP_LOGD(TAG, "Setting reg %d mode %s value %d ", cmd->item_type.reg_action.reg, + sys_dac_control_mode_name(cmd->item_type.reg_action.mode), cmd->item_type.reg_action.val); + if (cmd->item_type.reg_action.mode == sys_dac_control_mode_NOTHING) { + err = adac_write_byte(i2c_addr, cmd->item_type.reg_action.reg, cmd->item_type.reg_action.val); + } else if (cmd->item_type.reg_action.mode == sys_dac_control_mode_OR) { + uint8_t data = adac_read_byte(i2c_addr, cmd->item_type.reg_action.reg); + data |= (uint8_t)cmd->item_type.reg_action.val; + err = adac_write_byte(i2c_addr, cmd->item_type.reg_action.reg, data); + } else if (cmd->item_type.reg_action.mode == sys_dac_control_mode_AND) { + uint8_t data = adac_read_byte(i2c_addr, cmd->item_type.reg_action.reg); + data &= (uint8_t)cmd->item_type.reg_action.val; + err = adac_write_byte(i2c_addr, cmd->item_type.reg_action.reg, data); + } + + break; + case sys_dac_control_itm_regs_action_tag: + ESP_LOGD(TAG, "Setting reg %d with %d byte(s)", cmd->item_type.regs_action.reg, cmd->item_type.regs_action.vals_count); + err = adac_write(i2c_addr, cmd->item_type.regs_action.reg, cmd->item_type.regs_action.vals, cmd->item_type.regs_action.vals_count); + break; + case sys_dac_control_itm_gpio_action_tag: + ESP_LOGI(TAG, "set GPIO %d at %s", cmd->item_type.gpio_action.gpio, sys_dac_control_lvl_name(cmd->item_type.gpio_action.level)); + err = gpio_set_direction_x(cmd->item_type.gpio_action.gpio, GPIO_MODE_OUTPUT); + if(err == ESP_OK) err = gpio_set_level_x(cmd->item_type.gpio_action.gpio, cmd->item_type.gpio_action.level - sys_dac_control_lvl_LV_0); + break; + case sys_dac_control_itm_delay_action_tag: + vTaskDelay(pdMS_TO_TICKS(cmd->item_type.delay_action.delay)); + ESP_LOGI(TAG, "DAC waiting %" PRIu64 " ms", cmd->item_type.delay_action.delay); + break; + + default: + break; } - - action= cJSON_GetObjectItemCaseSensitive(item, "reg"); - cJSON *val = cJSON_GetObjectItemCaseSensitive(item, "val"); - - // this is gpio register setting or crap - if (cJSON_IsArray(val)) { - cJSON *value; - uint8_t *data = malloc(cJSON_GetArraySize(val)); - int count = 0; - - if (!data) continue; - - cJSON_ArrayForEach(value, val) { - data[count++] = value->valueint; - } - - adac_write(i2c_addr, action->valueint, data, count); - free(data); - } else { - cJSON *mode = cJSON_GetObjectItemCaseSensitive(item, "mode"); + } - if (!action || !val) continue; - - if (!mode) { - adac_write_byte(i2c_addr, action->valueint, val->valueint); - } else if (!strcasecmp(mode->valuestring, "or")) { - uint8_t data = adac_read_byte(i2c_addr, action->valueint); - data |= (uint8_t) val->valueint; - adac_write_byte(i2c_addr, action->valueint, data); - } else if (!strcasecmp(mode->valuestring, "and")) { - uint8_t data = adac_read_byte(i2c_addr, action->valueint); - data &= (uint8_t) val->valueint; - adac_write_byte(i2c_addr, action->valueint, data); - } - } - } - - return true; -} + return (err==ESP_OK); +} diff --git a/components/squeezelite/output_bt.c b/components/squeezelite/output_bt.c index 186643c8..f7d01c9c 100644 --- a/components/squeezelite/output_bt.c +++ b/components/squeezelite/output_bt.c @@ -16,9 +16,10 @@ #include "perf_trace.h" #include "services.h" #include "led.h" -#include "Configurator.h" -extern log_level log_level_from_sys_level(sys_DebugLevelEnum level); -static sys_Squeezelite * config = NULL; +#include "Config.h" +extern log_level log_level_from_sys_level(sys_squeezelite_debug_levels level); +extern sys_squeezelite_config* get_profile(const char* name); +static sys_squeezelite_config * config = NULL; extern struct outputstate output; extern struct buffer *outputbuf; extern struct buffer *streambuf; @@ -76,7 +77,8 @@ static uint32_t bt_idle_callback(void) { * Init BT sink */ void output_init_bt() { - config = &platform->services.squeezelite; + config = get_profile(NULL); // get the active profile + if(!config) return; loglevel = log_level_from_sys_level(config->log.output); bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); services_sleep_setsleeper(bt_idle_callback); diff --git a/components/squeezelite/output_embedded.c b/components/squeezelite/output_embedded.c index 7cd334e5..c8fa9062 100644 --- a/components/squeezelite/output_embedded.c +++ b/components/squeezelite/output_embedded.c @@ -10,9 +10,10 @@ */ #include "squeezelite.h" #include "equalizer.h" -#include "Configurator.h" -extern log_level log_level_from_sys_level(sys_DebugLevelEnum level); -static sys_Squeezelite* config = NULL; +#include "Config.h" +extern log_level log_level_from_sys_level(sys_squeezelite_debug_levels level); +extern sys_squeezelite_config* get_profile(const char* name); +static sys_squeezelite_config* config = NULL; extern unsigned int* get_rates() ; @@ -76,9 +77,9 @@ static bool handler(u8_t* data, int len) { } void output_init_embedded() { - config = &platform->services.squeezelite; + config = get_profile(NULL); // get the active profile loglevel = log_level_from_sys_level(config->log.output); - LOG_INFO("init device: %s", sys_OutputTypeEnum_name(config->output_type)); + LOG_INFO("init device: %s", sys_squeezelite_outputs_name(config->output_type)); // chain handlers slimp_handler_chain = slimp_handler; @@ -87,15 +88,22 @@ void output_init_embedded() { // init equalizer before backends equalizer_init(); memset(&output, 0, sizeof(output)); - - output_init_common(loglevel, sys_OutputTypeEnum_name(config->output_type), - config->buffers.output, get_rates(), config->amp_gpio_timeout); + unsigned int output_buffer = OUTPUTBUF_SIZE; + if(config->buffers.output > 0){ + output_buffer = config->buffers.output *1024; + LOG_DEBUG("Found output buffer configuration: %d (%d)",config->buffers.output,output_buffer); + } + else { + LOG_DEBUG("Using default output buffer: %d",output_buffer); + } + output_init_common(loglevel, sys_squeezelite_outputs_name(config->output_type), + output_buffer, get_rates(), config->amp_gpio_timeout); output.start_frames = FRAME_BLOCK; #pragma message("Rate delay logic incomplete") output.rate_delay = 0; #if CONFIG_BT_SINK - if (config->output_type == sys_OutputTypeEnum_OUTPUT_Bluetooth) { + if (config->output_type == sys_squeezelite_outputs_BT) { LOG_INFO("init Bluetooth"); close_cb = &output_close_bt; output_init_bt(get_rates()); @@ -132,7 +140,7 @@ void set_volume(unsigned left, unsigned right) { bool test_open(const char* device, unsigned rates[], bool userdef_rates) { memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned)); - if (config->output_type == sys_OutputTypeEnum_OUTPUT_I2S) { + if (config->output_type == sys_squeezelite_outputs_I2S) { unsigned _rates[] = { #if BYTES_PER_FRAME == 4 192000, @@ -152,7 +160,7 @@ bool test_open(const char* device, unsigned rates[], bool userdef_rates) { 0 }; memcpy(rates, _rates, sizeof(_rates)); - } else if (config->output_type == sys_OutputTypeEnum_OUTPUT_SPDIF) { + } else if (config->output_type == sys_squeezelite_outputs_SPDIF) { unsigned _rates[] = { 96000, 88200, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0}; memcpy(rates, _rates, sizeof(_rates)); diff --git a/components/squeezelite/output_i2s.c b/components/squeezelite/output_i2s.c index 2222c50a..8e0feefa 100644 --- a/components/squeezelite/output_i2s.c +++ b/components/squeezelite/output_i2s.c @@ -30,27 +30,29 @@ there might be a pop and a de-sync when sampling rate change happens. Not sure that using rate_delay would fix that */ -#include "squeezelite.h" -#include "slimproto.h" -#include "esp_pthread.h" -#include "driver/i2s.h" -#include "driver/i2c.h" -#include "driver/gpio.h" -#include "perf_trace.h" -#include -#include "adac.h" -#include "time.h" -#include "led.h" -#include "services.h" -#include "monitor.h" -#include "gpio_exp.h" +#include "Config.h" #include "accessors.h" +#include "adac.h" +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "driver/i2s.h" #include "equalizer.h" +#include "esp_pthread.h" #include "globdefs.h" -#include "Configurator.h" +#include "gpio_exp.h" +#include "hal/gpio_hal.h" +#include "led.h" +#include "monitor.h" +#include "perf_trace.h" +#include "services.h" +#include "slimproto.h" +#include "squeezelite.h" +#include "time.h" +#include -extern log_level log_level_from_sys_level(sys_DebugLevelEnum level); -static sys_Squeezelite* config = NULL; +extern sys_squeezelite_config* get_profile(const char* name); +extern log_level log_level_from_sys_level(sys_squeezelite_debug_levels level); +static sys_squeezelite_config* config = NULL; #define LOCK mutex_lock(outputbuf->mutex) #define UNLOCK mutex_unlock(outputbuf->mutex) @@ -75,18 +77,18 @@ static sys_Squeezelite* config = NULL; #define DMA_BUF_FRAMES_SPDIF 450 #define DMA_BUF_COUNT_SPDIF 7 -#define DECLARE_ALL_MIN_MAX \ - DECLARE_MIN_MAX(o); \ - DECLARE_MIN_MAX(s); \ - DECLARE_MIN_MAX(rec); \ - DECLARE_MIN_MAX(i2s_time); \ +#define DECLARE_ALL_MIN_MAX \ + DECLARE_MIN_MAX(o); \ + DECLARE_MIN_MAX(s); \ + DECLARE_MIN_MAX(rec); \ + DECLARE_MIN_MAX(i2s_time); \ DECLARE_MIN_MAX(buffering); -#define RESET_ALL_MIN_MAX \ - RESET_MIN_MAX(o); \ - RESET_MIN_MAX(s); \ - RESET_MIN_MAX(rec); \ - RESET_MIN_MAX(i2s_time); \ +#define RESET_ALL_MIN_MAX \ + RESET_MIN_MAX(o); \ + RESET_MIN_MAX(s); \ + RESET_MIN_MAX(rec); \ + RESET_MIN_MAX(i2s_time); \ RESET_MIN_MAX(buffering); #define STATS_PERIOD_MS 5000 @@ -101,7 +103,7 @@ extern struct buffer* streambuf; extern struct buffer* outputbuf; extern u8_t* silencebuf; -const struct adac_s* dac_set[] = {&dac_tas57xx, &dac_tas5713, &dac_ac101, &dac_wm8978, NULL}; +const struct adac_s* dac_set[] = {&dac_tas57xx, &dac_tas5713, &dac_ac101, &dac_wm8978, &dac_cs4265, NULL}; const struct adac_s* adac = &dac_external; static log_level loglevel; @@ -122,21 +124,18 @@ static size_t dma_buf_frames; static TaskHandle_t output_i2s_task; static struct { int gpio, active; -} amp_control = {CONFIG_AMP_GPIO, CONFIG_AMP_GPIO_LEVEL}, - mute_control = {CONFIG_MUTE_GPIO, CONFIG_MUTE_GPIO_LEVEL}; +} amp_control = {-1, 0}, mute_control = {-1, 0}; DECLARE_ALL_MIN_MAX; -static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, - u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T** cross_ptr); +static int _i2s_write_frames( + frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T** cross_ptr); static void output_thread_i2s(void* arg); static void i2s_stats(uint32_t now); static void spdif_convert(ISAMPLE_T* src, size_t frames, u32_t* dst); static void (*jack_handler_chain)(bool inserted); -#define I2C_PORT 0 - /**************************************************************************************** * AUDO packet handler */ @@ -151,7 +150,7 @@ static bool handler(u8_t* data, int len) { if (jack_mutes_amp != (pkt->config == 0)) { jack_mutes_amp = pkt->config == 0; platform->dev.dac.jack_mutes_amp = jack_mutes_amp; - configurator_raise_changed(); + config_raise_changed(false); if (jack_mutes_amp && jack_inserted_svc()) { adac->speaker(false); @@ -181,8 +180,7 @@ static void jack_handler(bool inserted) { if (jack_mutes_amp) { LOG_INFO("switching amplifier %s", inserted ? "OFF" : "ON"); adac->speaker(!inserted); - if (amp_control.gpio != -1) - gpio_set_level_x(amp_control.gpio, inserted ? !amp_control.active : amp_control.active); + if (amp_control.gpio != -1) gpio_set_level_x(amp_control.gpio, inserted ? !amp_control.active : amp_control.active); } // activate headset @@ -195,19 +193,17 @@ static void jack_handler(bool inserted) { /**************************************************************************************** * Get inactivity callback */ -static uint32_t i2s_idle_callback(void) { - return output.state <= OUTPUT_STOPPED ? pdTICKS_TO_MS(xTaskGetTickCount()) - i2s_idle_since : 0; -} +static uint32_t i2s_idle_callback(void) { return output.state <= OUTPUT_STOPPED ? pdTICKS_TO_MS(xTaskGetTickCount()) - i2s_idle_since : 0; } /**************************************************************************************** * Initialize the DAC output */ void output_init_i2s() { int silent_do = -1; - config = &platform->services.squeezelite; - sys_DAC* dac_config = platform->has_dev && platform->dev.has_dac ? &platform->dev.dac : NULL; - sys_SPDIF* spdif_config = - platform->has_dev && platform->dev.has_spdif ? &platform->dev.spdif : NULL; + LOG_DEBUG("Initializing I2S output"); + config = get_profile(NULL); + sys_dac_config* dac_config = platform->has_dev && platform->dev.has_dac ? &platform->dev.dac : NULL; + sys_dev_spdif* spdif_config = platform->has_dev && platform->dev.has_spdif ? &platform->dev.spdif : NULL; loglevel = log_level_from_sys_level(config->log.output); esp_err_t res; @@ -216,8 +212,8 @@ void output_init_i2s() { slimp_handler = handler; if (dac_config) jack_mutes_amp = dac_config->jack_mutes_amp; if (platform->has_gpios) { - amp_control.gpio = platform->has_gpios && platform->gpios.has_amp ? platform->gpios.amp.pin:-1; - amp_control.active = platform->has_gpios && platform->gpios.has_amp ? platform->gpios.amp.level:0; + amp_control.gpio = platform->has_gpios && platform->gpios.has_amp ? platform->gpios.amp.pin : -1; + amp_control.active = platform->has_gpios && platform->gpios.has_amp ? platform->gpios.amp.level : 0; } #if BYTES_PER_FRAME == 8 @@ -236,16 +232,25 @@ void output_init_i2s() { running = true; - i2s_pin_config_t i2s_dac_pin = {-1, -1, -1, -1}, i2s_spdif_pin = {-1, -1, -1, -1}; + i2s_pin_config_t i2s_dac_pin = {-1, -1, -1, -1, -1}, i2s_spdif_pin = {-1, -1, -1, -1, -1}; if (dac_config) { - i2s_dac_pin.bck_io_num = dac_config->has_bck ? dac_config->bck.pin : -1; - i2s_dac_pin.data_out_num = dac_config->has_dout ? dac_config->dout.pin : -1; - i2s_dac_pin.ws_io_num = dac_config->has_ws ? dac_config->ws.pin : -1; + i2s_dac_pin.bck_io_num = dac_config->bck; + i2s_dac_pin.data_out_num = dac_config->dout; + i2s_dac_pin.ws_io_num = dac_config->ws; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) + if (dac_config->mck != sys_dac_mck_NONE && dac_config->mck != sys_dac_mck_INVALID1) { + LOG_INFO("Using I2S Master clock %s", sys_dac_mck_name(dac_config->mck)); + i2s_dac_pin.mck_io_num = dac_config->mck - sys_dac_mck_GPIO0; + } else { + LOG_INFO("Configuration does not specify an I2S Master Clock"); + i2s_dac_pin.mck_io_num = -1; + } +#endif } if (spdif_config) { - i2s_spdif_pin.bck_io_num = spdif_config->has_clk ? spdif_config->clk.pin : -1; - i2s_spdif_pin.data_out_num = spdif_config->has_data ? spdif_config->data.pin : -1; - i2s_spdif_pin.ws_io_num = spdif_config->has_dc ? spdif_config->dc.pin : -1; + i2s_spdif_pin.bck_io_num = spdif_config->clk; + i2s_spdif_pin.data_out_num = spdif_config->data; + i2s_spdif_pin.ws_io_num = spdif_config->ws; } if (i2s_dac_pin.data_out_num == -1 && i2s_spdif_pin.data_out_num == -1) { @@ -266,16 +271,16 @@ void output_init_i2s() { i2s_config.dma_buf_len = DMA_BUF_FRAMES; i2s_config.dma_buf_count = DMA_BUF_COUNT; - if (config->output_type == sys_OutputTypeEnum_OUTPUT_SPDIF) { + if (config->output_type == sys_squeezelite_outputs_SPDIF) { spdif.enabled = true; + LOG_DEBUG("Configuring SPDIF"); if ((spdif.buf = heap_caps_malloc(SPDIF_BLOCK * 16, MALLOC_CAP_INTERNAL)) == NULL) { LOG_ERROR("Cannot allocate SPDIF buffer"); } - if (i2s_spdif_pin.bck_io_num == -1 || i2s_spdif_pin.ws_io_num == -1 || - i2s_spdif_pin.data_out_num == -1) { - LOG_WARN("Cannot initialize I2S for SPDIF bck:%d ws:%d do:%d", i2s_spdif_pin.bck_io_num, - i2s_spdif_pin.ws_io_num, i2s_spdif_pin.data_out_num); + if (i2s_spdif_pin.bck_io_num == -1 || i2s_spdif_pin.ws_io_num == -1 || i2s_spdif_pin.data_out_num == -1) { + LOG_WARN( + "Cannot initialize I2S for SPDIF bck:%d ws:%d do:%d", i2s_spdif_pin.bck_io_num, i2s_spdif_pin.ws_io_num, i2s_spdif_pin.data_out_num); } i2s_config.sample_rate = output.current_sample_rate * 2; @@ -291,15 +296,14 @@ void output_init_i2s() { dma_buf_frames = i2s_config.dma_buf_len * i2s_config.dma_buf_count / 2; // silence DAC output if sharing the same ws/bck - if (i2s_dac_pin.ws_io_num == i2s_spdif_pin.ws_io_num && - i2s_dac_pin.bck_io_num == i2s_spdif_pin.bck_io_num) + if (i2s_dac_pin.ws_io_num == i2s_spdif_pin.ws_io_num && i2s_dac_pin.bck_io_num == i2s_spdif_pin.bck_io_num) silent_do = i2s_dac_pin.data_out_num; res = i2s_driver_install(CONFIG_I2S_NUM, &i2s_config, 0, NULL); res |= i2s_set_pin(CONFIG_I2S_NUM, &i2s_spdif_pin); - LOG_INFO("SPDIF using I2S bck:%d, ws:%d, do:%d", i2s_spdif_pin.bck_io_num, - i2s_spdif_pin.ws_io_num, i2s_spdif_pin.data_out_num); + LOG_INFO("SPDIF using I2S bck:%d, ws:%d, do:%d", i2s_spdif_pin.bck_io_num, i2s_spdif_pin.ws_io_num, i2s_spdif_pin.data_out_num); } else { + LOG_DEBUG("Configuring DAC"); i2s_config.sample_rate = output.current_sample_rate; i2s_config.bits_per_sample = BYTES_PER_FRAME * 8 / 2; // Counted in frames (but i2s allocates a buffer <= 4092 bytes) @@ -312,17 +316,30 @@ void output_init_i2s() { mute_control.gpio = dac_config && dac_config->has_mute ? dac_config->mute.pin : -1; mute_control.active = dac_config && dac_config->has_mute ? dac_config->mute.level : 0; bool mck_required = false; - for (int i = 0; adac == &dac_external && dac_set[i]; i++) - if (dac_set[i]->model == dac_config->model) adac = dac_set[i]; - res = adac->init(NULL, I2C_PORT, &i2s_config, &mck_required) ? ESP_OK : ESP_FAIL; - + LOG_DEBUG("Looking for %s DAC Driver", sys_dac_models_name(dac_config->model)); + for (int i = 0; adac == &dac_external && dac_set[i]; i++) { + if (dac_set[i]->model == dac_config->model) { + LOG_DEBUG("Found Driver"); + adac = dac_set[i]; + } else { + LOG_DEBUG("Skipping %s", sys_dac_models_name(dac_set[i]->model)); + } + } + if (!adac) { + LOG_ERROR("Invalid adac structure"); + return; + } + if (!adac->init) { + LOG_ERROR("adac doesn't have a valid init"); + return; + } + LOG_DEBUG("Calling DAC init for %s", sys_dac_models_name(adac->model)); + res = adac->init(&platform->dev.dac, &i2s_config, &mck_required) ? ESP_OK : ESP_FAIL; #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0) - int mck_io_num = (dac_config->mck - sys_MCKEnum_MCK0) < 0 && mck_required - ? 0 - : dac_config->mck - sys_MCKEnum_MCK0; - + int mck_io_num = (((int)dac_config->mck) - ((int)sys_MCKEnum_MCK0)) < 0 && mck_required ? 0 + : mck_required ? dac_config->mck - sys_MCKEnum_MCK0 + : -1; LOG_INFO("configuring MCLK on GPIO %d", mck_io_num); - if (mck_io_num == GPIO_NUM_0) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); WRITE_PERI_REG(PIN_CTRL, CONFIG_I2S_NUM == I2S_NUM_0 ? 0xFFF0 : 0xFFFF); @@ -336,22 +353,28 @@ void output_init_i2s() { LOG_WARN("invalid MCK gpio %d", mck_io_num); } #else - if (mck_required && i2s_dac_pin.mck_io_num == -1) i2s_dac_pin.mck_io_num = 0; - LOG_INFO("configuring MCLK on GPIO %d", i2s_dac_pin.mck_io_num); -#endif - - res |= i2s_driver_install(CONFIG_I2S_NUM, &i2s_config, 0, NULL); - res |= i2s_set_pin(CONFIG_I2S_NUM, &i2s_dac_pin); - - if (res == ESP_OK && mute_control.gpio >= 0) { - gpio_pad_select_gpio(mute_control.gpio); - gpio_set_direction(mute_control.gpio, GPIO_MODE_OUTPUT); - gpio_set_level(mute_control.gpio, mute_control.active); + if (res == ESP_OK) { + if (mck_required && i2s_dac_pin.mck_io_num == -1) { + LOG_DEBUG("Defaulting MCLK on GPIO %d", i2s_dac_pin.mck_io_num); + i2s_dac_pin.mck_io_num = 0; + } else { + LOG_DEBUG("MCLK configured on GPIO %d", i2s_dac_pin.mck_io_num); + } } +#endif + if (res == ESP_OK) { + res |= i2s_driver_install(CONFIG_I2S_NUM, &i2s_config, 0, NULL); + res |= i2s_set_pin(CONFIG_I2S_NUM, &i2s_dac_pin); - LOG_INFO("%s DAC using I2S bck:%d, ws:%d, do:%d, mute:%d:%d (res:%d)", - sys_EthModelEnum_name(dac_config->model), i2s_dac_pin.bck_io_num, i2s_dac_pin.ws_io_num, - i2s_dac_pin.data_out_num, mute_control.gpio, mute_control.active, res); + if (res == ESP_OK && mute_control.gpio >= 0) { + gpio_pad_select_gpio(mute_control.gpio); + gpio_set_direction(mute_control.gpio, GPIO_MODE_OUTPUT); + gpio_set_level(mute_control.gpio, mute_control.active); + } + + LOG_INFO("%s DAC using I2S bck:%d, ws:%d, do:%d, mute:%d:%d (res:%d)", sys_dac_models_name(dac_config->model), i2s_dac_pin.bck_io_num, + i2s_dac_pin.ws_io_num, i2s_dac_pin.data_out_num, mute_control.gpio, mute_control.active, res); + } } if (res != ESP_OK) { @@ -368,8 +391,7 @@ void output_init_i2s() { LOG_INFO("Initializing I2S mode %s with rate: %d, bits per sample: %d, buffer frames: %d, " "number of buffers: %d ", - spdif.enabled ? "S/PDIF" : "normal", i2s_config.sample_rate, i2s_config.bits_per_sample, - i2s_config.dma_buf_len, i2s_config.dma_buf_count); + spdif.enabled ? "S/PDIF" : "normal", i2s_config.sample_rate, i2s_config.bits_per_sample, i2s_config.dma_buf_len, i2s_config.dma_buf_count); i2s_stop(CONFIG_I2S_NUM); i2s_zero_dma_buffer(CONFIG_I2S_NUM); @@ -408,10 +430,8 @@ void output_init_i2s() { // create task as a FreeRTOS task but uses stack in internal RAM { static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__((aligned(4))); - static EXT_RAM_ATTR StackType_t xStack[OUTPUT_THREAD_STACK_SIZE] - __attribute__((aligned(4))); - output_i2s_task = xTaskCreateStaticPinnedToCore((TaskFunction_t)output_thread_i2s, - "output_i2s", OUTPUT_THREAD_STACK_SIZE, NULL, + static EXT_RAM_ATTR StackType_t xStack[OUTPUT_THREAD_STACK_SIZE] __attribute__((aligned(4))); + output_i2s_task = xTaskCreateStaticPinnedToCore((TaskFunction_t)output_thread_i2s, "output_i2s", OUTPUT_THREAD_STACK_SIZE, NULL, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, xStack, &xTaskBuffer, 0); } } @@ -439,17 +459,15 @@ void output_close_i2s(void) { * change volume */ bool output_volume_i2s(unsigned left, unsigned right) { - if (mute_control.gpio >= 0) - gpio_set_level( - mute_control.gpio, (left | right) ? !mute_control.active : mute_control.active); + if (mute_control.gpio >= 0) gpio_set_level(mute_control.gpio, (left | right) ? !mute_control.active : mute_control.active); return adac->volume(left, right); } /**************************************************************************************** * Write frames to the output buffer */ -static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, - u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T** cross_ptr) { +static int _i2s_write_frames( + frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T** cross_ptr) { if (!silence) { if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) { _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr); @@ -463,8 +481,7 @@ static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32 // don't update visu if we don't have enough data in buffer if (silence || output.external || _buf_used(outputbuf) > outputbuf->size >> 2) { - output_visu_export(obuf + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, - silence, (gainL + gainR) / 2); + output_visu_export(obuf + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, silence, (gainL + gainR) / 2); } oframes += out_frames; @@ -503,8 +520,7 @@ static void output_thread_i2s(void* arg) { led_blink(LED_GREEN, 200, 1000); } else if (output.state == OUTPUT_RUNNING) { if (!jack_mutes_amp || !jack_inserted_svc()) { - if (amp_control.gpio != -1) - gpio_set_level_x(amp_control.gpio, amp_control.active); + if (amp_control.gpio != -1) gpio_set_level_x(amp_control.gpio, amp_control.active); adac->speaker(true); } led_on(LED_GREEN); @@ -530,8 +546,7 @@ static void output_thread_i2s(void* arg) { output.frames_played_dmp = output.frames_played; // try to estimate how much we have consumed from the DMA buffer (calculation is incorrect // at the very beginning ...) - output.device_frames = - dma_buf_frames - ((output.updated - fullness) * output.current_sample_rate) / 1000; + output.device_frames = dma_buf_frames - ((output.updated - fullness) * output.current_sample_rate) / 1000; // we'll try to produce iframes if we have any, but we might return less if outpuf does not // have enough _output_frames(iframes); @@ -572,8 +587,7 @@ static void output_thread_i2s(void* arg) { // this does not work well as set_sample_rates resets the fifos (and it's too early) if (i2s_config.sample_rate != output.current_sample_rate) { - LOG_INFO("changing sampling rate %u to %u", i2s_config.sample_rate, - output.current_sample_rate); + LOG_INFO("changing sampling rate %u to %u", i2s_config.sample_rate, output.current_sample_rate); if (synced) { /* // can sleep for a buffer_queue - 1 and then eat a buffer (discard) if we are @@ -582,8 +596,7 @@ static void output_thread_i2s(void* arg) { */ } i2s_config.sample_rate = output.current_sample_rate; - i2s_set_sample_rates(CONFIG_I2S_NUM, - spdif.enabled ? i2s_config.sample_rate * 2 : i2s_config.sample_rate); + i2s_set_sample_rates(CONFIG_I2S_NUM, spdif.enabled ? i2s_config.sample_rate * 2 : i2s_config.sample_rate); i2s_zero_dma_buffer(CONFIG_I2S_NUM); equalizer_set_samplerate(output.current_sample_rate); @@ -607,8 +620,7 @@ static void output_thread_i2s(void* arg) { } #if BYTES_PER_FRAME == 4 } else if (i2s_config.bits_per_sample == 32) { - i2s_write_expand( - CONFIG_I2S_NUM, obuf, oframes * BYTES_PER_FRAME, 16, 32, &bytes, portMAX_DELAY); + i2s_write_expand(CONFIG_I2S_NUM, obuf, oframes * BYTES_PER_FRAME, 16, 32, &bytes, portMAX_DELAY); #endif } else { i2s_write(CONFIG_I2S_NUM, obuf, oframes * BYTES_PER_FRAME, &bytes, portMAX_DELAY); @@ -617,8 +629,7 @@ static void output_thread_i2s(void* arg) { fullness = gettime_ms(); if (bytes != oframes * BYTES_PER_FRAME) { - LOG_WARN("I2S DMA Overflow! available bytes: %d, I2S wrote %d bytes", - oframes * BYTES_PER_FRAME, bytes); + LOG_WARN("I2S DMA Overflow! available bytes: %d, I2S wrote %d bytes", oframes * BYTES_PER_FRAME, bytes); } SET_MIN_MAX(TIME_MEASUREMENT_GET(timer_start), i2s_time); @@ -643,8 +654,7 @@ static void i2s_stats(uint32_t now) { if (output.state <= OUTPUT_STOPPED || now < last + STATS_PERIOD_MS) return; last = now; - LOG_INFO("Output State: %d, current sample rate: %d, bytes per frame: %d", output.state, - output.current_sample_rate, BYTES_PER_FRAME); + LOG_INFO("Output State: %d, current sample rate: %d, bytes per frame: %d", output.state, output.current_sample_rate, BYTES_PER_FRAME); LOG_INFO(LINE_MIN_MAX_FORMAT_HEAD1); LOG_INFO(LINE_MIN_MAX_FORMAT_HEAD2); LOG_INFO(LINE_MIN_MAX_FORMAT_HEAD3); @@ -673,27 +683,20 @@ static void i2s_stats(uint32_t now) { static const u8_t VUCP24[2] = {0xCC, 0x32}; -static const u16_t spdif_bmclookup[256] = {0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, - 0xab33, 0xcd33, 0xb2cc, 0xd2cc, 0xad33, 0xcacc, 0xb533, 0xd533, 0xaacc, 0xccb3, 0xb34c, 0xd34c, - 0xacb3, 0xcb4c, 0xb4b3, 0xd4b3, 0xab4c, 0xcd4c, 0xb2b3, 0xd2b3, 0xad4c, 0xcab3, 0xb54c, 0xd54c, - 0xaab3, 0xccd3, 0xb32c, 0xd32c, 0xacd3, 0xcb2c, 0xb4d3, 0xd4d3, 0xab2c, 0xcd2c, 0xb2d3, 0xd2d3, - 0xad2c, 0xcad3, 0xb52c, 0xd52c, 0xaad3, 0xccac, 0xb353, 0xd353, 0xacac, 0xcb53, 0xb4ac, 0xd4ac, - 0xab53, 0xcd53, 0xb2ac, 0xd2ac, 0xad53, 0xcaac, 0xb553, 0xd553, 0xaaac, 0xcccb, 0xb334, 0xd334, - 0xaccb, 0xcb34, 0xb4cb, 0xd4cb, 0xab34, 0xcd34, 0xb2cb, 0xd2cb, 0xad34, 0xcacb, 0xb534, 0xd534, - 0xaacb, 0xccb4, 0xb34b, 0xd34b, 0xacb4, 0xcb4b, 0xb4b4, 0xd4b4, 0xab4b, 0xcd4b, 0xb2b4, 0xd2b4, - 0xad4b, 0xcab4, 0xb54b, 0xd54b, 0xaab4, 0xccd4, 0xb32b, 0xd32b, 0xacd4, 0xcb2b, 0xb4d4, 0xd4d4, - 0xab2b, 0xcd2b, 0xb2d4, 0xd2d4, 0xad2b, 0xcad4, 0xb52b, 0xd52b, 0xaad4, 0xccab, 0xb354, 0xd354, - 0xacab, 0xcb54, 0xb4ab, 0xd4ab, 0xab54, 0xcd54, 0xb2ab, 0xd2ab, 0xad54, 0xcaab, 0xb554, 0xd554, - 0xaaab, 0xcccd, 0xb332, 0xd332, 0xaccd, 0xcb32, 0xb4cd, 0xd4cd, 0xab32, 0xcd32, 0xb2cd, 0xd2cd, - 0xad32, 0xcacd, 0xb532, 0xd532, 0xaacd, 0xccb2, 0xb34d, 0xd34d, 0xacb2, 0xcb4d, 0xb4b2, 0xd4b2, - 0xab4d, 0xcd4d, 0xb2b2, 0xd2b2, 0xad4d, 0xcab2, 0xb54d, 0xd54d, 0xaab2, 0xccd2, 0xb32d, 0xd32d, - 0xacd2, 0xcb2d, 0xb4d2, 0xd4d2, 0xab2d, 0xcd2d, 0xb2d2, 0xd2d2, 0xad2d, 0xcad2, 0xb52d, 0xd52d, - 0xaad2, 0xccad, 0xb352, 0xd352, 0xacad, 0xcb52, 0xb4ad, 0xd4ad, 0xab52, 0xcd52, 0xb2ad, 0xd2ad, - 0xad52, 0xcaad, 0xb552, 0xd552, 0xaaad, 0xccca, 0xb335, 0xd335, 0xacca, 0xcb35, 0xb4ca, 0xd4ca, - 0xab35, 0xcd35, 0xb2ca, 0xd2ca, 0xad35, 0xcaca, 0xb535, 0xd535, 0xaaca, 0xccb5, 0xb34a, 0xd34a, - 0xacb5, 0xcb4a, 0xb4b5, 0xd4b5, 0xab4a, 0xcd4a, 0xb2b5, 0xd2b5, 0xad4a, 0xcab5, 0xb54a, 0xd54a, - 0xaab5, 0xccd5, 0xb32a, 0xd32a, 0xacd5, 0xcb2a, 0xb4d5, 0xd4d5, 0xab2a, 0xcd2a, 0xb2d5, 0xd2d5, - 0xad2a, 0xcad5, 0xb52a, 0xd52a, 0xaad5, 0xccaa, 0xb355, 0xd355, 0xacaa, 0xcb55, 0xb4aa, 0xd4aa, +static const u16_t spdif_bmclookup[256] = {0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, 0xab33, 0xcd33, 0xb2cc, 0xd2cc, 0xad33, 0xcacc, + 0xb533, 0xd533, 0xaacc, 0xccb3, 0xb34c, 0xd34c, 0xacb3, 0xcb4c, 0xb4b3, 0xd4b3, 0xab4c, 0xcd4c, 0xb2b3, 0xd2b3, 0xad4c, 0xcab3, 0xb54c, 0xd54c, + 0xaab3, 0xccd3, 0xb32c, 0xd32c, 0xacd3, 0xcb2c, 0xb4d3, 0xd4d3, 0xab2c, 0xcd2c, 0xb2d3, 0xd2d3, 0xad2c, 0xcad3, 0xb52c, 0xd52c, 0xaad3, 0xccac, + 0xb353, 0xd353, 0xacac, 0xcb53, 0xb4ac, 0xd4ac, 0xab53, 0xcd53, 0xb2ac, 0xd2ac, 0xad53, 0xcaac, 0xb553, 0xd553, 0xaaac, 0xcccb, 0xb334, 0xd334, + 0xaccb, 0xcb34, 0xb4cb, 0xd4cb, 0xab34, 0xcd34, 0xb2cb, 0xd2cb, 0xad34, 0xcacb, 0xb534, 0xd534, 0xaacb, 0xccb4, 0xb34b, 0xd34b, 0xacb4, 0xcb4b, + 0xb4b4, 0xd4b4, 0xab4b, 0xcd4b, 0xb2b4, 0xd2b4, 0xad4b, 0xcab4, 0xb54b, 0xd54b, 0xaab4, 0xccd4, 0xb32b, 0xd32b, 0xacd4, 0xcb2b, 0xb4d4, 0xd4d4, + 0xab2b, 0xcd2b, 0xb2d4, 0xd2d4, 0xad2b, 0xcad4, 0xb52b, 0xd52b, 0xaad4, 0xccab, 0xb354, 0xd354, 0xacab, 0xcb54, 0xb4ab, 0xd4ab, 0xab54, 0xcd54, + 0xb2ab, 0xd2ab, 0xad54, 0xcaab, 0xb554, 0xd554, 0xaaab, 0xcccd, 0xb332, 0xd332, 0xaccd, 0xcb32, 0xb4cd, 0xd4cd, 0xab32, 0xcd32, 0xb2cd, 0xd2cd, + 0xad32, 0xcacd, 0xb532, 0xd532, 0xaacd, 0xccb2, 0xb34d, 0xd34d, 0xacb2, 0xcb4d, 0xb4b2, 0xd4b2, 0xab4d, 0xcd4d, 0xb2b2, 0xd2b2, 0xad4d, 0xcab2, + 0xb54d, 0xd54d, 0xaab2, 0xccd2, 0xb32d, 0xd32d, 0xacd2, 0xcb2d, 0xb4d2, 0xd4d2, 0xab2d, 0xcd2d, 0xb2d2, 0xd2d2, 0xad2d, 0xcad2, 0xb52d, 0xd52d, + 0xaad2, 0xccad, 0xb352, 0xd352, 0xacad, 0xcb52, 0xb4ad, 0xd4ad, 0xab52, 0xcd52, 0xb2ad, 0xd2ad, 0xad52, 0xcaad, 0xb552, 0xd552, 0xaaad, 0xccca, + 0xb335, 0xd335, 0xacca, 0xcb35, 0xb4ca, 0xd4ca, 0xab35, 0xcd35, 0xb2ca, 0xd2ca, 0xad35, 0xcaca, 0xb535, 0xd535, 0xaaca, 0xccb5, 0xb34a, 0xd34a, + 0xacb5, 0xcb4a, 0xb4b5, 0xd4b5, 0xab4a, 0xcd4a, 0xb2b5, 0xd2b5, 0xad4a, 0xcab5, 0xb54a, 0xd54a, 0xaab5, 0xccd5, 0xb32a, 0xd32a, 0xacd5, 0xcb2a, + 0xb4d5, 0xd4d5, 0xab2a, 0xcd2a, 0xb2d5, 0xd2d5, 0xad2a, 0xcad5, 0xb52a, 0xd52a, 0xaad5, 0xccaa, 0xb355, 0xd355, 0xacaa, 0xcb55, 0xb4aa, 0xd4aa, 0xab55, 0xcd55, 0xb2aa, 0xd2aa, 0xad55, 0xcaaa, 0xb555, 0xd555, 0xaaaa}; /* diff --git a/components/squeezelite/tas57xx/dac_5713.c b/components/squeezelite/tas57xx/dac_5713.c index 4be86f62..1ec51c0a 100644 --- a/components/squeezelite/tas57xx/dac_5713.c +++ b/components/squeezelite/tas57xx/dac_5713.c @@ -39,13 +39,13 @@ static const char TAG[] = "TAS5713"; -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck); static void speaker(bool active) { }; static void headset(bool active) { } ; static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode) { }; -const struct adac_s dac_tas5713 = {sys_DACModelEnum_TAS5713, init, adac_deinit, power, speaker, headset, volume}; +const struct adac_s dac_tas5713 = {sys_dac_models_TAS5713, init, adac_deinit, power, speaker, headset, volume}; struct tas5713_cmd_s { uint8_t reg; @@ -65,9 +65,9 @@ typedef enum { /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck) { +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck) { /* find if there is a tas5713 attached. Reg 0 should read non-zero but not 255 if so */ - adac_init(config, i2c_port); + adac_init(config); if (adac_read_byte(TAS5713, 0x00) == 255) { ESP_LOGW(TAG, "No TAS5713 detected"); adac_deinit(); diff --git a/components/squeezelite/tas57xx/dac_57xx.c b/components/squeezelite/tas57xx/dac_57xx.c index 88aff0b2..8b02aaf8 100644 --- a/components/squeezelite/tas57xx/dac_57xx.c +++ b/components/squeezelite/tas57xx/dac_57xx.c @@ -23,13 +23,13 @@ static const char TAG[] = "TAS575x/8x"; -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck); static void speaker(bool active); static void headset(bool active); static bool volume(unsigned left, unsigned right); static void power(adac_power_e mode); -const struct adac_s dac_tas57xx = { sys_DACModelEnum_TAS57xx, init, adac_deinit, power, speaker, headset, volume }; +const struct adac_s dac_tas57xx = { sys_dac_models_TAS57xx, init, adac_deinit, power, speaker, headset, volume }; struct tas57xx_cmd_s { uint8_t reg; @@ -71,9 +71,9 @@ static int tas57_detect(void); /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck) { +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck) { // find which TAS we are using (if any) - tas57_addr = adac_init(config, i2c_port); + tas57_addr = adac_init(config); if (!tas57_addr) tas57_addr = tas57_detect(); if (!tas57_addr) { @@ -93,7 +93,7 @@ static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck } i2c_master_stop(i2c_cmd); - esp_err_t res = i2c_master_cmd_begin(i2c_port, i2c_cmd, 500 / portTICK_RATE_MS); + esp_err_t res = i2c_master_cmd_begin(config->i2c.port-sys_i2c_port_PORT0, i2c_cmd, 500 / portTICK_RATE_MS); i2c_cmd_link_delete(i2c_cmd); if (res != ESP_OK) { diff --git a/components/squeezelite/wm8978/wm8978.c b/components/squeezelite/wm8978/wm8978.c index 98123c6f..2b169c08 100644 --- a/components/squeezelite/wm8978/wm8978.c +++ b/components/squeezelite/wm8978/wm8978.c @@ -23,14 +23,14 @@ static void speaker(bool active) { } static void headset(bool active) { } static bool volume(unsigned left, unsigned right) { return false; } static void power(adac_power_e mode); -static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck); static esp_err_t i2c_write_shadow(uint8_t reg, uint16_t val); static uint16_t i2c_read_shadow(uint8_t reg); static int WM8978; -const struct adac_s dac_wm8978 = { sys_DACModelEnum_WM8978, init, adac_deinit, power, speaker, headset, volume }; +const struct adac_s dac_wm8978 = { sys_dac_models_WM8978, init, adac_deinit, power, speaker, headset, volume }; // initiation table for non-readbale 9-bit i2c registers static uint16_t WM8978_REGVAL_TBL[58] = { @@ -47,8 +47,8 @@ static uint16_t WM8978_REGVAL_TBL[58] = { /**************************************************************************************** * init */ -static bool init(char *config, int i2c_port, i2s_config_t *i2s_config, bool *mck) { - WM8978 = adac_init(config, i2c_port); +static bool init(sys_dac_config *config, i2s_config_t *i2s_config, bool *mck) { + WM8978 = adac_init(config); if (!WM8978) WM8978 = 0x1a; ESP_LOGI(TAG, "WM8978 detected @%d", WM8978); diff --git a/components/targets/targets.c b/components/targets/targets.c index 9f54d364..8aa5d669 100644 --- a/components/targets/targets.c +++ b/components/targets/targets.c @@ -1,10 +1,13 @@ #include "string.h" +#include "esp_log.h" #include "targets.h" - +static const char * TAG = "targets"; const struct target_s *target_set[] = { &target_muse, NULL }; void target_init(char *target) { + ESP_LOGI(TAG,"Checking if target %s needs init",target); for (int i = 0; *target && target_set[i]; i++) if (strcasestr(target_set[i]->model, target)) { + ESP_LOGI(TAG,"Initializing target %s ",target); target_set[i]->init(); break; } diff --git a/components/telnet/telnet.c b/components/telnet/telnet.c index b126209e..58d6b3e6 100644 --- a/components/telnet/telnet.c +++ b/components/telnet/telnet.c @@ -1,4 +1,4 @@ - /** +/** * Test the telnet functions. * * Perform a test using the telnet functions. @@ -18,29 +18,29 @@ * https://github.com/PocketSprite/8bkc-sdk/blob/master/8bkc-components/8bkc-hal/vfs-stdout.c * */ -#include // Required for libtelnet.h -#include -#include "libtelnet.h" -#include "stdbool.h" -#include -#include -#include -#include -#include "sdkconfig.h" -#include "freertos/ringbuf.h" -#include "esp_app_trace.h" #include "telnet.h" +#include "Config.h" +#include "accessors.h" +#include "config.h" +#include "driver/uart.h" +#include "esp_app_trace.h" +#include "esp_attr.h" #include "esp_vfs.h" #include "esp_vfs_dev.h" -#include "esp_attr.h" -#include "soc/uart_struct.h" -#include "driver/uart.h" -#include "config.h" -#include "platform_esp32.h" +#include "freertos/ringbuf.h" +#include "libtelnet.h" #include "messaging.h" +#include "platform_esp32.h" +#include "sdkconfig.h" +#include "soc/uart_struct.h" +#include "stdbool.h" #include "tools.h" -#include "Configurator.h" -#include "accessors.h" +#include +#include +#include +#include +#include // Required for libtelnet.h +#include /************************************ * Globals */ @@ -48,251 +48,235 @@ #define TELNET_STACK_SIZE 4096 #define TELNET_RX_BUF 1024 -extern bool bypass_network_manager; - struct telnetUserData { - int sockfd; - telnet_t *tnHandle; - char * rxbuf; + int sockfd; + telnet_t* tnHandle; + char* rxbuf; }; const static char TAG[] = "telnet"; static int uart_fd; static RingbufHandle_t buf_handle; static size_t send_chunk = 512; -static size_t log_buf_size = 4*1024; -static bool bIsEnabled=false; +static size_t log_buf_size = 4 * 1024; +static bool bIsEnabled = false; static int partnerSocket; -static telnet_t *tnHandle; -static bool bMirrorToUART; +static telnet_t* tnHandle; /************************************ * Forward declarations */ -static void telnet_task(void *data); -static int stdout_open(const char * path, int flags, int mode); -static int stdout_fstat(int fd, struct stat * st); -static ssize_t stdout_write(int fd, const void * data, size_t size); -static void handle_telnet_conn(); -static size_t process_logs( UBaseType_t bytes, bool make_room); +static void telnet_task(void* data); +static int stdout_open(const char* path, int flags, int mode); +static int stdout_fstat(int fd, struct stat* st); +static ssize_t stdout_write(int fd, const void* data, size_t size); +static void handle_telnet_conn(); +static size_t process_logs(UBaseType_t bytes, bool make_room); +static sys_telnet_config* telnet_svc = NULL; -void init_telnet(){ - sys_Telnet * telnet_svc=NULL; - if(!SYS_SERVICES_TELNET(telnet_svc) || !telnet_svc->enable){ - ESP_LOGI(TAG,"Telnet support disabled"); - return; - } +void init_telnet() { + if (!sys_services_config_TELNET(telnet_svc) || telnet_svc->enable == sys_telnet_output_SERIAL_ONLY) { + ESP_LOGI(TAG, "Telnet support disabled"); + return; + } + ESP_LOGI(TAG, "Starting Telnet service"); + ESP_LOGD(TAG, "Getting values from configuration"); + if (telnet_svc->block > 0) send_chunk = telnet_svc->block; + if (telnet_svc->block > 0) log_buf_size = telnet_svc->buffer; + ESP_LOGD(TAG, "Allocating memory for the ring buffer and storage. send_chunk: %d, log_buf_size: %d", send_chunk, log_buf_size); - #pragma message("Do we still need this logic for telnet?") - // // if wifi manager is bypassed, there will possibly be no wifi available - // bMirrorToUART = (strcasestr("D",val)!=NULL); - // if (!bMirrorToUART && bypass_network_manager){ - // // This isn't supposed to happen, as telnet won't start if wifi manager isn't - // // started. So this is a safeguard only. - // ESP_LOGW(TAG,"Wifi manager is not active. Forcing console on Serial output."); - // } + // Redirect the output to our telnet handler as soon as possible + StaticRingbuffer_t* buffer_struct = (StaticRingbuffer_t*)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + // All non-split ring buffer must have their memory alignment set to 32 bits. + uint8_t* buffer_storage = (uint8_t*)heap_caps_malloc(sizeof(uint8_t) * log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct); + if (buf_handle == NULL || buffer_struct == NULL) { + ESP_LOGE(TAG, "Failed to create ring buffer for telnet!"); + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Failed to allocate memory for telnet buffer"); + return; + } - if (telnet_svc->block > 0) send_chunk = telnet_svc->block; - if (telnet_svc->block > 0) log_buf_size = telnet_svc->buffer; + if (telnet_svc->enable == sys_telnet_output_TELNET) { + ESP_LOGI(TAG, "***Redirecting log output to telnet"); + } else { + ESP_LOGI(TAG, "Instantiating telnet service"); + } - // Redirect the output to our telnet handler as soon as possible - StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *) heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - // All non-split ring buffer must have their memory alignment set to 32 bits. - uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT ); - buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct); - if (buf_handle == NULL) { - ESP_LOGE(TAG,"Failed to create ring buffer for telnet!"); - messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Failed to allocate memory for telnet buffer"); + esp_vfs_t vfs = {}; + vfs.flags = ESP_VFS_FLAG_DEFAULT; + vfs.write = &stdout_write; + vfs.open = &stdout_open; + vfs.fstat = &stdout_fstat; - return; - } + if (telnet_svc->enable == sys_telnet_output_TELNET_SERIAL) uart_fd = open("/dev/uart/0", O_RDWR); - ESP_LOGI(TAG, "***Redirecting log output to telnet"); - esp_vfs_t vfs = { }; - vfs.flags = ESP_VFS_FLAG_DEFAULT; - vfs.write = &stdout_write; - vfs.open = &stdout_open; - vfs.fstat = &stdout_fstat; - - if (bMirrorToUART) uart_fd = open("/dev/uart/0", O_RDWR); - - ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL)); - freopen("/dev/pkspstdout", "w", stdout); - freopen("/dev/pkspstdout", "w", stderr); - - bIsEnabled=true; + ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL)); + freopen("/dev/pkspstdout", "w", stdout); + freopen("/dev/pkspstdout", "w", stderr); + bIsEnabled = true; } -void start_telnet(void * pvParameter){ - static bool isStarted=false; +void start_telnet(void* pvParameter) { + static bool isStarted = false; - if (isStarted || !bIsEnabled) return; + if (isStarted || !bIsEnabled) return; - isStarted=true; + isStarted = true; - StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - StackType_t *xStack = heap_caps_malloc(TELNET_STACK_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN, xStack, xTaskBuffer); + StaticTask_t* xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + StackType_t* xStack = heap_caps_malloc(TELNET_STACK_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + xTaskCreateStatic((TaskFunction_t)&telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN, xStack, xTaskBuffer); } -static void telnet_task(void *data) { - int serverSocket; - struct sockaddr_in serverAddr; - serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); - serverAddr.sin_port = htons(23); +static void telnet_task(void* data) { + int serverSocket; + struct sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddr.sin_port = htons(23); - while (1) { - serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) >= 0 && listen(serverSocket, 1) >= 0) break; - close(serverSocket); - ESP_LOGI(TAG, "can't bind Telnet socket"); - vTaskDelay(pdMS_TO_TICKS(1000)); - } + while (1) { + serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) >= 0 && listen(serverSocket, 1) >= 0) break; + close(serverSocket); + ESP_LOGI(TAG, "can't bind Telnet socket"); + vTaskDelay(pdMS_TO_TICKS(1000)); + } - while (1) { - socklen_t len = sizeof(serverAddr); - int sock = accept(serverSocket, (struct sockaddr *)&serverAddr, &len); + while (1) { + socklen_t len = sizeof(serverAddr); + int sock = accept(serverSocket, (struct sockaddr*)&serverAddr, &len); - if (sock >= 0) { - partnerSocket = sock; - ESP_LOGI(TAG, "We have a new client connection %d", sock); - handle_telnet_conn(); - ESP_LOGI(TAG, "Telnet connection terminated %d", sock); - } else { - ESP_LOGW(TAG, "accept: %d (%s)", errno, strerror(errno)); - } - } + if (sock >= 0) { + partnerSocket = sock; + ESP_LOGI(TAG, "We have a new client connection %d", sock); + handle_telnet_conn(); + ESP_LOGI(TAG, "Telnet connection terminated %d", sock); + } else { + ESP_LOGW(TAG, "accept: %d (%s)", errno, strerror(errno)); + } + } - // we should not be here - close(serverSocket); - vTaskDelete(NULL); + // we should not be here + close(serverSocket); + vTaskDelete(NULL); } /** * Telnet handler. */ -static void handle_telnet_events(telnet_t *thisTelnet, telnet_event_t *event, void *userData) { - struct telnetUserData *telnetUserData = (struct telnetUserData *)userData; +static void handle_telnet_events(telnet_t* thisTelnet, telnet_event_t* event, void* userData) { + struct telnetUserData* telnetUserData = (struct telnetUserData*)userData; - switch(event->type) { - case TELNET_EV_SEND: - send(telnetUserData->sockfd, event->data.buffer, event->data.size, 0); - break; - case TELNET_EV_DATA: - console_push(event->data.buffer, event->data.size); - break; - case TELNET_EV_TTYPE: - telnet_ttype_send(telnetUserData->tnHandle); - break; - default: - break; - } + switch (event->type) { + case TELNET_EV_SEND: + send(telnetUserData->sockfd, event->data.buffer, event->data.size, 0); + break; + case TELNET_EV_DATA: + console_push(event->data.buffer, event->data.size); + break; + case TELNET_EV_TTYPE: + telnet_ttype_send(telnetUserData->tnHandle); + break; + default: + break; + } } -static size_t process_logs(UBaseType_t bytes, bool make_room){ - UBaseType_t pending; +static size_t process_logs(UBaseType_t bytes, bool make_room) { + UBaseType_t pending; - vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &pending); + vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &pending); - // nothing to do or we can do - if (!partnerSocket || (make_room && log_buf_size - pending > bytes)) return pending; + // nothing to do or we can do + if (!partnerSocket || (make_room && log_buf_size - pending > bytes)) return pending; - // can't send more than what we have - if (bytes > pending) bytes = pending; + // can't send more than what we have + if (bytes > pending) bytes = pending; - while (bytes > 0) { - size_t size; - char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &size, pdMS_TO_TICKS(50), bytes); - - if (!item || !partnerSocket) break; + while (bytes > 0) { + size_t size; + char* item = (char*)xRingbufferReceiveUpTo(buf_handle, &size, pdMS_TO_TICKS(50), bytes); - bytes -= size; - telnet_send_text(tnHandle, item, size); + if (!item || !partnerSocket) break; - vRingbufferReturnItem(buf_handle, (void *)item); - } + bytes -= size; + telnet_send_text(tnHandle, item, size); - return pending - bytes; + vRingbufferReturnItem(buf_handle, (void*)item); + } + + return pending - bytes; } static void handle_telnet_conn() { - static const telnet_telopt_t my_telopts[] = { - { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, - { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_ZMP, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_BINARY, TELNET_WILL, TELNET_DO }, - { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, - {TELNET_TELOPT_LINEMODE, TELNET_WONT, TELNET_DO }, - { -1, 0, 0 } - }; - struct telnetUserData *pTelnetUserData = (struct telnetUserData *)heap_caps_malloc(sizeof(struct telnetUserData), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData); + static const telnet_telopt_t my_telopts[] = {{TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO}, {TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT}, + {TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO}, {TELNET_TELOPT_ZMP, TELNET_WONT, TELNET_DO}, {TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO}, + {TELNET_TELOPT_BINARY, TELNET_WILL, TELNET_DO}, {TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT}, + {TELNET_TELOPT_LINEMODE, TELNET_WONT, TELNET_DO}, {-1, 0, 0}}; + struct telnetUserData* pTelnetUserData = + (struct telnetUserData*)heap_caps_malloc(sizeof(struct telnetUserData), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData); - pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - pTelnetUserData->tnHandle = tnHandle; - pTelnetUserData->sockfd = partnerSocket; + pTelnetUserData->rxbuf = (char*)heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + pTelnetUserData->tnHandle = tnHandle; + pTelnetUserData->sockfd = partnerSocket; - bool pending = true; + bool pending = true; - while(1) { - fd_set rfds, wfds; - struct timeval timeout = {0, 200*1000}; + while (1) { + fd_set rfds, wfds; + struct timeval timeout = {0, 200 * 1000}; - FD_ZERO(&rfds); - FD_SET(partnerSocket, &rfds); + FD_ZERO(&rfds); + FD_SET(partnerSocket, &rfds); - FD_ZERO(&wfds); - if (pending) FD_SET(partnerSocket, &wfds); + FD_ZERO(&wfds); + if (pending) FD_SET(partnerSocket, &wfds); - int res = select(partnerSocket + 1, &rfds, &wfds, NULL, &timeout); - if (res < 0) break; + int res = select(partnerSocket + 1, &rfds, &wfds, NULL, &timeout); + if (res < 0) break; - if (FD_ISSET(partnerSocket, &rfds)) { - int len = recv(partnerSocket, pTelnetUserData->rxbuf, TELNET_RX_BUF, 0); - if (!len) break; - telnet_recv(tnHandle, pTelnetUserData->rxbuf, len); - } + if (FD_ISSET(partnerSocket, &rfds)) { + int len = recv(partnerSocket, pTelnetUserData->rxbuf, TELNET_RX_BUF, 0); + if (!len) break; + telnet_recv(tnHandle, pTelnetUserData->rxbuf, len); + } - if (FD_ISSET(partnerSocket, &wfds)) { - pending = process_logs(send_chunk, false) > 0; - } else { - pending = true; - } - } - - telnet_free(tnHandle); - tnHandle = NULL; + if (FD_ISSET(partnerSocket, &wfds)) { + pending = process_logs(send_chunk, false) > 0; + } else { + pending = true; + } + } - free(pTelnetUserData->rxbuf); - free(pTelnetUserData); + telnet_free(tnHandle); + tnHandle = NULL; - close(partnerSocket); - partnerSocket = 0; + free(pTelnetUserData->rxbuf); + free(pTelnetUserData); + + close(partnerSocket); + partnerSocket = 0; } // ******************* stdout/stderr Redirection to ringbuffer -static ssize_t stdout_write(int fd, const void * data, size_t size) { - // flush the buffer and send item - if (buf_handle) { - process_logs(size, true); - xRingbufferSend(buf_handle, data, size, 0); - } - - // mirror to uart if required - return (bMirrorToUART || !buf_handle) ? write(uart_fd, data, size) : size; +static ssize_t stdout_write(int fd, const void* data, size_t size) { + // flush the buffer and send item + if (buf_handle) { + process_logs(size, true); + xRingbufferSend(buf_handle, data, size, 0); + } + + // mirror to uart if required + return (telnet_svc->enable == sys_telnet_output_TELNET_SERIAL || !buf_handle) ? write(uart_fd, data, size) : size; } -static int stdout_open(const char * path, int flags, int mode) { - return 0; -} +static int stdout_open(const char* path, int flags, int mode) { return 0; } -static int stdout_fstat(int fd, struct stat * st) { - st->st_mode = S_IFCHR; - return 0; +static int stdout_fstat(int fd, struct stat* st) { + st->st_mode = S_IFCHR; + return 0; } diff --git a/components/tools/CMakeLists.txt b/components/tools/CMakeLists.txt index 20950a0f..01c9a765 100644 --- a/components/tools/CMakeLists.txt +++ b/components/tools/CMakeLists.txt @@ -1,11 +1,10 @@ -idf_component_register( SRCS operator.cpp tools.c trace.c - REQUIRES esp_common pthread - PRIV_REQUIRES esp_http_client esp_http_server esp-tls json spiffs +set(CMAKE_CXX_STANDARD 20) +idf_component_register( SRC_DIRS . + REQUIRES esp_common pthread json spiffs + PRIV_REQUIRES esp_http_client esp_http_server esp-tls services INCLUDE_DIRS . ) #doing our own implementation of new operator for some pre-compiled binaries target_link_libraries(${COMPONENT_LIB} INTERFACE "-u _ZdlPv") target_link_libraries(${COMPONENT_LIB} INTERFACE "-u _Znwj") - - \ No newline at end of file diff --git a/components/tools/bootstate.cpp b/components/tools/bootstate.cpp new file mode 100644 index 00000000..5d5971cd --- /dev/null +++ b/components/tools/bootstate.cpp @@ -0,0 +1,143 @@ +#include "bootstate.h" +#include "Config.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_spi_flash.h" +#include "messaging.h" +#include "tools.h" +static const char* TAG = "bootstate"; + +RTC_NOINIT_ATTR uint32_t RebootCounter; +RTC_NOINIT_ATTR uint32_t RecoveryRebootCounter; +RTC_NOINIT_ATTR uint16_t ColdBootIndicatorFlag; +EXT_RAM_ATTR bool is_recovery_running = false; +EXT_RAM_ATTR bool cold_boot = true; +EXT_RAM_ATTR esp_reset_reason_t xReason = ESP_RST_UNKNOWN; +EXT_RAM_ATTR static bool restarting = false; + +uint32_t bootstate_read_counter(void) { return RebootCounter; } +uint32_t bootstate_uptate_counter(int32_t xValue) { + if (RebootCounter > 100) { + RebootCounter = 0; + RecoveryRebootCounter = 0; + } + RebootCounter = (xValue != 0) ? (RebootCounter + xValue) : 0; + RecoveryRebootCounter = (xValue != 0) && is_recovery_running ? (RecoveryRebootCounter + xValue) : 0; + return RebootCounter; +} + +void bootstate_handle_boot() { + if (ColdBootIndicatorFlag != 0xFACE) { + ESP_LOGI(TAG, "System is booting from power on."); + cold_boot = true; + ColdBootIndicatorFlag = 0xFACE; + } else { + cold_boot = false; + } + const esp_partition_t* running = esp_ota_get_running_partition(); + + xReason = esp_reset_reason(); + ESP_LOGI(TAG, "Reset reason is: %u. Running from partition %s type %s ", xReason, running->label, + running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY ? "Factory" : "Application"); + is_recovery_running = (running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY); + + if (!is_recovery_running) { + /* unscheduled restart (HW, Watchdog or similar) thus increment dynamic + * counter then log current boot statistics as a warning */ + uint32_t Counter = bootstate_uptate_counter(1); // increment counter + ESP_LOGI(TAG, "Reboot counter=%u\n", Counter); + if (Counter == 5) { + guided_factory(); + } + } else { + uint32_t Counter = bootstate_uptate_counter(1); // increment counter + if (RecoveryRebootCounter == 1 && Counter >= 5) { + // First time we are rebooting in recovery after crashing + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, + "System was forced into recovery mode after crash likely caused by some bad " + "configuration\n"); + } + ESP_LOGI(TAG, "Recovery Reboot counter=%u\n", Counter); + if (RecoveryRebootCounter == 5) { + ESP_LOGW(TAG, "System rebooted too many times. This could be an indication that " + "configuration is corrupted. Erasing config."); + if (config_erase_config()) { + config_raise_changed(true); + guided_factory(); + } else { + ESP_LOGE(TAG, "Error erasing configuration"); + } + } + if (RecoveryRebootCounter > 5) { + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, + "System was forced into recovery mode after crash likely caused by some bad " + "configuration. Configuration was reset to factory.\n"); + } + } +} +esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) { + if (is_recovery_running) { + if (partition_subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) { + simple_restart(); + } + } else { + if (partition_subtype != ESP_PARTITION_SUBTYPE_APP_FACTORY) { + simple_restart(); + } + } + esp_err_t err = ESP_OK; + const esp_partition_t* partition; + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL); + + if (it == NULL) { + log_send_messaging(MESSAGING_ERROR, "Reboot failed. Partitions error"); + } else { + ESP_LOGD(TAG, "Found partition. Getting info."); + partition = (esp_partition_t*)esp_partition_get(it); + ESP_LOGD(TAG, "Releasing partition iterator"); + esp_partition_iterator_release(it); + if (partition != NULL) { + log_send_messaging(MESSAGING_INFO, "Rebooting to %s", partition->label); + err = esp_ota_set_boot_partition(partition); + if (err != ESP_OK) { + log_send_messaging(MESSAGING_ERROR, "Unable to select partition for reboot: %s", esp_err_to_name(err)); + } + } else { + log_send_messaging(MESSAGING_ERROR, "partition type %u not found! Unable to reboot to recovery.", partition_subtype); + } + ESP_LOGD(TAG, "Yielding to other processes"); + taskYIELD(); + simple_restart(); + } + + return ESP_OK; +} +esp_err_t guided_restart_ota() { + log_send_messaging(MESSAGING_WARNING, "Booting to Squeezelite"); + guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); + return ESP_FAIL; // return fail. This should never return... we're rebooting! +} +esp_err_t guided_factory() { + log_send_messaging(MESSAGING_WARNING, "Booting to recovery"); + guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); + return ESP_FAIL; // return fail. This should never return... we're rebooting! +} +void simple_restart() { + restarting = true; + log_send_messaging(MESSAGING_WARNING, "Rebooting."); + + TimerHandle_t timer = xTimerCreate("reboot", 1, pdFALSE, nullptr, [](TimerHandle_t xTimer) { + if (!config_waitcommit()) { + log_send_messaging(MESSAGING_WARNING, "Waiting for configuration to commit "); + ESP_LOGD(TAG,"Queuing restart asynchronously to ensure all events are flushed."); + network_async_reboot(RESTART); + return; + } + vTaskDelay(750 / portTICK_PERIOD_MS); + esp_restart(); + xTimerDelete(xTimer, portMAX_DELAY); + }); + xTimerStart(timer, portMAX_DELAY); +} +bool is_restarting() { return restarting; } \ No newline at end of file diff --git a/components/tools/bootstate.h b/components/tools/bootstate.h new file mode 100644 index 00000000..332e3e90 --- /dev/null +++ b/components/tools/bootstate.h @@ -0,0 +1,126 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + +#pragma once +#include "esp_partition.h" +#include "esp_system.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +uint32_t bootstate_read_counter(void); + +/** + * @fn uint32_t bootstate_uptate_counter(int32_t xValue) + * Updates the boot state counter. + * + * Increments the RebootCounter by 'xValue'. If 'xValue' is 0, or if RebootCounter + * exceeds 100, it resets both RebootCounter and RecoveryRebootCounter to 0. + * Additionally, updates the RecoveryRebootCounter based on the recovery state. + * + * @param xValue The value to increment the RebootCounter. + * @return The updated value of the RebootCounter. + */ +uint32_t bootstate_uptate_counter(int32_t xValue); + +/** + * @fn void bootstate_handle_boot(void) + * Handles the boot state logic on system startup. + * + * This function manages boot states based on cold boot indicators, recovery states, and reboot counters. + * It includes logic for handling regular and recovery boots, and manages the boot counter's logic + * for different scenarios such as factory resets or configuration erasures. + */ +void bootstate_handle_boot(void); + +/** + * @fn esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) + * Performs a guided boot to a specified partition subtype. + * + * This function attempts to reboot the device to a specified partition subtype. + * It includes logic to handle different scenarios based on the current running state + * (normal or recovery) and the target partition subtype. + * + * @param partition_subtype The target partition subtype to boot to. + * @return ESP_OK on successful execution, or an ESP_ERR code on failure. + */ +esp_err_t guided_boot(esp_partition_subtype_t partition_subtype); + +/** + * @fn esp_err_t guided_restart_ota(void) + * Initiates a guided restart to an OTA (Over The Air) update partition. + * + * This function logs the intention to boot to the Squeezelite OTA partition and then + * calls guided_boot to execute the reboot. It always returns ESP_FAIL as the system + * is expected to reboot and not return from the function. + * + * @return ESP_FAIL to indicate the function should not return as a reboot is expected. + */ +esp_err_t guided_restart_ota(void); + +/** + * @fn esp_err_t guided_factory(void) + * Initiates a guided restart to the factory partition. + * + * This function logs the intention to boot to the recovery partition and then + * calls guided_boot to execute the reboot. It always returns ESP_FAIL as the system + * is expected to reboot and not return from the function. + * + * @return ESP_FAIL to indicate the function should not return as a reboot is expected. + */ +esp_err_t guided_factory(void); + +/** + * @fn void simple_restart(void) + * Performs a simple system restart. + * + * This function logs a reboot message, attempts to commit any pending configurations, + * waits for a short duration, and then triggers a system restart using `esp_restart`. + */ +void simple_restart(void); + +/** + * @fn bool is_restarting(void) + * Checks if the system is in the process of restarting. + * + * @return `true` if the system is currently restarting, `false` otherwise. + */ +bool is_restarting(void); + +/** + * @var extern bool is_recovery_running + * Indicates whether the system is currently running in recovery mode. + * + * This variable is used to determine the current operating mode of the system. + * It should be set to `true` when the system is operating in recovery mode, and + * `false` otherwise. As an external variable, it is likely defined and managed + * in another file/module. + */ +extern bool is_recovery_running; + +#ifdef __cplusplus +} +#endif diff --git a/components/tools/component.mk b/components/tools/component.mk deleted file mode 100644 index ace79fdb..00000000 --- a/components/tools/component.mk +++ /dev/null @@ -1,11 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# - -COMPONENT_SRCDIRS := . -COMPONENT_ADD_INCLUDEDIRS := . diff --git a/components/tools/cpp_tools.cpp b/components/tools/cpp_tools.cpp new file mode 100644 index 00000000..0cf20f97 --- /dev/null +++ b/components/tools/cpp_tools.cpp @@ -0,0 +1,22 @@ +#include "cpp_tools.h" +#include +#include "tools.h" + +std::string trim(const std::string& str) { + const size_t first = str.find_first_not_of(' '); + if (first == std::string::npos) { + // String contains only spaces or is empty + return ""; + } + const size_t last = str.find_last_not_of(' '); + return str.substr(first, (last - first + 1)); +} + +std::string& toLowerStr(std::string& str) { + for (auto& c : str) { + if (c >= 'A' && c <= 'Z') { + c = c - 'A' + 'a'; + } + } + return str; +} diff --git a/components/tools/cpp_tools.h b/components/tools/cpp_tools.h new file mode 100644 index 00000000..c37a98a0 --- /dev/null +++ b/components/tools/cpp_tools.h @@ -0,0 +1,48 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + +#ifdef __cplusplus +#include +/** + * @brief Trims leading and trailing whitespace from a string. + * + * This function removes all leading and trailing spaces from the given string. + * It does not modify the original string but returns a new trimmed string. + * + * @param str The string to trim. + * @return std::string A new string with leading and trailing spaces removed. + */ +std::string trim(const std::string& str); + +/** + * @brief Converts a string to lowercase. + * + * This function modifies the given string in place, converting all characters + * to their lowercase equivalents. + * + * @param str Reference to the string to be converted to lowercase. + * @return std::string& Reference to the modified string. + */ +std::string& toLowerStr(std::string& str); + +#endif diff --git a/components/tools/perf_trace.h b/components/tools/perf_trace.h index ca7bccc8..604901f6 100644 --- a/components/tools/perf_trace.h +++ b/components/tools/perf_trace.h @@ -1,18 +1,34 @@ -/* - * Squeezelite for esp32 +/* * - * (c) Sebastien 2019 - * Philippe G. 2019, philippe_44@outlook.com + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com * * This software is released under the MIT License. * https://opensource.org/licenses/MIT * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. */ - + #pragma once #include "sys/time.h" +#ifdef __cplusplus +extern "C" { +#endif + #define PERF_MAX LONG_MAX #define MIN_MAX_VAL(x) x==PERF_MAX?0:x #define CURR_SAMPLE_RATE output.current_sample_rate>0?output.current_sample_rate:1 @@ -76,3 +92,7 @@ static inline bool hasTimeElapsed(time_t delayMS, bool bforce) return false; } +#ifdef __cplusplus +} +#endif + diff --git a/components/tools/platform_esp32.h b/components/tools/platform_esp32.h index e7031607..2f291e30 100644 --- a/components/tools/platform_esp32.h +++ b/components/tools/platform_esp32.h @@ -26,8 +26,7 @@ #ifndef SQUEEZELITE_ESP32_RELEASE_URL #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" #endif -extern bool is_recovery_running; -extern bool wait_for_wifi(); + extern bool console_push(const char * data, size_t size); extern void console_start(); extern pthread_cond_t wifi_connect_suspend_cond; diff --git a/components/tools/test/CMakeLists.txt b/components/tools/test/CMakeLists.txt new file mode 100644 index 00000000..1ebbf047 --- /dev/null +++ b/components/tools/test/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRC_DIRS . + INCLUDE_DIRS "." + REQUIRES unity tools) +target_include_directories(${COMPONENT_LIB} PUBLIC SYSTEM ${CMAKE_SOURCE_DIR}/test_main) \ No newline at end of file diff --git a/components/tools/test/test_tools.cpp b/components/tools/test/test_tools.cpp new file mode 100644 index 00000000..ee99af55 --- /dev/null +++ b/components/tools/test/test_tools.cpp @@ -0,0 +1,387 @@ +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "esp_log.h" +#include "test_common_init.h" +#include "tools.h" +#include "unity.h" +#include +#include +#include +#include "tools_spiffs_utils.h" + +static const char* TAG = "test_tools"; + +static const char* data = "SomeTestData\0"; +#define UINT8T_DATA (const uint8_t*)data +static size_t len = strlen(data); + +TEST_CASE("Test Write/Read File", "[tools]") { + common_test_init(); + const char* testfilename = "/spiffs/test_file.bin"; + size_t loaded = 0; + // allow +1 to the length below for null termination of the string + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len + 1, testfilename)); + char* loaded_data = (char*)load_file_psram(&loaded, testfilename); + TEST_ASSERT_EQUAL(loaded, len + 1); + TEST_ASSERT_NOT_EQUAL(loaded_data, NULL); + TEST_ASSERT_EQUAL_STRING((const char*)data, (char*)loaded_data); + free(loaded_data); +} + +TEST_CASE("Test Simple Erase File ", "[tools]") { + std::ostringstream fullfilename; + const char* prefix = "test_file"; + + struct stat fileInfo; + // test for simple file names + fullfilename << "/spiffs/" << prefix << ".bin"; + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len, fullfilename.str().c_str())); + TEST_ASSERT_TRUE(get_file_info(&fileInfo, fullfilename.str().c_str())); + TEST_ASSERT_EQUAL(fileInfo.st_size, len); + TEST_ASSERT_TRUE(erase_path(fullfilename.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullfilename.str().c_str())); + fullfilename.clear(); + fullfilename.str(""); +} +TEST_CASE("Test Wildcard Erase File ", "[tools]") { + std::ostringstream fullfilename; + std::ostringstream fullfilename2; + std::ostringstream fullnamewc; + const char* prefix = "/spiffs/test_file"; + struct stat fileInfo; + // Test for wildcard + + fullfilename << prefix << ".bin"; + fullfilename2 << prefix << ".bin2"; + fullnamewc << prefix << "*.bin"; + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len, fullfilename.str().c_str())); + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len, fullfilename2.str().c_str())); + TEST_ASSERT_TRUE(get_file_info(&fileInfo, fullfilename.str().c_str())); + TEST_ASSERT_EQUAL(fileInfo.st_size, len); + TEST_ASSERT_TRUE(erase_path(fullnamewc.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullfilename.str().c_str())); + TEST_ASSERT_TRUE(get_file_info(&fileInfo, fullfilename2.str().c_str())); + fullnamewc.str(""); + fullnamewc << prefix << ".bin*"; + TEST_ASSERT_TRUE(erase_path(fullnamewc.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullfilename2.str().c_str())); +} +TEST_CASE("Test Folder Erase File ", "[tools]") { + std::ostringstream fullfilename; + const char* prefix = "test_file"; + struct stat fileInfo; + fullfilename << "/spiffs/somefolder/" << prefix << ".bin"; + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len, fullfilename.str().c_str())); + TEST_ASSERT_TRUE(get_file_info(&fileInfo, fullfilename.str().c_str())); + TEST_ASSERT_EQUAL(fileInfo.st_size, len); + TEST_ASSERT_TRUE(erase_path(fullfilename.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullfilename.str().c_str())); +} +TEST_CASE("Test Folder Wildcard Erase File ", "[tools]") { + std::ostringstream fullfilename; + std::ostringstream fullnamewc; + const char* prefix = "test_file"; + struct stat fileInfo; + + fullfilename << "/spiffs/somefolder/" << prefix << ".bin"; + fullnamewc << prefix << "*.bin"; + TEST_ASSERT_TRUE(write_file(UINT8T_DATA, len, fullfilename.str().c_str())); + TEST_ASSERT_TRUE(get_file_info(&fileInfo, fullfilename.str().c_str())); + TEST_ASSERT_EQUAL(fileInfo.st_size, len); + TEST_ASSERT_TRUE(erase_path(fullfilename.str().c_str(), false)); + TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullnamewc.str().c_str())); +} + +const std::vector testRestrictedFiles = {"defaults/config.bin", + "fonts/droid_sans_fb_11x13.bin", "targets/bureau-oled/config.bin", "www/favicon-32x32.png"}; + +TEST_CASE("Test _write_file Function", "[tools]") { + init_spiffs(); + const uint8_t testData[] = {0x01, 0x02, 0x03, 0x04}; + size_t testDataSize = sizeof(testData); + const char* testFileName = "/spiffs/testfile.bin"; + + // Test writing valid data + TEST_ASSERT_TRUE(write_file(testData, testDataSize, testFileName)); + + // Verify file size + struct stat fileInfo; + TEST_ASSERT_TRUE(get_file_info(&fileInfo, testFileName)); + TEST_ASSERT_EQUAL_UINT32(testDataSize, fileInfo.st_size); + + // Verify file content + size_t loadedSize; + uint8_t* loadedData = (uint8_t*)load_file_psram(&loadedSize, testFileName); + TEST_ASSERT_NOT_NULL(loadedData); + TEST_ASSERT_EQUAL_UINT32(testDataSize, loadedSize); + TEST_ASSERT_EQUAL_UINT8_ARRAY(testData, loadedData, testDataSize); + free(loadedData); + ESP_LOGI(TAG, "Erasing test file"); + TEST_ASSERT_TRUE(erase_path(testFileName, false)); + + // Test writing with null data + ESP_LOGI(TAG, "Test Invalid write_file with NULL pointer"); + TEST_ASSERT_FALSE(write_file(NULL, testDataSize, testFileName)); + + // Test writing with zero size + ESP_LOGI(TAG, "Test Invalid write_file with data length 0"); + TEST_ASSERT_FALSE(write_file(testData, 0, testFileName)); +} + +TEST_CASE("Test _open_file Function", "[tools]") { + init_spiffs(); + const char* testFileName = "/spiffs/test_open_file.bin"; + const char* testFileContent = "Hello, world!"; + size_t contentLength = strlen(testFileContent); + + // Test opening a file for writing + FILE* writeFile = fopen(testFileName, "w"); + TEST_ASSERT_NOT_NULL(writeFile); + fwrite(testFileContent, 1, contentLength, writeFile); + fclose(writeFile); + + // Test opening the same file for reading + FILE* readFile = fopen(testFileName, "r"); + TEST_ASSERT_NOT_NULL(readFile); + char buffer[100]; + size_t bytesRead = fread(buffer, 1, contentLength, readFile); + TEST_ASSERT_EQUAL_UINT32(contentLength, bytesRead); + buffer[bytesRead] = '\0'; // Null-terminate the string + TEST_ASSERT_EQUAL_STRING(testFileContent, buffer); + fclose(readFile); + + // Test opening a file with an invalid mode + FILE* invalidFile = fopen(testFileName, "invalid_mode"); + TEST_ASSERT_NULL(invalidFile); + + TEST_ASSERT_TRUE(erase_path(testFileName, false)); + + // Test opening a non-existent file for reading + FILE* nonExistentFile = fopen("/spiffs/non_existent_file.bin", "r"); + TEST_ASSERT_NULL(nonExistentFile); +} + +TEST_CASE("Test _load_file and _get_file_info Functions", "[tools]") { + init_spiffs(); + const char* testFileName = "/spiffs/test_load_file.bin"; + const char* testFileContent = "Hello, world!"; + size_t contentLength = strlen(testFileContent); + + // Write test data to a file + FILE* writeFile = fopen(testFileName, "w"); + TEST_ASSERT_NOT_NULL(writeFile); + fwrite(testFileContent, 1, contentLength, writeFile); + fclose(writeFile); + + // Test loading file content + size_t loadedSize; + uint8_t* loadedData = (uint8_t*)load_file_psram(&loadedSize, testFileName); + TEST_ASSERT_NOT_NULL(loadedData); + TEST_ASSERT_EQUAL_UINT32(contentLength, loadedSize); + TEST_ASSERT_EQUAL_UINT8_ARRAY(testFileContent, loadedData, contentLength); + free(loadedData); + + // Test getting file information + struct stat fileInfo; + TEST_ASSERT_TRUE(get_file_info(&fileInfo, testFileName)); + TEST_ASSERT_EQUAL_UINT32(contentLength, fileInfo.st_size); + TEST_ASSERT_TRUE(erase_path(testFileName, false)); + + // Test loading a non-existent file + uint8_t* nonExistentData = + (uint8_t*)load_file_psram(&loadedSize, "/spiffs/non_existent_file.bin"); + TEST_ASSERT_NULL(nonExistentData); + + // Test getting information for a non-existent file + TEST_ASSERT_FALSE(get_file_info(&fileInfo, "/spiffs/non_existent_file.bin")); +} + +TEST_CASE("Test trim Function", "[tools]") { + // Test trimming a string with leading and trailing spaces + std::string str1 = " Hello World "; + TEST_ASSERT_EQUAL_STRING("Hello World", trim(str1).c_str()); + + // Test trimming a string with no leading or trailing spaces + std::string str2 = "Hello World"; + TEST_ASSERT_EQUAL_STRING("Hello World", trim(str2).c_str()); + + // Test trimming an empty string + std::string str3 = ""; + TEST_ASSERT_EQUAL_STRING("", trim(str3).c_str()); + + // Test trimming a string with only spaces + std::string str4 = " "; + TEST_ASSERT_EQUAL_STRING("", trim(str4).c_str()); +} + +TEST_CASE("Test toLowerStr Function", "[tools]") { + // Test converting a mixed case string to lowercase + std::string str1 = "Hello World"; + toLowerStr(str1); + TEST_ASSERT_EQUAL_STRING("hello world", str1.c_str()); + + // Test converting an already lowercase string + std::string str2 = "hello world"; + toLowerStr(str2); + TEST_ASSERT_EQUAL_STRING("hello world", str2.c_str()); + + // Test converting an uppercase string + std::string str3 = "HELLO WORLD"; + toLowerStr(str3); + TEST_ASSERT_EQUAL_STRING("hello world", str3.c_str()); + + // Test converting an empty string + std::string str4 = ""; + toLowerStr(str4); + TEST_ASSERT_EQUAL_STRING("", str4.c_str()); + + // Test converting a string with special characters + std::string str5 = "Hello-World_123"; + toLowerStr(str5); + TEST_ASSERT_EQUAL_STRING("hello-world_123", str5.c_str()); +} +static const std::vector testRestrictedPaths = { + "/spiffs/defaults/file.txt", // A restricted path + "/spiffs/fonts/otherfile.txt", // A restricted path + "/spiffs/targets/somefile.txt", // A restricted path + "/spiffs/targets/*.txt", // A restricted path + "/spiffs/www/index.html" // A restricted path +}; +TEST_CASE("Test is_restricted_path with restricted paths", "[tools]") { + for (const std::string& path : testRestrictedPaths) { + bool result = is_restricted_path(path.c_str()); + TEST_ASSERT_TRUE(result); + } +} + +// Negative Testing +TEST_CASE("Test is_restricted_path with non-restricted paths", "[tools]") { + const std::vector nonRestrictedPaths = { + "/spiffs/allowed/file.txt", // Not a restricted path + "/spiffs/allowed/otherfile.txt" // Not a restricted path + }; + + for (const std::string& path : nonRestrictedPaths) { + bool result = is_restricted_path(path.c_str()); + TEST_ASSERT_FALSE(result); + } +} +static const std::vector testWildcardPaths = { + "/spiffs/defaults/file.txt", // A restricted path + "/spiffs/fonts/otherfile.txt", // A restricted path + "/spiffs/targets/somefile.txt", // A restricted path + "/spiffs/www/index.html", // A restricted path + "/spiffs/defaults/*", // A path with wildcard + "/spiffs/fonts/*" // A path with wildcard +}; +TEST_CASE("Test is_restricted_path with wildcards (positive)", "[tools]") { + for (const std::string& path : testWildcardPaths) { + bool result = is_restricted_path(path.c_str()); + if (!result) { + ESP_LOGE(TAG, "Unexpected result. File should be restricted: %s", path.c_str()); + } + TEST_ASSERT_TRUE(result); + } +} + +TEST_CASE("Test Erase Restricted Path", "[erase_path]") { + + for (const std::string& path : testRestrictedFiles) { + std::ostringstream fullfilename; + fullfilename << "/spiffs/" << path; + + // Check if the file exists before erasing + struct stat fileInfoBefore; + TEST_ASSERT_TRUE(get_file_info(&fileInfoBefore, fullfilename.str().c_str())); + + // Attempt to erase the restricted path + TEST_ASSERT_FALSE(erase_path(fullfilename.str().c_str(), true)); + + // Check if the file still exists after the erase attempt + struct stat fileInfoAfter; + TEST_ASSERT_TRUE(get_file_info(&fileInfoAfter, fullfilename.str().c_str())); + TEST_ASSERT_EQUAL(fileInfoBefore.st_ino, fileInfoAfter.st_ino); + } +} + +// Test case to attempt erasing restricted files with wildcards +TEST_CASE("Test Erase Restricted Files with Wildcards", "[erase_path]") { + // Get a list of restricted files based on restrictedPaths + std::list restrictedFiles = get_files_list(std::string("/")); + + for (const tools_file_entry_t& restrictedFile : restrictedFiles) { + std::string fullfilename = "/" + restrictedFile.name; + + // Check if the file exists before erasing + struct stat fileInfoBefore; + TEST_ASSERT_TRUE(get_file_info(&fileInfoBefore, fullfilename.c_str())); + + // Attempt to erase the file with wildcard pattern + TEST_ASSERT_FALSE(erase_path(fullfilename.c_str(), true)); + + // Check if the file still exists after the erase attempt + struct stat fileInfoAfter; + TEST_ASSERT_TRUE(get_file_info(&fileInfoAfter, fullfilename.c_str())); + TEST_ASSERT_EQUAL(fileInfoBefore.st_ino, fileInfoAfter.st_ino); + } +} +// Test case to create a file and delete it bypassing restrictions +TEST_CASE("Test Create and Delete File Bypassing Restrictions", "[erase_path]") { + const uint8_t testData[] = {0x01, 0x02, 0x03, 0x04}; + size_t testDataSize = sizeof(testData); + const char* testFileName = "/spiffs/defaults/test_file.bin"; + + // Test writing valid data to create the file + TEST_ASSERT_TRUE(write_file(testData, testDataSize, testFileName)); + + // Verify file size + struct stat fileInfo; + TEST_ASSERT_TRUE(get_file_info(&fileInfo, testFileName)); + TEST_ASSERT_EQUAL_UINT32(testDataSize, fileInfo.st_size); + + // Attempt to erase the file with bypassing restrictions (false) + TEST_ASSERT_TRUE(erase_path(testFileName, false)); + + // Verify that the file no longer exists + TEST_ASSERT_FALSE(get_file_info(&fileInfo, testFileName)); +} + +// Test function to create a file, check its presence and unrestricted status, and delete it +TEST_CASE("Create, Check, and Delete File in SPIFFS", "[spiffs]") { + const char* testFileName = "/spiffs/somerandomfile.bin"; + const uint8_t testData[] = {0x01, 0x02, 0x03, 0x04}; + size_t testDataSize = sizeof(testData); + + // Create a file + TEST_ASSERT_TRUE(write_file(testData, testDataSize, testFileName)); + + // Get the list of files + std::list fileList = get_files_list("/spiffs"); + + // Check if the new file is in the list and is unrestricted + bool fileFound = false; + bool fileUnrestricted = false; + for (const auto& fileEntry : fileList) { + if (fileEntry.name == testFileName) { + fileFound = true; + fileUnrestricted = !fileEntry.restricted; + break; + } + } + + TEST_ASSERT_TRUE(fileFound); + TEST_ASSERT_TRUE(fileUnrestricted); + + // Delete the file + TEST_ASSERT_TRUE(erase_path(testFileName, false)); // Assuming false bypasses restrictions + fileFound = false; + // Verify that the file no longer exists + fileList = get_files_list("/spiffs"); + for (const auto& fileEntry : fileList) { + if (std::string(testFileName) == fileEntry.name) { + fileFound = true; + break; + } + } + + TEST_ASSERT_FALSE(fileFound); +} \ No newline at end of file diff --git a/components/tools/tools.c b/components/tools/tools.c index 676ee236..c02d49b0 100644 --- a/components/tools/tools.c +++ b/components/tools/tools.c @@ -6,25 +6,22 @@ * https://opensource.org/licenses/MIT * */ -// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#define LOG_LOCAL_LEVEL ESP_LOG_INFO #include "tools.h" #include "esp_heap_caps.h" -#include "esp_http_client.h" #include "esp_log.h" #include "esp_task.h" -#include "esp_tls.h" + #include #include -#include #include -#include -#include "esp_http_server.h" #if CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS < 2 #error CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS must be at least 2 #endif -static bool initialized = false; + const static char TAG[] = "tools"; -static esp_vfs_spiffs_conf_t* spiffs_conf = NULL; +const char unknown_string_placeholder[] = "unknown"; +const char null_string_placeholder[] = "null"; /**************************************************************************************** * UTF-8 tools @@ -67,6 +64,15 @@ static const uint8_t utf8d[] = { 1, // s7..s8 }; +/** + * @fn static uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) + * Decodes a single UTF-8 encoded byte. + * + * @param state A pointer to the current state of the UTF-8 decoder. + * @param codep A pointer to the code point being built from the UTF-8 bytes. + * @param byte The current byte to be decoded. + * @return The new state after processing the byte. + */ static uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) { uint32_t type = utf8d[byte]; @@ -76,6 +82,13 @@ static uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) { return *state; } +/** + * @fn static uint8_t UNICODEtoCP1252(uint16_t chr) + * Converts a Unicode character to its corresponding CP1252 character. + * + * @param chr The Unicode character to be converted. + * @return The corresponding CP1252 character or 0x00 if there is no direct mapping. + */ static uint8_t UNICODEtoCP1252(uint16_t chr) { if (chr <= 0xff) return (chr & 0xff); @@ -181,27 +194,6 @@ void utf8_decode(char* src) { *dst = '\0'; } -/**************************************************************************************** - * URL tools - */ - -static inline char from_hex(char ch) { return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; } - -void url_decode(char* url) { - char *p, *src = strdup(url); - for (p = src; *src; url++) { - *url = *src++; - if (*url == '%') { - *url = from_hex(*src++) << 4; - *url |= from_hex(*src++); - } else if (*url == '+') { - *url = ' '; - } - } - *url = '\0'; - free(p); -} - /**************************************************************************************** * Memory tools */ @@ -233,8 +225,7 @@ char* strdup_psram(const char* source) { size_t source_sz = strlen(source) + 1; ptr = heap_caps_malloc(source_sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (ptr == NULL) { - ESP_LOGE(TAG, "strdup_psram: unable to allocate %d bytes of PSRAM! Cannot clone string %s", - source_sz, source); + ESP_LOGE(TAG, "strdup_psram: unable to allocate %d bytes of PSRAM! Cannot clone string %s", source_sz, source); } else { memset(ptr, 0x00, source_sz); strcpy(ptr, source); @@ -247,27 +238,42 @@ char* strdup_psram(const char* source) { */ #define TASK_TLS_INDEX 1 +/** + * @struct task_context_t + * Structure to hold the context of a task including its task buffer and stack. + * + * @var StaticTask_t* xTaskBuffer + * Pointer to the task's control block. + * + * @var StackType_t* xStack + * Pointer to the task's stack. + */ typedef struct { StaticTask_t* xTaskBuffer; StackType_t* xStack; } task_context_t; +/** + * @fn static void task_cleanup(int index, task_context_t* context) + * Cleans up the resources allocated for a task. + * This function is intended to be used as a callback for task deletion. + * + * @param index The TLS index where the task's context is stored. + * @param context Pointer to the task's context to be cleaned up. + */ static void task_cleanup(int index, task_context_t* context) { free(context->xTaskBuffer); free(context->xStack); free(context); } -BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName, - configSTACK_DEPTH_TYPE usStackDepth, void* pvParameters, UBaseType_t uxPriority, - TaskHandle_t* pxCreatedTask) { +BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName, configSTACK_DEPTH_TYPE usStackDepth, void* pvParameters, + UBaseType_t uxPriority, TaskHandle_t* pxCreatedTask) { // create the worker task as a static task_context_t* context = calloc(1, sizeof(task_context_t)); - context->xTaskBuffer = (StaticTask_t*)heap_caps_malloc( - sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)); + context->xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)); context->xStack = heap_caps_malloc(usStackDepth, (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); - TaskHandle_t handle = xTaskCreateStatic(pvTaskCode, pcName, usStackDepth, pvParameters, - uxPriority, context->xStack, context->xTaskBuffer); + TaskHandle_t handle = xTaskCreateStatic(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, context->xStack, context->xTaskBuffer); // store context in TCB or free everything in case of failure if (!handle) { @@ -275,8 +281,7 @@ BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName free(context->xStack); free(context); } else { - vTaskSetThreadLocalStoragePointerAndDelCallback( - handle, TASK_TLS_INDEX, context, (TlsDeleteCallbackFunction_t)task_cleanup); + vTaskSetThreadLocalStoragePointerAndDelCallback(handle, TASK_TLS_INDEX, context, (TlsDeleteCallbackFunction_t)task_cleanup); } if (pxCreatedTask) *pxCreatedTask = handle; @@ -291,104 +296,6 @@ void vTaskDeleteEXTRAM(TaskHandle_t xTask) { vTaskDelete(xTask); } -/**************************************************************************************** - * URL download - */ - -typedef struct { - void* user_context; - http_download_cb_t callback; - size_t max, bytes; - bool abort; - uint8_t* data; - esp_http_client_handle_t client; -} http_context_t; - -static void http_downloader(void* arg); -static esp_err_t http_event_handler(esp_http_client_event_t* evt); - -void http_download(char* url, size_t max, http_download_cb_t callback, void* context) { - http_context_t* http_context = - (http_context_t*)heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM); - - esp_http_client_config_t config = { - .url = url, - .event_handler = http_event_handler, - .user_data = http_context, - }; - - http_context->callback = callback; - http_context->user_context = context; - http_context->max = max; - http_context->client = esp_http_client_init(&config); - - xTaskCreateEXTRAM( - http_downloader, "downloader", 8 * 1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL); -} - -static void http_downloader(void* arg) { - http_context_t* http_context = (http_context_t*)arg; - - esp_http_client_perform(http_context->client); - esp_http_client_cleanup(http_context->client); - - free(http_context); - vTaskDeleteEXTRAM(NULL); -} - -static esp_err_t http_event_handler(esp_http_client_event_t* evt) { - http_context_t* http_context = (http_context_t*)evt->user_data; - - if (http_context->abort) return ESP_FAIL; - - switch (evt->event_id) { - case HTTP_EVENT_ERROR: - http_context->callback(NULL, 0, http_context->user_context); - http_context->abort = true; - break; - case HTTP_EVENT_ON_HEADER: - if (!strcasecmp(evt->header_key, "Content-Length")) { - size_t len = atoi(evt->header_value); - if (!len || len > http_context->max) { - ESP_LOGI(TAG, "content-length null or too large %zu / %zu", len, http_context->max); - http_context->abort = true; - } - } - break; - case HTTP_EVENT_ON_DATA: { - size_t len = esp_http_client_get_content_length(evt->client); - if (!http_context->data) { - if ((http_context->data = (uint8_t*)malloc(len)) == NULL) { - http_context->abort = true; - ESP_LOGE(TAG, "failed to allocate memory for output buffer %zu", len); - return ESP_FAIL; - } - } - memcpy(http_context->data + http_context->bytes, evt->data, evt->data_len); - http_context->bytes += evt->data_len; - break; - } - case HTTP_EVENT_ON_FINISH: - http_context->callback(http_context->data, http_context->bytes, http_context->user_context); - break; - case HTTP_EVENT_DISCONNECTED: { - int mbedtls_err = 0; - esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL); - if (err != ESP_OK) { - ESP_LOGE(TAG, "HTTP download disconnect %d", err); - if (http_context->data) free(http_context->data); - http_context->callback(NULL, 0, http_context->user_context); - return ESP_FAIL; - } - break; - } - default: - break; - } - - return ESP_OK; -} - void dump_json_content(const char* prefix, cJSON* json, int level) { if (!json) { ESP_LOG_LEVEL(level, TAG, "%s: empty!", prefix); @@ -400,159 +307,10 @@ void dump_json_content(const char* prefix, cJSON* json, int level) { } FREE_AND_NULL(output); } -void init_spiffs() { - if (initialized) { - ESP_LOGD(TAG, "SPIFFS already initialized. returning"); - return; - } - ESP_LOGI(TAG, "Initializing the SPI File system"); - spiffs_conf = (esp_vfs_spiffs_conf_t*)malloc(sizeof(esp_vfs_spiffs_conf_t)); - spiffs_conf->base_path = "/spiffs"; - spiffs_conf->partition_label = NULL; - spiffs_conf->max_files = 5; - spiffs_conf->format_if_mount_failed = true; - - // Use settings defined above to initialize and mount SPIFFS filesystem. - // Note: esp_vfs_spiffs_register is an all-in-one convenience function. - esp_err_t ret = esp_vfs_spiffs_register(spiffs_conf); - if (ret != ESP_OK) { - if (ret == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } else if (ret == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } else { - ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); - } - return; - } - - size_t total = 0, used = 0; - ret = esp_spiffs_info(spiffs_conf->partition_label, &total, &used); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", - esp_err_to_name(ret)); - esp_spiffs_format(spiffs_conf->partition_label); - } else { - ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); - } - - - initialized = true; -} - -// Function to safely append a path part with '/' if needed -void append_path_part(char** dest, const char* part) { - if ((*dest)[-1] != '/' && part[0] != '/') { - strcat(*dest, "/"); - *dest += 1; // Move the pointer past the '/' - } - strcat(*dest, part); - *dest += strlen(part); -} - -// Function to calculate the total length needed for the new path -size_t calculate_total_length(const char* base_path, va_list args) { - ESP_LOGV(TAG, "%s, Starting with base path: %s", "calculate_total_length", base_path); - size_t length = strlen(base_path) + 1; // +1 for null terminator - const char* part; - va_list args_copy; - va_copy(args_copy, args); - while ((part = va_arg(args_copy, const char*)) != NULL) { - ESP_LOGV(TAG, "Adding length of %s", part); - length += strlen(part) + 1; // +1 for potential '/' - } - ESP_LOGV(TAG, "Done looping. calculated length: %d", length); - va_end(args_copy); - return length; -} - -// Main function to join paths -char* __alloc_join_path(const char* base_path, va_list args) { - size_t count = 0; - ESP_LOGD(TAG, "Getting path length starting with %s", base_path); - size_t total_length = calculate_total_length(base_path, args); - - // Allocate memory - char* full_path = malloc_init_external(total_length); - if (!full_path) { - ESP_LOGE(TAG, "Unable to allocate memory for path"); - return NULL; - } - - // Start constructing the path - strcpy(full_path, base_path); - char* current_position = full_path + strlen(full_path); - - // Append each path part - const char* part; - while ((part = va_arg(args, const char*)) != NULL) { - append_path_part(¤t_position, part); - } - *current_position = '\0'; // Null-terminate the string - return full_path; -} -char* _alloc_join_path(const char* base_path, ...) { - va_list args; - ESP_LOGD(TAG, "%s", "join_path_var_parms"); - va_start(args, base_path); - char* result = __alloc_join_path(base_path, args); - va_end(args); - return result; -} - -FILE* __open_file(const char* mode, va_list args) { - FILE* file = NULL; - char* fullfilename = __alloc_join_path(spiffs_conf->base_path, args); - if (!fullfilename) { - ESP_LOGE(TAG, "Open file failed: unable to determine name"); - } else { - ESP_LOGI(TAG, "Opening file %s in mode %s ", fullfilename, mode); - file = fopen(fullfilename, mode); - } - if (file == NULL) { - ESP_LOGE(TAG, "Open file failed"); - } - if (fullfilename) free(fullfilename); - return file; -} -FILE* _open_file(const char* mode, ...) { - va_list args; - FILE* file = NULL; - va_start(args, mode); - file = __open_file(mode, args); - va_end(args); - return file; -} -bool _write_file(uint8_t* data, size_t sz, ...) { - bool result = true; - FILE* file = NULL; - va_list args; - if (data == NULL) { - ESP_LOGE(TAG, "Cannot write file. Data not received"); - return false; - } - if (sz == 0) { - ESP_LOGE(TAG, "Cannot write file. Data length 0"); - return false; - } - va_start(args, sz); - file = __open_file("w+", args); - va_end(args); - if (file == NULL) { - return false; - } - size_t written = fwrite(data, 1, sz, file); - if (written != sz) { - ESP_LOGE(TAG, "Write error. Wrote %d bytes of %d.", written, sz); - result = false; - } - fclose(file); - return result; -} const char* get_mem_flag_desc(int flags) { - static char flagString[101]; - memset(flagString,0x00,sizeof(flagString)); + static char flagString[101]; + memset(flagString, 0x00, sizeof(flagString)); if (flags & MALLOC_CAP_EXEC) strcat(flagString, "EXEC "); if (flags & MALLOC_CAP_32BIT) strcat(flagString, "32BIT "); if (flags & MALLOC_CAP_8BIT) strcat(flagString, "8BIT "); @@ -571,65 +329,7 @@ const char* get_mem_flag_desc(int flags) { return flagString; } -void* _load_file(uint32_t memflags,size_t* sz, ...) { - void* data = NULL; - FILE* file = NULL; - size_t fsz = 0; - va_list args; - va_start(args, sz); - file = __open_file("rb", args); - va_end(args); - if (file == NULL) { - return data; - } - fseek(file, 0, SEEK_END); - fsz = ftell(file); - fseek(file, 0, SEEK_SET); - if (fsz > 0) { - ESP_LOGD(TAG, "Allocating %d bytes to load file content with flags: %s ", fsz,get_mem_flag_desc(memflags)); - data = (void*)heap_caps_calloc(1, fsz, memflags); - if (data == NULL) { - ESP_LOGE(TAG, "Failed to allocate %d bytes to load file", fsz); - } else { - fread(data, 1, fsz, file); - if (sz) { - *sz = fsz; - } - } - } else { - ESP_LOGW(TAG, "File is empty. Nothing to read"); - } - fclose(file); - return data; -} -bool _get_file_info(struct stat* pfileInfo, ...) { - va_list args; - struct stat fileInfo; - va_start(args, pfileInfo); - char* fullfilename = __alloc_join_path(spiffs_conf->base_path, args); - va_end(args); - ESP_LOGD(TAG, "Getting file info for %s", fullfilename); - - if (!fullfilename) { - ESP_LOGE(TAG, "Failed to construct full file path"); - return false; - } - bool result = false; - // Use stat to fill the fileInfo structure - if (stat(fullfilename, &fileInfo) != 0) { - ESP_LOGD(TAG, "File %s not found", fullfilename); - } else { - result = true; - if (pfileInfo) { - memcpy(pfileInfo, &fileInfo, sizeof(fileInfo)); - } - ESP_LOGD(TAG, "File %s has %lu bytes", fullfilename, fileInfo.st_size); - } - - free(fullfilename); - return result; -} #define LOCAL_MAC_SIZE 10 const char* get_mac_str() { uint8_t mac[6]; @@ -644,111 +344,89 @@ const char* get_mac_str() { return macStr; } char* alloc_get_string_with_mac(const char* val) { - uint8_t mac[6]; - char macStr[LOCAL_MAC_SIZE + 1]; - char* fullvalue = NULL; - esp_read_mac((uint8_t*)&mac, ESP_MAC_WIFI_STA); - snprintf(macStr, LOCAL_MAC_SIZE - 1, "-%x%x%x", mac[3], mac[4], mac[5]); - fullvalue = (char*)malloc_init_external(strlen(val) + sizeof(macStr) + 1); + const char* macstr = get_mac_str(); + char* fullvalue = (char*)malloc_init_external(strlen(val) + sizeof(macstr) + 1); if (fullvalue) { strcpy(fullvalue, val); - strcat(fullvalue, macStr); + strcat(fullvalue, macstr); } else { ESP_LOGE(TAG, "malloc failed for value %s", val); } return fullvalue; } -void listFiles(const char *path_requested) { - DIR *dir = NULL; - char * sep="---------------------------------------------------------\n"; - struct dirent *ent; - char type; - char size[21]; - char tpath[255]; - struct stat sb; - struct tm *tm_info; - char *lpath = NULL; - int statok; - char * path= alloc_join_path(spiffs_conf->base_path,path_requested); - printf("\nList of Directory [%s]\n", path); - printf(sep); - // Open directory - dir = opendir(path); - if (!dir) { - printf("Error opening directory\n"); - free(path); - return; +char* alloc_get_fallback_unique_name() { +#ifdef CONFIG_LWIP_LOCAL_HOSTNAME + return alloc_get_string_with_mac(CONFIG_LWIP_LOCAL_HOSTNAME "-"); +#elif defined(CONFIG_FW_PLATFORM_NAME) + return alloc_get_string_with_mac(CONFIG_FW_PLATFORM_NAME "-"); +#else + return alloc_get_string_with_mac("squeezelite-"); +#endif +} + +#define LOCAL_MAC_SIZE 20 +char* alloc_get_formatted_mac_string(uint8_t mac[6]) { + char* macStr = malloc_init_external(LOCAL_MAC_SIZE); + if (macStr) { + snprintf(macStr, LOCAL_MAC_SIZE, MACSTR, MAC2STR(mac)); + } + return macStr; +} + +const char* str_or_unknown(const char* str) { return (str ? str : unknown_string_placeholder); } +const char* str_or_null(const char* str) { return (str ? str : null_string_placeholder); } + +esp_log_level_t get_log_level_from_char(char* level) { + if (!strcasecmp(level, "NONE")) { + return ESP_LOG_NONE; + } + if (!strcasecmp(level, "ERROR")) { + return ESP_LOG_ERROR; + } + if (!strcasecmp(level, "WARN")) { + return ESP_LOG_WARN; + } + if (!strcasecmp(level, "INFO")) { + return ESP_LOG_INFO; + } + if (!strcasecmp(level, "DEBUG")) { + return ESP_LOG_DEBUG; + } + if (!strcasecmp(level, "VERBOSE")) { + return ESP_LOG_VERBOSE; + } + return ESP_LOG_WARN; +} +const char* get_log_level_desc(esp_log_level_t level) { + switch (level) { + case ESP_LOG_NONE: + return "NONE"; + break; + + case ESP_LOG_ERROR: + return "ERROR"; + break; + + case ESP_LOG_WARN: + return "WARN"; + break; + + case ESP_LOG_INFO: + return "INFO"; + break; + case ESP_LOG_DEBUG: + return "DEBUG"; + break; + case ESP_LOG_VERBOSE: + return "VERBOSE"; + break; + + default: + break; } - // Read directory entries - uint64_t total = 0; - int nfiles = 0; - printf("T Size Name\n"); - printf(sep); - while ((ent = readdir(dir)) != NULL) { - sprintf(tpath, path); - if (path[strlen(path)-1] != '/') strcat(tpath,"/"); - strcat(tpath,ent->d_name); - - // Get file stat - statok = stat(tpath, &sb); - - if (ent->d_type == DT_REG) { - type = 'f'; - nfiles++; - if (statok) strcpy(size, " ?"); - else { - total += sb.st_size; - if (sb.st_size < (1024*1024)) sprintf(size,"%8d", (int)sb.st_size); - else if ((sb.st_size/1024) < (1024*1024)) sprintf(size,"%6dKB", (int)(sb.st_size / 1024)); - else sprintf(size,"%6dMB", (int)(sb.st_size / (1024 * 1024))); - } - } - else { - type = 'd'; - strcpy(size, " -"); - } - - printf("%c %s %s\r\n", - type, - size, - ent->d_name - ); - - } - if (total) { - printf(sep); - if (total < (1024*1024)) printf(" %8d", (int)total); - else if ((total/1024) < (1024*1024)) printf(" %6dKB", (int)(total / 1024)); - else printf(" %6dMB", (int)(total / (1024 * 1024))); - printf(" in %d file(s)\n", nfiles); - } - printf(sep); - - closedir(dir); - - free(lpath); - free(path); - uint32_t tot=0, used=0; - esp_spiffs_info(NULL, &tot, &used); - printf("SPIFFS: free %d KB of %d KB\n", (tot-used) / 1024, tot / 1024); - printf(sep); + return "UNKNOWN"; } -bool out_file_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count) { - FILE* file = (FILE*)stream->state; - ESP_LOGD(TAG, "Writing %d bytes to file", count); - return fwrite(buf, 1, count, file) == count; -} -bool in_file_binding(pb_istream_t* stream, pb_byte_t *buf, size_t count) { - FILE* file = (FILE*)stream->state; - ESP_LOGD(TAG, "Reading %d bytes from file", count); - return fread(buf, 1, count, file) == count; -} - -bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count) { - httpd_req_t* req = (httpd_req_t*)stream->state; - ESP_LOGD(TAG, "Writing %d bytes to file", count); - return httpd_resp_send_chunk(req, (const char*)buf, count) == ESP_OK; -} +void set_log_level(char* tag, char* level) { esp_log_level_set(tag, get_log_level_from_char(level)); } diff --git a/components/tools/tools.h b/components/tools/tools.h index 50fd588e..3a37fa9e 100644 --- a/components/tools/tools.h +++ b/components/tools/tools.h @@ -1,125 +1,350 @@ /* - * Tools * - * Philippe G. 2019, philippe_44@outlook.com + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com * * This software is released under the MIT License. * https://opensource.org/licenses/MIT * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. */ #pragma once +#include "esp_log.h" #include "cJSON.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_spiffs.h" -#include "stdio.h" -#include "sys/stat.h" -#include "pb_common.h" // Nanopb header for encoding (serialization) -#include "pb_decode.h" // Nanopb header for decoding (deserialization) -#include "pb_encode.h" // Nanopb header for encoding (serialization) + #ifdef __cplusplus +#include "cpp_tools.h" extern "C" { #endif - +/** + * @def QUOTE + * Converts the argument name into a string. + * + * @param name The name to be converted into a string. + */ #ifndef QUOTE #define QUOTE(name) #name #endif +/** + * @def STR + * Converts a macro value into a string. + * + * @param macro The macro whose value is to be converted into a string. + */ #ifndef STR #define STR(macro) QUOTE(macro) #endif +/** + * @def STR_OR_ALT + * Returns the string 'str' or an alternative 'alt' if 'str' is NULL. + * + * @param str The string to check. + * @param alt The alternative string to return if 'str' is NULL. + */ #ifndef STR_OR_ALT +#ifdef __cplusplus +#define STR_OR_ALT(str, alt) (str!=nullptr ? str : alt) +#else #define STR_OR_ALT(str, alt) (str ? str : alt) #endif -#ifndef STR_OR_BLANK -#define STR_OR_BLANK(p) p == NULL ? "" : p #endif +/** + * @def STR_OR_BLANK + * Returns the string 'p' or an empty string if 'p' is NULL. + * + * @param p The string to check. + */ +#ifndef STR_OR_BLANK +#ifdef __cplusplus +#define STR_OR_BLANK(p) p == nullptr ? "" : p +#else +#define STR_OR_BLANK(p) p == NULL ? "" : p +#endif +#endif + +/** + * @def ESP_LOG_DEBUG_EVENT + * Logs a debug event with a given tag. + * + * @param tag The tag associated with the log message. + * @param e The event to log. + */ #define ESP_LOG_DEBUG_EVENT(tag, e) ESP_LOGD(tag, "evt: " e) +/** + * @def FREE_AND_NULL + * Frees a pointer if it's not NULL and sets it to NULL. + * + * @param x The pointer to free and nullify. + */ #ifndef FREE_AND_NULL -#define FREE_AND_NULL(x) \ - if (x) { \ - free(x); \ - x = NULL; \ +#define FREE_AND_NULL(x) \ + if (x) { \ + free(x); \ + x = NULL; \ } #endif +/** + * @def CASE_TO_STR + * A switch case that returns the string representation of a case constant. + * + * @param x The case constant. + */ #ifndef CASE_TO_STR -#define CASE_TO_STR(x) \ - case x: \ - return STR(x); \ +#define CASE_TO_STR(x) \ + case x: \ + return STR(x); \ break; #endif -#define ENUM_TO_STRING(g) \ - case g: \ - return STR(g); \ +/** + * @def ENUM_TO_STRING + * A switch case for an enum that returns the string representation of the enum value. + * + * @param g The enum value. + */ +#define ENUM_TO_STRING(g) \ + case g: \ + return STR(g); \ break; +/** + * @fn void utf8_decode(char* src) + * Decodes a string encoded in UTF-8 to CP1252 in place. + * The result is stored in the same buffer as the input. + * + * @param src A pointer to the null-terminated string to be decoded. + */ void utf8_decode(char* src); -void url_decode(char* url); + +/** + * @fn void* malloc_init_external(size_t sz) + * Allocates memory in PSRAM and initializes it to zero. + * + * This function attempts to allocate a block of memory of size 'sz' in PSRAM. + * If allocation is successful, the memory is initialized to zero. + * + * @param sz The size of memory to allocate in bytes. + * @return A pointer to the allocated memory block or NULL if allocation fails. + */ void* malloc_init_external(size_t sz); + +/** + * @fn void* clone_obj_psram(void* source, size_t source_sz) + * Clones an object into PSRAM. + * + * This function allocates memory in PSRAM and copies the contents of the + * source object into the newly allocated memory. The size of the source + * object is specified by 'source_sz'. + * + * @param source A pointer to the source object to clone. + * @param source_sz The size of the source object in bytes. + * @return A pointer to the cloned object in PSRAM or NULL if allocation fails. + */ void* clone_obj_psram(void* source, size_t source_sz); + +/** + * @fn char* strdup_psram(const char* source) + * Duplicates a string into PSRAM. + * + * This function allocates enough memory in PSRAM to hold a copy of 'source', + * including the null terminator, and then copies the string into the new memory. + * + * @param source A pointer to the null-terminated string to duplicate. + * @return A pointer to the duplicated string in PSRAM or NULL if allocation fails. + */ char* strdup_psram(const char* source); +/** + * @fn const char* get_mem_flag_desc(int flags) + * Returns a string describing memory allocation flags. + * + * This function takes memory allocation flags as an argument and returns + * a string representation of these flags. The description includes various + * memory capabilities like EXEC, DMA, SPIRAM, etc. + * + * @param flags The memory allocation flags to describe. + * @return A string representation of the memory allocation flags. + */ +const char* get_mem_flag_desc(int flags); + +/** + * @fn const char* get_mac_str() + * Returns a string representation of the device's MAC address. + * + * This function reads the MAC address of the device and returns a string + * representation of the last three bytes of the MAC address. It uses a static + * buffer to store the MAC address string. + * + * @return A string representation of the device's MAC address. + */ +const char* get_mac_str(); + +/** + * @fn char* alloc_get_string_with_mac(const char* val) + * Allocates a new string which is a concatenation of the provided value and the device's MAC address. + * + * This function concatenates 'val' with the device's MAC address string and returns + * a pointer to the newly allocated string. + * + * @param val The string to concatenate with the MAC address. + * @return A pointer to the newly allocated string, or NULL if allocation fails. + */ +char* alloc_get_string_with_mac(const char* val); + +/** + * @fn char* alloc_get_fallback_unique_name() + * Allocates a unique name for the device based on predefined configurations or fallbacks. + * + * This function creates a unique name by concatenating a base name defined by + * configuration macros (CONFIG_LWIP_LOCAL_HOSTNAME, CONFIG_FW_PLATFORM_NAME) + * or a fallback prefix "squeezelite-" with the device's MAC address. + * + * @return A pointer to the newly allocated unique name, or NULL if allocation fails. + */ +char* alloc_get_fallback_unique_name(); + +/** + * @fn char* alloc_get_formatted_mac_string(uint8_t mac[6]) + * Allocates and returns a formatted MAC address string. + * + * This function formats a given MAC address into a human-readable string, + * allocating the necessary memory dynamically. + * + * @param mac An array containing the 6-byte MAC address. + * @return A pointer to the dynamically allocated MAC address string, or NULL if allocation fails. + */ +char* alloc_get_formatted_mac_string(uint8_t mac[6]); + +/** + * @fn const char* str_or_unknown(const char* str) + * Returns the input string or a placeholder for unknown string. + * + * If the input string is not NULL, it returns the string. Otherwise, + * it returns a predefined placeholder for unknown strings. + * + * @param str The input string. + * @return The input string or a placeholder if the input is NULL. + */ const char* str_or_unknown(const char* str); + +/** + * @fn const char* str_or_null(const char* str) + * Returns the input string or a placeholder for null string. + * + * If the input string is not NULL, it returns the string. Otherwise, + * it returns a predefined placeholder for null strings. + * + * @param str The input string. + * @return The input string or a placeholder if the input is NULL. + */ const char* str_or_null(const char* str); + +/** + * @fn esp_log_level_t get_log_level_from_char(char* level) + * Converts a string representation of a log level to its corresponding `esp_log_level_t` enum value. + * + * The function supports log level strings like "NONE", "ERROR", "WARN", "INFO", "DEBUG", and "VERBOSE". + * + * @param level The log level as a string. + * @return The corresponding `esp_log_level_t` value, or ESP_LOG_WARN if the string does not match any log level. + */ +esp_log_level_t get_log_level_from_char(char* level); + +/** + * @fn const char* get_log_level_desc(esp_log_level_t level) + * Returns the string description of a given `esp_log_level_t` log level. + * + * @param level The log level as an `esp_log_level_t` enum. + * @return The string description of the log level. + */ +const char* get_log_level_desc(esp_log_level_t level); + +/** + * @fn void set_log_level(char* tag, char* level) + * Sets the log level for a specific tag. + * + * The log level is specified as a string and converted internally to the corresponding `esp_log_level_t` value. + * + * @param tag The tag for which to set the log level. + * @param level The log level as a string. + */ +void set_log_level(char* tag, char* level); + +/** + * @fn BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName, configSTACK_DEPTH_TYPE usStackDepth, void* pvParameters, + * UBaseType_t uxPriority, TaskHandle_t* pxCreatedTask) Creates a new task with its stack allocated in external RAM (PSRAM). Use these to dynamically + * create tasks whose stack is on EXTRAM. Be aware that it requires configNUM_THREAD_LOCAL_STORAGE_POINTERS to bet set to 2 at least (index 0 is used + * by pthread and this uses index 1, obviously + * + * @param pvTaskCode Pointer to the task entry function. + * @param pcName Task name. + * @param usStackDepth Stack depth in words. + * @param pvParameters Pointer to the task's parameters. + * @param uxPriority Task priority. + * @param pxCreatedTask Pointer to a variable to store the task's handle. + * @return pdPASS on success, pdFAIL on failure. + */ +BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName, configSTACK_DEPTH_TYPE usStackDepth, void* pvParameters, + UBaseType_t uxPriority, TaskHandle_t* pxCreatedTask); + +/** + * @fn void vTaskDeleteEXTRAM(TaskHandle_t xTask) + * Deletes a task and cleans up its allocated resources. + * This function should be used in place of vTaskDelete for tasks created with xTaskCreateEXTRAM. + * + * @param xTask Handle to the task to be deleted. + */ +void vTaskDeleteEXTRAM(TaskHandle_t xTask); + +/** + * @fn void dump_json_content(const char* prefix, cJSON* json, int level) + * Dumps the content of a cJSON object to the log. + * + * @param prefix Prefix for the log message. + * @param json Pointer to the cJSON object to dump. + * @param level Logging level for the output. + */ void dump_json_content(const char* prefix, cJSON* json, int level); -void init_spiffs(); -char * alloc_get_string_with_mac(const char * val); -const char * get_mac_str(); -#define alloc_join_path(base_path, ...) _alloc_join_path(base_path,__VA_ARGS__, NULL) -char* _alloc_join_path(const char* base_path, ...); - -#define get_file_info(pfileInfo, ...) _get_file_info(pfileInfo,__VA_ARGS__, NULL) - -bool _get_file_info(struct stat* pfileInfo, ...); - -#define load_file(sz, ...) _load_file(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT, sz, __VA_ARGS__, NULL) -#define load_file_dma(sz, ...) _load_file(MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA, sz, __VA_ARGS__, NULL) - -void* _load_file(uint32_t memflags, size_t* sz, ...); - -#define file_exists(pfileinfo,...) _file_exists(pfileInfo,__VA_ARGS__, NULL) -bool _file_exists(struct stat *fileInfo, ...); - -#define open_file(mode,...) _open_file(mode,__VA_ARGS__, NULL) -FILE* _open_file( const char* mode,...); - -bool in_file_binding(pb_istream_t* stream, pb_byte_t *buf, size_t count); -bool out_file_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); -bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); - -#define write_file(data,sz,...) _write_file(data,sz,__VA_ARGS__, NULL) -bool _write_file(uint8_t* data, size_t sz, ...); - -void listFiles(const char *path_requested); #ifndef gettime_ms // body is provided somewhere else... uint32_t _gettime_ms_(void); #define gettime_ms _gettime_ms_ #endif -typedef void (*http_download_cb_t)(uint8_t* data, size_t len, void* context); -void http_download(char* url, size_t max, http_download_cb_t callback, void* context); - -/* Use these to dynamically create tasks whose stack is on EXTRAM. Be aware that it - * requires configNUM_THREAD_LOCAL_STORAGE_POINTERS to bet set to 2 at least (index 0 - * is used by pthread and this uses index 1, obviously +/** + * @def TRACE_DEBUG + * A macro for debug tracing. + * + * This macro prints a formatted debug message to the standard output. + * The message includes the name of the function and the line number from which + * the macro is called, followed by a custom formatted message. + * + * @param msgformat A printf-style format string for the custom message. + * @param ... Variable arguments for the format string. */ -BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName, - configSTACK_DEPTH_TYPE usStackDepth, void* pvParameters, UBaseType_t uxPriority, - TaskHandle_t* pxCreatedTask); -void vTaskDeleteEXTRAM(TaskHandle_t xTask); - -extern const char unknown_string_placeholder[]; - #ifndef TRACE_DEBUG -#define TRACE_DEBUG(msgformat, ... ) printf("%-30s%-5d" msgformat "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define TRACE_DEBUG(msgformat, ...) printf("%-30s%-5d" msgformat "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/components/tools/tools_http_utils.c b/components/tools/tools_http_utils.c new file mode 100644 index 00000000..025412e6 --- /dev/null +++ b/components/tools/tools_http_utils.c @@ -0,0 +1,148 @@ +#include "tools_http_utils.h" +#include "esp_http_client.h" +#include "esp_http_server.h" +#include "esp_log.h" +#include "tools.h" +#include "esp_tls.h" +#include "pb_decode.h" +#include "pb_encode.h" + +static const char* TAG = "http_utils"; + +/**************************************************************************************** + * URL download + */ + +typedef struct { + void* user_context; + http_download_cb_t callback; + size_t max, bytes; + bool abort; + uint8_t* data; + esp_http_client_handle_t client; +} http_context_t; + +static void http_downloader(void* arg); +static esp_err_t http_event_handler(esp_http_client_event_t* evt); + +void http_download(char* url, size_t max, http_download_cb_t callback, void* context) { + http_context_t* http_context = + (http_context_t*)heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM); + + esp_http_client_config_t config = { + .url = url, + .event_handler = http_event_handler, + .user_data = http_context, + }; + + http_context->callback = callback; + http_context->user_context = context; + http_context->max = max; + http_context->client = esp_http_client_init(&config); + + xTaskCreateEXTRAM( + http_downloader, "downloader", 8 * 1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL); +} + +static void http_downloader(void* arg) { + http_context_t* http_context = (http_context_t*)arg; + + esp_http_client_perform(http_context->client); + esp_http_client_cleanup(http_context->client); + + free(http_context); + vTaskDeleteEXTRAM(NULL); +} + +static esp_err_t http_event_handler(esp_http_client_event_t* evt) { + http_context_t* http_context = (http_context_t*)evt->user_data; + + if (http_context->abort) return ESP_FAIL; + + switch (evt->event_id) { + case HTTP_EVENT_ERROR: + http_context->callback(NULL, 0, http_context->user_context); + http_context->abort = true; + break; + case HTTP_EVENT_ON_HEADER: + if (!strcasecmp(evt->header_key, "Content-Length")) { + size_t len = atoi(evt->header_value); + if (!len || len > http_context->max) { + ESP_LOGI(TAG, "content-length null or too large %zu / %zu", len, http_context->max); + http_context->abort = true; + } + } + break; + case HTTP_EVENT_ON_DATA: { + size_t len = esp_http_client_get_content_length(evt->client); + if (!http_context->data) { + if ((http_context->data = (uint8_t*)malloc(len)) == NULL) { + http_context->abort = true; + ESP_LOGE(TAG, "failed to allocate memory for output buffer %zu", len); + return ESP_FAIL; + } + } + memcpy(http_context->data + http_context->bytes, evt->data, evt->data_len); + http_context->bytes += evt->data_len; + break; + } + case HTTP_EVENT_ON_FINISH: + http_context->callback(http_context->data, http_context->bytes, http_context->user_context); + break; + case HTTP_EVENT_DISCONNECTED: { + int mbedtls_err = 0; + esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "HTTP download disconnect %d", err); + if (http_context->data) free(http_context->data); + http_context->callback(NULL, 0, http_context->user_context); + return ESP_FAIL; + } + break; + } + default: + break; + } + + return ESP_OK; +} + + +/**************************************************************************************** + * URL tools + */ + +static inline char from_hex(char ch) { return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; } + +void url_decode(char* url) { + char *p, *src = strdup(url); + for (p = src; *src; url++) { + *url = *src++; + if (*url == '%') { + *url = from_hex(*src++) << 4; + *url |= from_hex(*src++); + } else if (*url == '+') { + *url = ' '; + } + } + *url = '\0'; + free(p); +} + +bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count) { + httpd_req_t* req = (httpd_req_t*)stream->state; + ESP_LOGD(TAG, "Writing %d bytes to file", count); + return httpd_resp_send_chunk(req, (const char*)buf, count) == ESP_OK; +} + +bool in_http_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count) { + httpd_req_t* req = (httpd_req_t*)stream->state; + ESP_LOGV(TAG, "Reading %d bytes from http stream", count); + int received = httpd_req_recv(req, (char*)buf, count); + if (received <= 0) { + stream->errmsg = "Not all data received"; + return false; + } + return received==count; + +} diff --git a/components/tools/tools_http_utils.h b/components/tools/tools_http_utils.h new file mode 100644 index 00000000..1a8e411a --- /dev/null +++ b/components/tools/tools_http_utils.h @@ -0,0 +1,100 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + +#pragma once +#include "esp_system.h" +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Type definition for a callback function used in HTTP download. + * + * @param data Pointer to the downloaded data buffer. + * @param len Length of the data buffer. + * @param context User-defined context passed to the callback. + */ +typedef void (*http_download_cb_t)(uint8_t* data, size_t len, void* context); + +/** + * @brief Downloads data from a specified URL. + * + * This function initializes an HTTP client and starts a download task. + * It uses a callback mechanism to return the downloaded data. + * + * @param url The URL from which to download data. + * @param max The maximum size of data to download. + * @param callback The callback function to be called with the downloaded data. + * @param context User-defined context to be passed to the callback function. + */ +void http_download(char* url, size_t max, http_download_cb_t callback, void* context); + +/** + * @brief Decodes a URL-encoded string. + * + * This function replaces percent-encoded characters in the URL with their ASCII representations. + * Spaces encoded as '+' are also converted to space characters. + * + * @param url The URL-encoded string to be decoded in place. + */ +void url_decode(char* url); + +/** + * @brief Callback function for output streaming with HTTP binding. + * + * This function is designed to be used with NanoPB for streaming output data over HTTP. + * It sends the given buffer over an HTTP connection. + * + * @param stream The output stream provided by NanoPB. + * @param buf The buffer containing data to be sent. + * @param count The number of bytes in the buffer to be sent. + * @return Returns true on successful transmission, false otherwise. + */ +bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); + + +/** + * @brief Callback function for input streaming with HTTP binding. + * + * This function is designed to be used with NanoPB for streaming input data over HTTP. + * It reads data into the given buffer from an HTTP connection. + * + * The function is typically used as a callback in a `pb_istream_t` structure, + * allowing NanoPB to receive data in a streaming manner from an HTTP source. + * + * @param stream The input stream provided by NanoPB. + * @param buf The buffer where data should be stored. + * @param count The size of the buffer, indicating the maximum number of bytes to read. + * @return Returns true on successful reception of data, false otherwise. When false + * is returned, it indicates an error in data reception or end of stream. + */ +bool in_http_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count); + + + +#ifdef __cplusplus +} +#endif diff --git a/components/tools/tools_spiffs_utils.cpp b/components/tools/tools_spiffs_utils.cpp new file mode 100644 index 00000000..9ab86a45 --- /dev/null +++ b/components/tools/tools_spiffs_utils.cpp @@ -0,0 +1,383 @@ +#define LOG_LOCAL_LEVEL ESP_LOG_INFO +#include "tools_spiffs_utils.h" +#include "esp_log.h" +#include "tools.h" + +#include "PBW.h" +#include // For isprint() +#include +#include +#include // for std::setw +#include +#include +#include // for file stat +#include + +static const char* TAG = "spiffs_utils"; +static bool initialized = false; +static esp_vfs_spiffs_conf_t* spiffs_conf = NULL; +const char* spiffs_base_path = "/spiffs"; +// Struct to represent a file entry + +// list of reserved files that the system controls +const std::vector restrictedPaths = { + "/spiffs/defaults/*", "/spiffs/fonts/*", "/spiffs/targets/*", "/spiffs/www/*"}; + +void init_spiffs() { + if (initialized) { + ESP_LOGV(TAG, "SPIFFS already initialized. returning"); + return; + } + ESP_LOGI(TAG, "Initializing the SPI File system"); + spiffs_conf = (esp_vfs_spiffs_conf_t*)malloc(sizeof(esp_vfs_spiffs_conf_t)); + spiffs_conf->base_path = spiffs_base_path; + spiffs_conf->partition_label = NULL; + spiffs_conf->max_files = 5; + spiffs_conf->format_if_mount_failed = true; + + // Use settings defined above to initialize and mount SPIFFS filesystem. + // Note: esp_vfs_spiffs_register is an all-in-one convenience function. + esp_err_t ret = esp_vfs_spiffs_register(spiffs_conf); + + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem"); + } else if (ret == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find SPIFFS partition"); + } else { + ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + } + return; + } + + size_t total = 0, used = 0; + ret = esp_spiffs_info(spiffs_conf->partition_label, &total, &used); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", + esp_err_to_name(ret)); + esp_spiffs_format(spiffs_conf->partition_label); + } else { + ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); + } + + initialized = true; +} + +bool write_file(const uint8_t* data, size_t sz, const char* filename) { + bool result = true; + FILE* file = NULL; + init_spiffs(); + if (data == NULL) { + ESP_LOGE(TAG, "Cannot write file. Data not received"); + return false; + } + if (sz == 0) { + ESP_LOGE(TAG, "Cannot write file. Data length 0"); + return false; + } + file = fopen(filename, "wb"); + if (file == NULL) { + ESP_LOGE(TAG, "Error opening %s for writing", filename); + return false; + } + size_t written = fwrite(data, 1, sz, file); + if (written != sz) { + ESP_LOGE(TAG, "Write error. Wrote %d bytes of %d.", written, sz); + result = false; + } + fclose(file); + return result; +} + +void* load_file(uint32_t memflags, size_t* sz, const char* filename) { + void* data = NULL; + FILE* file = NULL; + init_spiffs(); + size_t fsz = 0; + file = fopen(filename, "rb"); + + if (file == NULL) { + return data; + } + fseek(file, 0, SEEK_END); + fsz = ftell(file); + fseek(file, 0, SEEK_SET); + if (fsz > 0) { + ESP_LOGD(TAG, "Allocating %d bytes to load file %s content with flags: %s ", fsz, filename, + get_mem_flag_desc(memflags)); + data = (void*)heap_caps_calloc(1, fsz, memflags); + if (data == NULL) { + ESP_LOGE(TAG, "Failed to allocate %d bytes to load file %s", fsz, filename); + } else { + fread(data, 1, fsz, file); + if (sz) { + *sz = fsz; + } + } + } else { + ESP_LOGW(TAG, "File is empty. Nothing to read"); + } + fclose(file); + return data; +} +bool get_file_info(struct stat* pfileInfo, const char* filename) { + // ensure that the spiffs is initialized + struct stat fileInfo; + init_spiffs(); + if (strlen(filename) == 0) { + ESP_LOGE(TAG, "Invalid file name"); + return false; + } + ESP_LOGD(TAG, "Getting file info for %s", filename); + bool result = false; + // Use stat to fill the fileInfo structure + if (stat(filename, &fileInfo) != 0) { + ESP_LOGD(TAG, "File %s not found", filename); + } else { + result = true; + if (pfileInfo) { + memcpy(pfileInfo, &fileInfo, sizeof(fileInfo)); + } + ESP_LOGD(TAG, "File %s has %lu bytes", filename, fileInfo.st_size); + } + + return result; +} + +bool is_restricted_path(const char* filename) { + for (const auto& pattern : restrictedPaths) { + if (fnmatch(pattern.c_str(), filename, 0) == 0) { + return true; + } + } + return false; +} + +bool erase_path(const char* filename, bool restricted) { + std::string full_path_with_wildcard = std::string(filename); + if (full_path_with_wildcard.empty()) { + ESP_LOGE(TAG, "Error constructing full path"); + return false; + } + + ESP_LOGI(TAG, "Erasing file(s) matching pattern %s", full_path_with_wildcard.c_str()); + + // Extract directory path and wildcard pattern + size_t lastSlashPos = full_path_with_wildcard.find_last_of('/'); + std::string dirpath = full_path_with_wildcard.substr(0, lastSlashPos); + std::string wildcard = full_path_with_wildcard.substr(lastSlashPos + 1); + ESP_LOGD(TAG, "Last slash pos: %d, dirpath: %s, wildcard %s ", lastSlashPos, dirpath.c_str(), + wildcard.c_str()); + DIR* dir = opendir(dirpath.empty() ? "." : dirpath.c_str()); + if (!dir) { + ESP_LOGE(TAG, "Error opening directory"); + return false; + } + + bool result = false; + struct dirent* ent; + while ((ent = readdir(dir)) != NULL) { + if (fnmatch(wildcard.c_str(), ent->d_name, 0) == 0) { + std::string fullfilename = dirpath + "/" + ent->d_name; + // Check if the file is restricted + if (restricted && is_restricted_path(fullfilename.c_str())) { + ESP_LOGW(TAG, "Skipping restricted file %s", fullfilename.c_str()); + continue; + } + ESP_LOGW(TAG, "Deleting file %s", fullfilename.c_str()); + if (remove(fullfilename.c_str()) != 0) { + ESP_LOGE(TAG, "Error deleting file %s", fullfilename.c_str()); + } else { + result = true; + } + } else { + ESP_LOGV( + TAG, "%s does not match file pattern to delete: %s", ent->d_name, wildcard.c_str()); + } + } + + closedir(dir); + return result; +} + +// Function to format and print a file entry +void printFileEntry(const tools_file_entry_t& entry) { + const char* suffix; + double size; + + // Format the size + if (entry.type == 'F') { + if (entry.size < 1024) { // less than 1 KB + size = entry.size; + suffix = " B"; + printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), + entry.restricted ? "X" : "-"); + } else { + if (entry.size < 1024 * 1024) { // 1 KB to <1 MB + size = entry.size / 1024; + suffix = " KB"; + } else { // 1 MB and above + size = entry.size / (1024 * 1024); + suffix = " MB"; + } + printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), + entry.restricted ? "X" : "-"); + } + + } else { + printf("%c - %-80s%4s\n", entry.type, entry.name.c_str(), + entry.restricted ? "X" : "-"); + } +} + +void listFiles(const char* path_requested_char) { + // Ensure that the SPIFFS is initialized + init_spiffs(); + auto path_requested = std::string(path_requested_char); + auto filesList = get_files_list(path_requested); + printf("---------------------------------------------------------------------------------------" + "---------------\n"); + printf("T SIZE NAME " + " RSTR\n"); + printf("---------------------------------------------------------------------------------------" + "---------------\n"); + + uint64_t total = 0; + int nfiles = 0; + for (auto& e : filesList) { + if (e.type == 'F') { + total += e.size; + nfiles++; + } + printFileEntry(e); + } + printf("---------------------------------------------------------------------------------------" + "---------------\n"); + if (total > 0) { + printf("Total : %lu bytes in %d file(s)\n", (unsigned long)total, nfiles); + } + + uint32_t tot = 0, used = 0; + esp_spiffs_info(NULL, &tot, &used); + printf("SPIFFS: free %d KB of %d KB\n", (tot - used) / 1024, tot / 1024); + printf("---------------------------------------------------------------------------------------" + "---------------\n"); +} + +bool out_file_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count) { + FILE* file = (FILE*)stream->state; + ESP_LOGV(TAG, "Writing %d bytes to file", count); + return fwrite(buf, 1, count, file) == count; +} +bool in_file_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count) { + FILE* file = (FILE*)stream->state; + ESP_LOGV(TAG, "Reading %d bytes from file", count); + return fread(buf, 1, count, file) == count; +} + +// Function to list files matching the path_requested and return a std::list of FileEntry +std::list get_files_list(const std::string& path_requested) { + std::list fileList; + std::set directoryNames; + + struct dirent* ent; + struct stat sb; + + // Ensure that the SPIFFS is initialized + init_spiffs(); + + std::string prefix = (path_requested.back() != '/' ? path_requested + "/" : path_requested); + DIR* dir = opendir(path_requested.c_str()); + if (!dir) { + ESP_LOGE(TAG, "Error opening directory %s ", path_requested.c_str()); + return fileList; + } + + while ((ent = readdir(dir)) != NULL) { + tools_file_entry_t fileEntry; + fileEntry.name = prefix + ent->d_name; + fileEntry.type = (ent->d_type == DT_REG) ? 'F' : 'D'; + fileEntry.restricted = is_restricted_path(fileEntry.name.c_str()); + if (stat(fileEntry.name.c_str(), &sb) == -1) { + ESP_LOGE(TAG, "Ignoring file %s ", fileEntry.name.c_str()); + continue; + } + fileEntry.size = sb.st_size; + fileList.push_back(fileEntry); + + // Extract all parent directory names + size_t pos = 0; + while ((pos = fileEntry.name.find('/', pos + 1)) != std::string::npos) { + directoryNames.insert(fileEntry.name.substr(0, pos)); + } + } + closedir(dir); + + // Add directories to the file list + for (const auto& dirName : directoryNames) { + tools_file_entry_t dirEntry; + dirEntry.name = dirName; + dirEntry.type = 'D'; // Mark as directory + fileList.push_back(dirEntry); + } + + // Sort the list by directory/file name + fileList.sort( + [](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name < b.name; }); + + // Remove duplicates + fileList.unique( + [](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name == b.name; }); + + return fileList; +} +bool cat_file(const char* filename) { + size_t sz; + uint8_t* content = (uint8_t*)load_file_psram(&sz, filename); + + if (content == NULL) { + printf("Failed to load file\n"); + return false; + } + + for (size_t i = 0; i < sz; i++) { + if (isprint(content[i])) { + printf("%c", content[i]); // Print as a character + } else { + printf("\\x%02x", content[i]); // Print as hexadecimal + } + } + + printf("\n"); // New line after printing the content + free(content); + return true; +} + +bool dump_data(const uint8_t* pData, size_t length) { + if (pData == NULL && length == 0) { + printf("%s/%s\n", pData == nullptr ? "Invalid Data" : "Data OK", + length == 0 ? "Invalid Length" : "Length OK"); + return false; + } + + for (size_t i = 0; i < length; i++) { + if (isprint((char)pData[i])) { + printf("%c", (char)pData[i]); // Print as a character + } else { + printf("\\x%02x", (char)pData[i]); // Print as hexadecimal + } + } + + printf("\n"); // New line after printing the content + return true; +} + +bool dump_structure(const pb_msgdesc_t* fields, const void* src_struct) { + try { + std::vector encodedData = System::PBHelper::EncodeData(fields, src_struct); + return dump_data(encodedData.data(), encodedData.size()); + } catch (const std::runtime_error& e) { + ESP_LOGE(TAG, "Error in dump_structure: %s", e.what()); + return false; + } +} \ No newline at end of file diff --git a/components/tools/tools_spiffs_utils.h b/components/tools/tools_spiffs_utils.h new file mode 100644 index 00000000..fd44cc3b --- /dev/null +++ b/components/tools/tools_spiffs_utils.h @@ -0,0 +1,249 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + +#pragma once +#include "esp_spiffs.h" +#include "esp_system.h" +#include "pb.h" // Nanopb header for encoding (serialization) +#include "pb_decode.h" // Nanopb header for decoding (deserialization) +#include "pb_encode.h" // Nanopb header for encoding (serialization) +#include "sys/stat.h" + +#include + +#ifdef __cplusplus +#include // for va_list, va_start, va_end +#include +#include +#include +/** + * @brief Represents a file entry. + */ +typedef struct { + char type; /**< File type ('F' for regular file, 'D' for directory). */ + long size; /**< File size in bytes. */ + std::string name; /**< File or directory name. */ + bool restricted; /**< Restricted (system controled)*/ +} tools_file_entry_t; + +extern const std::vector restrictedPaths; + +/** + * @brief Retrieve a list of file entries in the specified directory. + * + * This function collects information about files and directories in the specified + * directory path. The caller is responsible for crafting the complete path + * (including any necessary SPIFFS base path). + * + * @param path_requested The directory path for which to list files and directories. + * @return A std::list of tools_file_entry_t representing the files and directories in the specified + * path. + * + * @note The caller is responsible for adding the SPIFFS base path if needed. + * + * Example usage: + * @code + * std::string base_path = "/spiffs"; + * std::string directory = "/some_directory"; + * std::string full_path = base_path + directory; + * std::list fileList = get_files_list(full_path); + * for (const auto& entry : fileList) { + * // Access entry.type, entry.size, and entry.name + * } + * @endcode + */ + +std::list get_files_list(const std::string& path_requested); + +extern "C" { +#endif + +void init_spiffs(); +extern const char* spiffs_base_path; + +/** + * @brief Retrieves information about a file. + * + * This function uses the stat system call to fill a struct stat with information about the file. + * + * @param pfileInfo Pointer to a struct stat where file information will be stored. + * @param filename The file path to get info for + * @return bool True if the file information was successfully retrieved, false otherwise. + */ +bool get_file_info(struct stat* pfileInfo, const char* filename); + +/** + * @brief Loads the entire content of a file into memory. + * + * This function opens a file in binary read mode and loads its entire + * content into a memory buffer. The memory for the buffer is allocated based + * on the specified memory flags. The size of the loaded data is stored in the + * variable pointed to by 'sz'. + * + * @param memflags Flags indicating the type of memory to allocate for the buffer. + * This can be a combination of memory capabilities like MALLOC_CAP_SPIRAM, + * MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL, MALLOC_CAP_DMA, etc. + * @param sz Pointer to a size_t variable where the size of the loaded data will be stored. + * Optional if loaded size is needed. + * @param filename The path of the file to load. The file should exist and be readable. + * @return A pointer to the allocated memory containing the file data. Returns NULL if the + * file cannot be opened, if memory allocation fails, or if the file is empty. + */ +void* load_file(uint32_t memflags, size_t* sz, const char* filename); + +/** + * @brief Macro to load a file into PSRAM (Pseudo-Static Random Access Memory). + * + * This macro is a convenience wrapper for 'load_file' to load file data into PSRAM. + * It is suitable for larger data that does not fit into the internal memory. + * + * @param pSz Pointer to a size_t variable to store the size of the loaded data. + * @param filename The path of the file to load. + * @return A pointer to the allocated memory in PSRAM containing the file data, or NULL on failure. + */ +#define load_file_psram(pSz, filename) load_file(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT, pSz, filename) + +/** + * @brief Macro to load a file into DMA-capable internal memory. + * + * This macro is a convenience wrapper for 'load_file' to load file data into + * DMA-capable internal memory. It is suitable for smaller data that needs to be + * accessed by DMA controllers. + * + * @param pSz Pointer to a size_t variable to store the size of the loaded data. + * @param filename The path of the file to load. + * @return A pointer to the allocated memory in internal DMA-capable memory, or NULL on failure. + */ +#define load_file_dma(pSz, filename) load_file(MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA, pSz, filename) + +/** + * @brief Erases files matching a specified pattern within a path. + * + * This function deletes files that match the given wildcard pattern in the specified path. + * If the 'restricted' flag is set to true, the function will not delete files that match + * any of the paths specified in the restricted paths list. + * + * @param path A string representing the path and wildcard pattern of files to be deleted. + * Example: "folder/test*.txt" will attempt to delete all test*.txt files in the + * 'folder' directory. + * @param restricted A boolean flag indicating whether to apply restrictions on file deletion. + * If true, files matching the restricted paths will not be deleted. + * @return Returns true if all files matching the pattern are successfully deleted or skipped (in + * case of restrictions). Returns false if there is an error in deleting any of the files or if the + * directory cannot be opened. + */ +bool erase_path(const char* path, bool restricted); + +/** + * @brief Checks if a given filename matches any of the restricted paths. + * + * This function determines whether the provided filename matches any pattern specified + * in the list of restricted paths. It is typically used to prevent certain files or directories + * from being modified or deleted. + * + * @param filename The name of the file to check against the restricted paths. + * @return Returns true if the filename matches any of the restricted paths. + * Returns false otherwise. + */ +bool is_restricted_path(const char* filename); + +bool in_file_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count); +bool out_file_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); + +/** + * @brief Writes binary data to a file. + * + * This function writes a given array of bytes (data) to a file. The file path + * is constructed from a variable number of string arguments. + * + * @param data Pointer to the data array to be written. + * @param sz Size of the data array in bytes. + * @param filename The file path to write to + * @return bool True if the file is written successfully, false otherwise. + * + * @note This function initializes the SPIFFS before writing and logs errors. + */ + +bool write_file(const uint8_t* data, size_t sz, const char* filename); + +void listFiles(const char* path_requested); + +/** + * @brief Prints the content of a specified file. + * + * This function reads the content of the file specified by `filename` and prints it to the standard + * output. Each byte of the file is checked to determine if it is a printable ASCII character. If a + * byte is printable, it is printed as a character; otherwise, it is printed in its hexadecimal + * representation. + * + * The function utilizes `load_file_psram` to load the file into memory. It is assumed that + * `load_file_psram` handles the opening and closing of the file, as well as memory allocation and + * error handling. + * + * @param filename The path of the file to be printed. It should be a null-terminated string. + * + * @return Returns `true` if the file is successfully read and printed. Returns `false` if the file + * cannot be opened, read, or if any other error occurs during processing. + * + * @note The function prints a hexadecimal representation (prefixed with \x) for non-printable + * characters. For example, a byte with value 0x1F is printed as \x1F. + * + * @warning The function assumes that `load_file_psram` returns a `NULL` pointer if the file cannot + * be loaded or if any error occurs. Ensure that `load_file_psram` adheres to this behavior. + */ +bool cat_file(const char* filename); + +/** + * @brief Dumps the given data to standard output. + * + * This function prints the provided data array to the standard output. + * If the data is printable (as per the `isprint` standard function), it is printed + * as a character. Otherwise, it is printed in hexadecimal format. The function + * also checks for null data or zero length and reports it before returning false. + * + * @param pData Pointer to the data array to be dumped. + * @param length The length of the data array. + * + * @return Returns `true` if the data is valid (not null and non-zero length), `false` otherwise. + * + * @note The function prints a newline character after dumping the entire data array. + */ +bool dump_data(const uint8_t* pData, size_t length); + +/** + * @brief Encodes a protobuf structure and dumps the encoded data to the console. + * + * This method takes a protobuf message structure, encodes it using NanoPB, and then dumps + * the encoded data to the console. It is useful for debugging purposes to visualize + * the encoded protobuf data. + * + * @param fields Pointer to the field descriptions array (generated by NanoPB). + * @param src_struct Pointer to the structure instance to be encoded. + * + * @return Returns `true` if the data was successfully encoded and dumped, `false` otherwise. + */ +bool dump_structure(const pb_msgdesc_t* fields, const void* src_struct); + +#ifdef __cplusplus +} +#endif diff --git a/components/tools/trace.c b/components/tools/trace.c index 44643f46..eaf4bc16 100644 --- a/components/tools/trace.c +++ b/components/tools/trace.c @@ -40,81 +40,4 @@ mem_usage_trace_for_thread_t* memtrace_get_thread_entry(TaskHandle_t task) { } return NULL; } -void memtrace_add_thread_entry(TaskHandle_t task) { - if(!task) { - ESP_LOGE(TAG, "memtrace_get_thread_entry: task is NULL"); - return ; - } - mem_usage_trace_for_thread_t* it = memtrace_get_thread_entry(task); - if (it) { - ESP_LOGW(TAG, "memtrace_add_thread_entry: thread already in list"); - return; - } - it = (mem_usage_trace_for_thread_t*)malloc_init_external(sizeof(mem_usage_trace_for_thread_t)); - if (!it) { - ESP_LOGE(TAG, "memtrace_add_thread_entry: malloc failed"); - return; - } - it->task = task; - it->malloc_int_last = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - it->malloc_spiram_last = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); - it->malloc_dma_last = heap_caps_get_free_size(MALLOC_CAP_DMA); - it->name = pcTaskGetName(task); - SLIST_INSERT_HEAD(&s_memtrace, it, next); - return; -} -// void memtrace_print_delta(){ -// TaskHandle_t task = xTaskGetCurrentTaskHandle(); -// mem_usage_trace_for_thread_t* it = memtrace_get_thread_entry(task); -// if (!it) { -// memtrace_add_thread_entry(task); -// ESP_LOGW(TAG, "memtrace_print_delta: added new entry for task %s",STR_OR_ALT(pcTaskGetName(task ), "unknown")); -// return; -// } -// size_t malloc_int_delta = heap_caps_get_free_size(MALLOC_CAP_INTERNAL) - it->malloc_int_last; -// size_t malloc_spiram_delta = heap_caps_get_free_size(MALLOC_CAP_SPIRAM) - it->malloc_spiram_last; -// size_t malloc_dma_delta = heap_caps_get_free_size(MALLOC_CAP_DMA) - it->malloc_dma_last; -// ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", -// heap_caps_get_free_size(MALLOC_CAP_INTERNAL), -// heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), -// heap_caps_get_free_size(MALLOC_CAP_SPIRAM), -// heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), -// heap_caps_get_free_size(MALLOC_CAP_DMA), -// heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); -// ESP_LOGW(TAG, "memtrace_print_delta: %s: malloc_int_delta=%d, malloc_spiram_delta=%d, malloc_dma_delta=%d", -// STR_OR_ALT(it->name, "unknown"), -// malloc_int_delta, -// malloc_spiram_delta, -// malloc_dma_delta); -// it->malloc_int_last = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); -// it->malloc_spiram_last = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); -// it->malloc_dma_last = heap_caps_get_free_size(MALLOC_CAP_DMA); - -// } -size_t malloc_int = 0; -size_t malloc_spiram =0; -size_t malloc_dma = 0; -void memtrace_print_delta(const char * msg, const char * tag, const char * function){ - size_t malloc_int_delta = heap_caps_get_free_size(MALLOC_CAP_INTERNAL) - malloc_int; - size_t malloc_spiram_delta = heap_caps_get_free_size(MALLOC_CAP_SPIRAM) - malloc_spiram; - size_t malloc_dma_delta = heap_caps_get_free_size(MALLOC_CAP_DMA) - malloc_dma; - ESP_LOGW(TAG, "Heap internal:%zu (min:%zu)(chg:%d)/external:%zu (min:%zu)(chg:%d)/dma:%zu (min:%zu)(chg:%d) : %s%s%s%s%s", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - malloc_int_delta, - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - malloc_spiram_delta, - heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), - malloc_dma_delta, - STR_OR_BLANK(tag), - tag?" ":"", - STR_OR_BLANK(function), - function?" ":"", - STR_OR_BLANK(msg) - ); - malloc_int = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - malloc_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); - malloc_dma = heap_caps_get_free_size(MALLOC_CAP_DMA); -} + diff --git a/components/tools/trace.h b/components/tools/trace.h index 5a37492e..18a3644c 100644 --- a/components/tools/trace.h +++ b/components/tools/trace.h @@ -1,21 +1,47 @@ -/* - * Squeezelite for esp32 +/* * - * (c) Sebastien 2019 - * Philippe G. 2019, philippe_44@outlook.com + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com * * This software is released under the MIT License. * https://opensource.org/licenses/MIT * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. */ - + #pragma once -#ifdef ENABLE_MEMTRACE -void memtrace_print_delta(const char * msg, const char * tag, const char * function); -#define MEMTRACE_PRINT_DELTA() memtrace_print_delta(NULL,TAG,__FUNCTION__); -#define MEMTRACE_PRINT_DELTA_MESSAGE(x) memtrace_print_delta(x,TAG,__FUNCTION__); +#ifdef __cplusplus +extern "C" { +#endif +#ifdef CONFIG_HEAP_TRACING +#define TRACE_INIT \ + if (!is_recovery_running) { \ + ESP_ERROR_CHECK(heap_trace_init_tohost()); \ + } +#define TRACE_START \ + if (!is_recovery_running) { \ + ESP_ERROR_CHECK(heap_trace_start(HEAP_TRACE_ALL)); \ + } \ + #define TRACE_STOP if (!is_recovery_running) { ESP_ERROR_CHECK(heap_trace_stop()); } #else -#define MEMTRACE_PRINT_DELTA() -#define MEMTRACE_PRINT_DELTA_MESSAGE(x) ESP_LOGD(TAG,"%s",x); -#endif \ No newline at end of file +#define TRACE_START +#define TRACE_STOP +#define TRACE_INIT +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/wifi-manager/CMakeLists.txt b/components/wifi-manager/CMakeLists.txt index fc4dba6e..64fb653b 100644 --- a/components/wifi-manager/CMakeLists.txt +++ b/components/wifi-manager/CMakeLists.txt @@ -1,11 +1,13 @@ +set(CMAKE_CXX_STANDARD 20) + set( WEBPACK_DIR webapp/webpack/dist ) # for the forgetful, REQUIRES cannot use CONFIG_XXX due to parsing order if(IDF_TARGET STREQUAL "esp32") set(target_requires "driver_bt") endif() - -idf_component_register( SRC_DIRS . UML-State-Machine-in-C/src + +idf_component_register( SRC_DIRS . UML-State-Machine-in-C/src INCLUDE_DIRS . UML-State-Machine-in-C/src REQUIRES squeezelite-ota json mdns PRIV_REQUIRES tools services platform_config esp_common json newlib freertos spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console ${target_requires} diff --git a/components/wifi-manager/Kconfig.projbuild b/components/wifi-manager/Kconfig.projbuild index a8f0bad4..f03e107b 100644 --- a/components/wifi-manager/Kconfig.projbuild +++ b/components/wifi-manager/Kconfig.projbuild @@ -1,66 +1,6 @@ menu "Network Manager Configuration" - menu "WiFi Options" - config WIFI_MANAGER_TASK_PRIORITY - int "RTOS Task Priority for the wifi_manager" - default 1 - help - Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. For this particular reason, minimum recommended task priority is 2. - - config WIFI_MANAGER_MAX_RETRY - int "Max Retry on failed connection" - default 2 - help - Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up. - - config DEFAULT_AP_SSID - string "Access Point SSID" - default "esp32" - help - SSID (network name) the the esp32 will broadcast. - - config DEFAULT_AP_PASSWORD - string "Access Point Password" - default "esp32pwd" - help - Password used for the Access Point. Leave empty and set AUTH MODE to WIFI_AUTH_OPEN for no password. - - config DEFAULT_AP_CHANNEL - int "Access Point WiFi Channel" - default 1 - help - Be careful you might not see the access point if you use a channel not allowed in your country. - - config DEFAULT_AP_IP - string "Access Point IP Address" - default "10.10.0.1" - help - This is used for the redirection to the captive portal. It is recommended to leave unchanged. - - config DEFAULT_AP_GATEWAY - string "Access Point IP Gateway" - default "10.10.0.1" - help - This is used for the redirection to the captive portal. It is recommended to leave unchanged. - - config DEFAULT_AP_NETMASK - string "Access Point Netmask" - default "255.255.255.0" - help - This is used for the redirection to the captive portal. It is recommended to leave unchanged. - - config DEFAULT_AP_MAX_CONNECTIONS - int "Access Point Max Connections" - default 4 - help - Max is 4. - - config DEFAULT_AP_BEACON_INTERVAL - int "Access Point Beacon Interval (ms)" - default 100 - help - 100ms is the recommended default. - endmenu + menu "Ethernet Options" visible if BASIC_I2C_BT && (ETH_USE_ESP32_EMAC || ETH_USE_SPI_ETHERNET) choice diff --git a/components/wifi-manager/LICENSE.md b/components/wifi-manager/LICENSE.md deleted file mode 100644 index 5f2ac0bc..00000000 --- a/components/wifi-manager/LICENSE.md +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2017-2019 Tony Pottier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/components/wifi-manager/component.mk b/components/wifi-manager/component.mk deleted file mode 100644 index d2d213f3..00000000 --- a/components/wifi-manager/component.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# -COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz favicon.ico -COMPONENT_ADD_INCLUDEDIRS := . -COMPONENT_EXTRA_INCLUDES += $(IDF_PATH)/components/esp_http_server/src $(IDF_PATH)/components/esp_http_server/src/port/esp32 $(IDF_PATH)/components/esp_http_server/src/util $(IDF_PATH)/components/esp_http_server/src/ -CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO - - diff --git a/components/wifi-manager/dns_server.c b/components/wifi-manager/dns_server.c index 932970be..964a6624 100644 --- a/components/wifi-manager/dns_server.c +++ b/components/wifi-manager/dns_server.c @@ -54,13 +54,15 @@ Contains the freeRTOS task for the DNS server that processes the requests. #include #include "squeezelite-ota.h" #include "network_manager.h" +#include "Config.h" +#include "tools.h" static const char TAG[] = "dns_server"; static TaskHandle_t task_dns_server = NULL; int socket_fd; void dns_server_start(esp_netif_t * netif) { - xTaskCreate(&dns_server, "dns_server", 3072, (void *)netif, WIFI_MANAGER_TASK_PRIORITY-1, &task_dns_server); + xTaskCreateEXTRAM(&dns_server, "dns_server", 3072, (void *)netif, ESP_TASK_PRIO_MIN+5, &task_dns_server); } void dns_server_stop(){ @@ -79,7 +81,7 @@ void dns_server(void *pvParameters) { esp_netif_t * netif = (esp_netif_t * )pvParameters; /* Set redirection DNS hijack to the access point IP */ ip4_addr_t ip_resolved; - inet_pton(AF_INET, DEFAULT_AP_IP, &ip_resolved); + inet_pton(AF_INET, platform->net.ap.ip.ip, &ip_resolved); /* Create UDP socket */ diff --git a/components/wifi-manager/http_server_handlers.c b/components/wifi-manager/http_server_handlers.c index 73471ed9..fc72af62 100644 --- a/components/wifi-manager/http_server_handlers.c +++ b/components/wifi-manager/http_server_handlers.c @@ -1,33 +1,39 @@ /* Copyright (c) 2017-2021 Sebastien L */ - +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #include "http_server_handlers.h" -#include "cJSON.h" -#include "cmd_system.h" -#include "esp_http_server.h" -#include "esp_system.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "squeezelite-ota.h" -#include -#include -#include -#include "Configurator.h" +#include "Config.h" +#include "DataRequest.pb.h" +#include "Locking.h" +#include "Status.pb.h" #include "accessors.h" #include "argtable3/argtable3.h" +#include "cJSON.h" +#include "cmd_system.h" #include "esp_console.h" +#include "esp_http_server.h" +#include "esp_system.h" #include "esp_vfs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "messaging.h" #include "network_status.h" #include "network_wifi.h" +#include "pb_decode.h" +#include "pb_encode.h" #include "platform_console.h" #include "platform_esp32.h" +#include "squeezelite-ota.h" #include "sys/param.h" #include "tools.h" -#include "pb_encode.h" -#include "pb_decode.h" -#include "Status.pb.h" +#include +#include +#include +#include "tools_http_utils.h" +#include "bootstate.h" + + #define HTTP_STACK_SIZE (5 * 1024) const char str_na[] = "N/A"; #define STR_OR_NA(s) s ? s : str_na @@ -43,6 +49,7 @@ typedef struct session_context { bool authenticated; char* sess_ip_address; u16_t port; + SemaphoreHandle_t signal; } session_context_t; extern cJSON* get_gpio_list(bool refresh); @@ -124,6 +131,7 @@ char* http_alloc_get_socket_address(httpd_req_t* req, u8_t local, in_port_t* por } return ipstr; } + bool is_captive_portal_host_name(httpd_req_t* req) { const char* host_name = NULL; const char* ap_host_name = NULL; @@ -196,6 +204,7 @@ void free_ctx_func(void* ctx) { session_context_t* get_session_context(httpd_req_t* req) { bool newConnection = false; + ESP_LOGD_LOC(TAG,"Getting session context for %s",req->uri); if (!req->sess_ctx) { ESP_LOGD(TAG, "New connection context. Allocating session buffer"); req->sess_ctx = malloc_init_external(sizeof(session_context_t)); @@ -212,7 +221,36 @@ session_context_t* get_session_context(httpd_req_t* req) { } return (session_context_t*)req->sess_ctx; } - +bool is_spiffs_safe_thread(httpd_req_t* req) { + session_context_t* ctx_data = get_session_context(req); + return ctx_data->signal != NULL; +} +void finalize_dispatch(httpd_req_t* req) { + ESP_LOGD_LOC(TAG,"Finalizing dispatch"); + session_context_t* ctx_data = get_session_context(req); + if (!ctx_data) { + ESP_LOGE(TAG, "Invalid HTTP Context"); + } else { + xSemaphoreGive(ctx_data->signal); + } +} +void dispatch_response(httpd_req_t* req, network_manager_ret_cb_t cb) { + session_context_t* ctx_data = get_session_context(req); + if (!ctx_data) { + ESP_LOGE(TAG, "Invalid HTTP Context"); + return; + } + ctx_data->signal = xSemaphoreCreateBinary(); + ESP_LOGD_LOC(TAG,"FIRING async task for %s",req->uri); + network_async_callback_withret(req, cb); + ESP_LOGD_LOC(TAG,"WAITING for async task to complete for %s",req->uri); + if (xSemaphoreTake(ctx_data->signal, portMAX_DELAY) != pdTRUE) { + ESP_LOGE(TAG, "Async http failed for %s", req->uri); + } + ESP_LOGD_LOC(TAG,"COMPLETED Async task for %s",req->uri); + vSemaphoreDelete(ctx_data->signal); + ctx_data->signal = NULL; +} bool is_user_authenticated(httpd_req_t* req) { session_context_t* ctx_data = get_session_context(req); @@ -270,41 +308,64 @@ static const char* get_path_from_uri(char* dest, const char* uri, size_t destsiz /* Return pointer to path, skipping the base */ return last_fs ? ++last_fs : dest; } +bool hasFileExtension(const char* filename, const char* ext) { + size_t fn_len = strlen(filename); + size_t ext_len = strlen(ext); -#define IS_FILE_EXT(filename, ext) \ - (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0) - -/* Set HTTP response content type according to file extension */ -static esp_err_t set_content_type_from_file(httpd_req_t* req, const char* filename) { - if (strlen(filename) == 0) { - // for root page, etc. - return httpd_resp_set_type(req, HTTPD_TYPE_TEXT); - } else if (IS_FILE_EXT(filename, ".pdf")) { - return httpd_resp_set_type(req, "application/pdf"); - } else if (IS_FILE_EXT(filename, ".html")) { - return httpd_resp_set_type(req, HTTPD_TYPE_TEXT); - } else if (IS_FILE_EXT(filename, ".jpeg")) { - return httpd_resp_set_type(req, "image/jpeg"); - } else if (IS_FILE_EXT(filename, ".png")) { - return httpd_resp_set_type(req, "image/png"); - } else if (IS_FILE_EXT(filename, ".ico")) { - return httpd_resp_set_type(req, "image/x-icon"); - } else if (IS_FILE_EXT(filename, ".css")) { - return httpd_resp_set_type(req, "text/css"); - } else if (IS_FILE_EXT(filename, ".js")) { - return httpd_resp_set_type(req, "text/javascript"); - } else if (IS_FILE_EXT(filename, ".json")) { - return httpd_resp_set_type(req, HTTPD_TYPE_JSON); - } else if (IS_FILE_EXT(filename, ".map")) { - return httpd_resp_set_type(req, "map"); - } else if (IS_FILE_EXT(filename, ".pro")) { - return httpd_resp_set_type(req, "application/octet-stream"); + if (ext_len > fn_len) { + return false; } - /* This is a limited set only */ - /* For any other type always set as plain text */ - return httpd_resp_set_type(req, "text/plain"); + return strcasecmp(&filename[fn_len - ext_len], ext) == 0; } + +static esp_err_t set_content_type_from_file(httpd_req_t* req, const char* full_name) { + char filename[strlen(full_name) + 1]; + strcpy(filename, full_name); + if (hasFileExtension(full_name, ".gz")) { + httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); + // Remove the .gz extension for MIME type detection + filename[strlen(full_name) - 3] = '\0'; + } + + if (hasFileExtension(filename, ".html") || hasFileExtension(filename, ".htm")) { + return httpd_resp_set_type(req, "text/html"); + } else if (hasFileExtension(filename, ".css")) { + return httpd_resp_set_type(req, "text/css"); + } else if (hasFileExtension(filename, ".js")) { + return httpd_resp_set_type(req, "application/javascript"); + } else if (hasFileExtension(filename, ".json")) { + return httpd_resp_set_type(req, "application/json"); + } else if (hasFileExtension(filename, ".xml")) { + return httpd_resp_set_type(req, "application/xml"); + } else if (hasFileExtension(filename, ".jpg") || hasFileExtension(filename, ".jpeg")) { + return httpd_resp_set_type(req, "image/jpeg"); + } else if (hasFileExtension(filename, ".png")) { + return httpd_resp_set_type(req, "image/png"); + } else if (hasFileExtension(filename, ".gif")) { + return httpd_resp_set_type(req, "image/gif"); + } else if (hasFileExtension(filename, ".svg")) { + return httpd_resp_set_type(req, "image/svg+xml"); + } else if (hasFileExtension(filename, ".ico")) { + return httpd_resp_set_type(req, "image/x-icon"); + } else if (hasFileExtension(filename, ".pdf")) { + return httpd_resp_set_type(req, "application/pdf"); + } else if (hasFileExtension(filename, ".txt")) { + return httpd_resp_set_type(req, "text/plain"); + } else if (hasFileExtension(filename, ".bin") || hasFileExtension(filename, ".dat")) { + return httpd_resp_set_type(req, "application/octet-stream"); + } else if (hasFileExtension(filename, ".mp3")) { + return httpd_resp_set_type(req, "audio/mpeg"); + } else if (hasFileExtension(filename, ".mp4")) { + return httpd_resp_set_type(req, "video/mp4"); + } else if (hasFileExtension(filename, ".avi")) { + return httpd_resp_set_type(req, "video/x-msvideo"); + } + + // Default MIME type for unknown files + return httpd_resp_set_type(req, "application/octet-stream"); +} + static esp_err_t set_content_type_from_req(httpd_req_t* req) { char filepath[FILE_PATH_MAX]; const char* filename = get_path_from_uri(filepath, req->uri, sizeof(filepath)); @@ -372,54 +433,88 @@ static bool resolve_file_path(const char* uri, char* resolvedpath, size_t resolv // Neither uncompressed nor compressed file exists return false; } -esp_err_t file_get_handler(httpd_req_t* req) { - size_t sz; - char filepath[FILE_PATH_MAX]; - struct stat file_stat={}; +esp_err_t send_file_chunked(httpd_req_t* req, const char* filename) { + struct stat file_stat = {}; + if (stat(filename, &file_stat) == -1) { + ESP_LOGE(TAG, "Failed to stat file : %s", filename); + /* Respond with 404 Not Found */ + httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist"); + return ESP_FAIL; + } - httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); - - ESP_LOGD_LOC(TAG, "Serving file from [%s]", req->uri); - const char* filename = get_path_from_uri(filepath, req->uri, sizeof(filepath)); - if (!filename) { - ESP_LOGE_LOC(TAG, "Filename is too long"); + FILE* fd = fopen(filename, "r"); + if (!fd) { + ESP_LOGE(TAG, "Failed to read existing file : %s", filename); /* Respond with 500 Internal Server Error */ - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long"); - return ESP_FAIL; - } - /* If name has trailing '/', respond with directory contents */ - if (filename[strlen(filename) - 1] == '/') { - httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Browsing files forbidden."); - return ESP_FAIL; - } - if (strlen(filename) != 0 && IS_FILE_EXT(filename, ".map")) { - return httpd_resp_sendstr(req, ""); - } - if (!resolve_file_path(filename, filepath, sizeof(filepath))) { - httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); - return ESP_FAIL; - } - esp_err_t err = set_content_type_from_file(req, filepath); - if (err != ESP_OK) { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file"); return ESP_FAIL; } - char* buffer = load_file(&sz,filepath); - if (buffer) { - if (sz == file_stat.st_size) { - httpd_resp_send(req, buffer, sz); - } else { - ESP_LOGE(TAG, "Failed to read full file : %s", filepath); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read full file"); - err = ESP_FAIL; + ESP_LOGD_LOC(TAG, "Setting content type for %s (%ld bytes)...", filename, file_stat.st_size); + set_content_type_from_file(req, filename); + ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size); + + /* Retrieve the pointer to scratch buffer for temporary storage */ + char* chunk = ((rest_server_context_t*)(req->user_ctx))->scratch; + size_t chunksize; + do { + ESP_LOGD_LOC(TAG,"More data to send"); + /* Read file in chunks into the scratch buffer */ + chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd); + ESP_LOGD_LOC(TAG,"Read chunk size: %d",chunksize); + if (chunksize > 0) { + /* Send the buffer contents as HTTP response chunk */ + if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { + fclose(fd); + ESP_LOGE(TAG, "File sending failed!"); + /* Abort sending file */ + ESP_LOGD_LOC(TAG,"Sending NULL chunk"); + httpd_resp_sendstr_chunk(req, NULL); + ESP_LOGD_LOC(TAG,"Sending 500 internal error"); + /* Respond with 500 Internal Server Error */ + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file"); + ESP_LOGD_LOC(TAG,"returning"); + return ESP_FAIL; + } } - free(buffer); - } else { - ESP_LOGE(TAG, "Failed to allocate memory for file : %s", filepath); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Server out of memory"); + + /* Keep looping till the whole file is sent */ + } while (chunksize != 0); + /* Close file after sending complete */ + fclose(fd); + ESP_LOGI(TAG, "File sending complete for %s", req->uri); + /* Respond with an empty chunk to signal HTTP response completion */ + ESP_LOGD_LOC(TAG,"Closing connection"); + httpd_resp_send_chunk(req, NULL, 0); + + + return ESP_OK; +} +esp_err_t file_get_handler(httpd_req_t* req) { + esp_err_t err = ESP_OK; + char filepath[FILE_PATH_MAX]; + if (!is_spiffs_safe_thread(req)) { + dispatch_response(req, (network_manager_ret_cb_t)file_get_handler); + return ESP_OK; + } + + // const char* filename = get_path_from_uri(filepath, req->uri, sizeof(filepath)); + ESP_LOGD_LOC(TAG, "Serving file from [%s]", req->uri); + if (err == ESP_OK && req->uri[strlen(req->uri) - 1] == '/') { + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Browsing files forbidden."); err = ESP_FAIL; } - return ESP_OK; + if (err == ESP_OK && strlen(req->uri) != 0 && hasFileExtension(req->uri, ".map")) { + err = httpd_resp_sendstr(req, ""); + } else { + if (err == ESP_OK && !resolve_file_path(req->uri, filepath, sizeof(filepath))) { + httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); + err = ESP_FAIL; + } + err = send_file_chunked(req, filepath); + } + finalize_dispatch(req); + return err; } esp_err_t root_get_handler(httpd_req_t* req) { @@ -428,56 +523,34 @@ esp_err_t root_get_handler(httpd_req_t* req) { esp_err_t err = ESP_OK; ESP_LOGD(TAG, "Serving [%s]", req->uri); - httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); - httpd_resp_set_hdr(req, "Accept-Encoding", "identity"); + if (!is_spiffs_safe_thread(req)) { + dispatch_response(req, (network_manager_ret_cb_t)root_get_handler); + return ESP_OK; + } if (!is_user_authenticated(req)) { // TODO: Send password entry page and return } - if (!resolve_file_path("index.html", filepath, sizeof(filepath))) { - httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); - return ESP_FAIL; - } - err = set_content_type_from_file(req, filepath); - if (err != ESP_OK) { - return ESP_FAIL; - } + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + httpd_resp_set_hdr(req, "Accept-Encoding", "identity"); - char* buffer = load_file(&sz,filepath); - if (buffer) { - httpd_resp_send(req, buffer, sz); - free(buffer); - } else { - ESP_LOGE(TAG, "Failed to allocate memory for file : %s", filepath); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Server out of memory"); + if (!resolve_file_path("/index.html", filepath, sizeof(filepath))) { + httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); err = ESP_FAIL; } - - ESP_LOGD(TAG, "Done serving [%s]", req->uri); + err = send_file_chunked(req, filepath); + finalize_dispatch(req); return err; } esp_err_t resource_filehandler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - esp_err_t err = file_get_handler(req); - ESP_LOGD_LOC(TAG, "Resource sending complete"); - return err; -} -esp_err_t ap_scan_handler(httpd_req_t* req) { - const char empty[] = "{}"; - ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { - // todo: redirect to login page - // return ESP_OK; - } - network_async_scan(); - esp_err_t err = set_content_type_from_req(req); - if (err == ESP_OK) { - httpd_resp_send(req, (const char*)empty, HTTPD_RESP_USE_STRLEN); - } + esp_err_t err = file_get_handler(req); + ESP_LOGD_LOC(TAG, "Resource sending complete"); return err; } + esp_err_t console_cmd_get_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); if (!is_user_authenticated(req)) { @@ -553,40 +626,6 @@ esp_err_t console_cmd_post_handler(httpd_req_t* req) { return err; } - -esp_err_t config_get_handler(httpd_req_t* req) { - ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { - // todo: redirect to login page - // return ESP_OK; - } - esp_err_t err = ESP_OK; - -// err= set_content_type_from_req(req); -// if(err == ESP_OK){ -// char * json = config_alloc_get_json(false); -// if(json==NULL){ -// ESP_LOGD_LOC(TAG, "Error retrieving config json string. "); -// httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Error retrieving configuration -// object"); err=ESP_FAIL; -// } -// else { -// ESP_LOGD_LOC(TAG, "config json : %s",json ); -// cJSON * gplist=get_gpio_list(false); -// char * gpliststr=cJSON_PrintUnformatted(gplist); -// httpd_resp_sendstr_chunk(req,"{ \"gpio\":"); -// httpd_resp_sendstr_chunk(req,gpliststr); -// httpd_resp_sendstr_chunk(req,", \"config\":"); -// httpd_resp_sendstr_chunk(req, (const char *)json); -// httpd_resp_sendstr_chunk(req,"}"); -// httpd_resp_sendstr_chunk(req,NULL); -// free(gpliststr); -// free(json); -// } -// } -// TODO: Add support for the commented code - return err; -} esp_err_t post_handler_buff_receive(httpd_req_t* req) { esp_err_t err = ESP_OK; @@ -617,302 +656,101 @@ esp_err_t post_handler_buff_receive(httpd_req_t* req) { } return err; } - -esp_err_t configurator_post_handler(httpd_req_t* req) { - ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - bool bOTA = false; - char* otaURL = NULL; - esp_err_t err = post_handler_buff_receive(req); - if (err != ESP_OK) { - return err; - } - if (!is_user_authenticated(req)) { - // todo: redirect to login page - // return ESP_OK; - } - err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } - - char* buf = ((rest_server_context_t*)(req->user_ctx))->scratch; - cJSON* root = cJSON_Parse(buf); - if (root == NULL) { - ESP_LOGE_LOC(TAG, "Parsing config json failed. Received content was: %s", buf); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed config json. Unable to parse content."); - return ESP_FAIL; - } - - char* root_str = cJSON_Print(root); - if (root_str != NULL) { - ESP_LOGD(TAG, "Processing config item: \n%s", root_str); - free(root_str); - } - - cJSON* item = cJSON_GetObjectItemCaseSensitive(root, "config"); - if (!item) { - ESP_LOGE_LOC(TAG, "Parsing config json failed. Received content was: %s", buf); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed config json. Unable to parse content."); +esp_err_t send_response(httpd_req_t* req, sys_request_response* response) { + esp_err_t err = ESP_OK; + pb_ostream_t http_stream = PB_OSTREAM_SIZING; + http_stream.callback = &out_http_binding; + http_stream.state = req; + http_stream.max_size = SIZE_MAX; + if (!pb_encode(&http_stream, &sys_request_response_msg, response)) { err = ESP_FAIL; - } else { - // navigate to the first child of the config structure - if (item->child) item = item->child; - } - - // while (item && err == ESP_OK) - // { - // cJSON *prev_item = item; - // item=item->next; - // char * entry_str = cJSON_Print(prev_item); - // if(entry_str!=NULL){ - // ESP_LOGD_LOC(TAG, "Processing config item: \n%s", entry_str); - // free(entry_str); - // } - - // if(prev_item->string==NULL) { - // ESP_LOGD_LOC(TAG,"Config value does not have a name"); - // httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed config json. Value does not - // have a name."); err = ESP_FAIL; - // } - // if(err == ESP_OK){ - // ESP_LOGD_LOC(TAG,"Found config value name [%s]", prev_item->string); - // nvs_type_t item_type= config_get_item_type(prev_item); - // if(item_type!=0){ - // void * val = config_safe_alloc_get_entry_value(item_type, prev_item); - // if(val!=NULL){ - // if(strcmp(prev_item->string, "fwurl")==0) { - // if(item_type!=NVS_TYPE_STR){ - // ESP_LOGE_LOC(TAG,"Firmware url should be type %d. Found type %d - // instead.",NVS_TYPE_STR,item_type ); httpd_resp_send_err(req, - // HTTPD_400_BAD_REQUEST, - // "Malformed config json. Wrong type for firmware URL."); err = ESP_FAIL; - // } - // else { - // // we're getting a request to do an OTA from that URL - // ESP_LOGW_LOC(TAG, "Found OTA request!"); - // otaURL=strdup_psram(val); - // bOTA=true; - // } - // } - // else { - // if(config_set_value(item_type, prev_item->string , val) != ESP_OK){ - // ESP_LOGE_LOC(TAG,"Unable to store value for [%s]", prev_item->string); - // httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Unable to store - // config value"); err = ESP_FAIL; - // } - // else { - // ESP_LOGD_LOC(TAG,"Successfully set value for [%s]",prev_item->string); - // } - // } - // free(val); - // } - // else { - // char messageBuffer[101]={}; - // ESP_LOGE_LOC(TAG,"Value not found for [%s]", prev_item->string); - // snprintf(messageBuffer,sizeof(messageBuffer),"Malformed config json. Missing value - // for entry %s.",prev_item->string); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, - // messageBuffer); err = ESP_FAIL; - // } - // } - // else { - // ESP_LOGE_LOC(TAG,"Unable to determine the type of config value [%s]", - // prev_item->string); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed config - // json. Missing value for entry."); err = ESP_FAIL; - // } - // } - // } - - cJSON_Delete(root); - if (bOTA) { - - if (is_recovery_running) { - ESP_LOGW_LOC(TAG, "Starting process OTA for url %s", otaURL); - } else { - ESP_LOGW_LOC(TAG, "Restarting system to process OTA for url %s", otaURL); - } - - network_reboot_ota(otaURL); - free(otaURL); } + /* Respond with an empty chunk to signal HTTP response completion */ + httpd_resp_send_chunk(req, NULL, 0); return err; } -esp_err_t configurator_get_handler(httpd_req_t* req) { +esp_err_t data_post_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); + sys_request_payload payload; + sys_request_response response; + response.result = sys_request_result_SUCCESS; + response.message = ""; + char* otaURL = NULL; if (!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } - esp_err_t err = ESP_OK; - void* config = NULL; - size_t datalen; + esp_err_t err = set_content_type_from_req(req); + if (err != ESP_OK) { + return err; + } + pb_istream_t http_stream = PB_ISTREAM_EMPTY; + http_stream.callback = &in_http_binding; + http_stream.state = req; + http_stream.bytes_left = req->content_len; - err = set_content_type_from_req(req); + if (!pb_decode(&http_stream, &sys_request_payload_msg, &payload)) { + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, http_stream.errmsg); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Received Payload"); + dump_structure(&sys_request_payload_msg, &payload); - if (err == ESP_OK) { - config = configurator_alloc_get_config(&datalen); - if (!config) { - ESP_LOGE_LOC(TAG, "Unable to serialize configuration"); - httpd_resp_send_err( - req, HTTPD_500_INTERNAL_SERVER_ERROR, "Unable to serialize configuration"); + switch (payload.type) { + case sys_request_type_CONFIG: + if (payload.action == sys_request_action_GET) { + if (!config_http_send_config(req)) { + err = ESP_FAIL; + } + } else { + // we are setting a config object + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Not implemented"); + err = ESP_FAIL; + } + break; + case sys_request_type_STATUS: + if (payload.action == sys_request_action_GET) { + if(!network_status_send_object(req)){ + err = ESP_FAIL; + } + } + else { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid request type"); + err = ESP_FAIL; + } + break; + case sys_request_type_SCAN: + if (payload.action == sys_request_action_GET) { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "SCAN List should be retrieved with request type STATUS"); err = ESP_FAIL; } else { - httpd_resp_send(req, (const char*)config, datalen); - free(config); + network_async_scan(); } - } - -// if(err == ESP_OK){ -// char * json = config_alloc_get_json(false); -// if(json==NULL){ -// ESP_LOGD_LOC(TAG, "Error retrieving config json string. "); -// httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Error retrieving configuration -// object"); err=ESP_FAIL; -// } -// else { -// ESP_LOGD_LOC(TAG, "config json : %s",json ); -// cJSON * gplist=get_gpio_list(false); -// char * gpliststr=cJSON_PrintUnformatted(gplist); -// httpd_resp_sendstr_chunk(req,"{ \"gpio\":"); -// httpd_resp_sendstr_chunk(req,gpliststr); -// httpd_resp_sendstr_chunk(req,", \"config\":"); -// httpd_resp_sendstr_chunk(req, (const char *)json); -// httpd_resp_sendstr_chunk(req,"}"); -// httpd_resp_sendstr_chunk(req,NULL); -// free(gpliststr); -// free(json); -// } -// } -// TODO: Add support for the commented code - return err; -} - -esp_err_t config_post_handler(httpd_req_t* req) { - ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - bool bOTA = false; - char* otaURL = NULL; - esp_err_t err = post_handler_buff_receive(req); - if (err != ESP_OK) { - return err; - } - if (!is_user_authenticated(req)) { - // todo: redirect to login page - // return ESP_OK; - } - err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } - - char* buf = ((rest_server_context_t*)(req->user_ctx))->scratch; - cJSON* root = cJSON_Parse(buf); - if (root == NULL) { - ESP_LOGE_LOC(TAG, "Parsing config json failed. Received content was: %s", buf); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed config json. Unable to parse content."); - return ESP_FAIL; - } - - char* root_str = cJSON_Print(root); - if (root_str != NULL) { - ESP_LOGD(TAG, "Processing config item: \n%s", root_str); - free(root_str); - } - - cJSON* item = cJSON_GetObjectItemCaseSensitive(root, "config"); - if (!item) { - ESP_LOGE_LOC(TAG, "Parsing config json failed. Received content was: %s", buf); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed config json. Unable to parse content."); - err = ESP_FAIL; - } else { - // navigate to the first child of the config structure - if (item->child) item = item->child; - } - - // while (item && err == ESP_OK) - // { - // cJSON *prev_item = item; - // item=item->next; - // char * entry_str = cJSON_Print(prev_item); - // if(entry_str!=NULL){ - // ESP_LOGD_LOC(TAG, "Processing config item: \n%s", entry_str); - // free(entry_str); - // } - - // if(prev_item->string==NULL) { - // ESP_LOGD_LOC(TAG,"Config value does not have a name"); - // httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed config json. Value does not - // have a name."); err = ESP_FAIL; - // } - // if(err == ESP_OK){ - // ESP_LOGD_LOC(TAG,"Found config value name [%s]", prev_item->string); - // nvs_type_t item_type= config_get_item_type(prev_item); - // if(item_type!=0){ - // void * val = config_safe_alloc_get_entry_value(item_type, prev_item); - // if(val!=NULL){ - // if(strcmp(prev_item->string, "fwurl")==0) { - // if(item_type!=NVS_TYPE_STR){ - // ESP_LOGE_LOC(TAG,"Firmware url should be type %d. Found type %d - // instead.",NVS_TYPE_STR,item_type ); httpd_resp_send_err(req, - // HTTPD_400_BAD_REQUEST, - // "Malformed config json. Wrong type for firmware URL."); err = ESP_FAIL; - // } - // else { - // // we're getting a request to do an OTA from that URL - // ESP_LOGW_LOC(TAG, "Found OTA request!"); - // otaURL=strdup_psram(val); - // bOTA=true; - // } - // } - // else { - // if(config_set_value(item_type, prev_item->string , val) != ESP_OK){ - // ESP_LOGE_LOC(TAG,"Unable to store value for [%s]", prev_item->string); - // httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Unable to store - // config value"); err = ESP_FAIL; - // } - // else { - // ESP_LOGD_LOC(TAG,"Successfully set value for [%s]",prev_item->string); - // } - // } - // free(val); - // } - // else { - // char messageBuffer[101]={}; - // ESP_LOGE_LOC(TAG,"Value not found for [%s]", prev_item->string); - // snprintf(messageBuffer,sizeof(messageBuffer),"Malformed config json. Missing value - // for entry %s.",prev_item->string); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, - // messageBuffer); err = ESP_FAIL; - // } - // } - // else { - // ESP_LOGE_LOC(TAG,"Unable to determine the type of config value [%s]", - // prev_item->string); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed config - // json. Missing value for entry."); err = ESP_FAIL; - // } - // } - // } -// TODO: Add support for the commented code - - if (err == ESP_OK) { - httpd_resp_sendstr(req, "{ \"result\" : \"OK\" }"); - messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "Save Success"); - } - cJSON_Delete(root); - if (bOTA) { - - if (is_recovery_running) { - ESP_LOGW_LOC(TAG, "Starting process OTA for url %s", otaURL); + break; + case sys_request_type_OTA: + if (payload.which_data != sys_request_payload_URL_tag) { + response.result = sys_request_result_ERROR; + response.message = "Missing URL"; } else { - ESP_LOGW_LOC(TAG, "Restarting system to process OTA for url %s", otaURL); + otaURL = strdup_psram(payload.data.URL); + if (is_recovery_running) { + ESP_LOGW_LOC(TAG, "Starting process OTA for url %s", otaURL); + } else { + ESP_LOGW_LOC(TAG, "Restarting system to process OTA for url %s", otaURL); + } + network_reboot_ota(otaURL); } + break; - network_reboot_ota(otaURL); - free(otaURL); + default: + break; } + send_response(req, &response); + + pb_release(&sys_request_payload_msg, &payload); return err; } + esp_err_t connect_post_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); char success[] = "{}"; @@ -955,14 +793,15 @@ esp_err_t connect_post_handler(httpd_req_t* req) { } cJSON_Delete(root); -// if(host_name!=NULL){ -// if(config_set_value(NVS_TYPE_STR, "host_name", host_name) != ESP_OK){ -// ESP_LOGW_LOC(TAG, "Unable to save host name configuration"); -// } -// } -// TODO: Add support for the commented code + // if(host_name!=NULL){ + // if(config_set_value(NVS_TYPE_STR, "host_name", host_name) != ESP_OK){ + // ESP_LOGW_LOC(TAG, "Unable to save host name configuration"); + // } + // } - if (ssid != NULL && strlen(ssid) <= MAX_SSID_SIZE && strlen(password) <= MAX_PASSWORD_SIZE) { +#pragma message("Update this to protocol buffers") + if (ssid != NULL && strlen(ssid) <= platform->net.max_ssid_size && + strlen(password) <= platform->net.max_password_size) { network_async_connect(ssid, password); httpd_resp_send(req, (const char*)success, strlen(success)); } else { @@ -970,10 +809,10 @@ esp_err_t connect_post_handler(httpd_req_t* req) { req, HTTPD_400_BAD_REQUEST, "Malformed json. Missing or invalid ssid/password."); err = ESP_FAIL; } -// FREE_AND_NULL(ssid); -// FREE_AND_NULL(password); -// FREE_AND_NULL(host_name); -// TODO: Add support for the commented code + // FREE_AND_NULL(ssid); + // FREE_AND_NULL(password); + // FREE_AND_NULL(host_name); + // TODO: Add support for the commented code return err; } esp_err_t connect_delete_handler(httpd_req_t* req) { @@ -1080,8 +919,8 @@ esp_err_t flash_post_handler(httpd_req_t* req) { /* Retry if timeout occurred */ continue; } -// FREE_RESET(binary_buffer); -// TODO: Add support for the commented code + // FREE_RESET(binary_buffer); + // TODO: Add support for the commented code ESP_LOGE(TAG, "File reception failed!"); /* Respond with 500 Internal Server Error */ httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file"); @@ -1208,13 +1047,7 @@ esp_err_t redirect_processor(httpd_req_t* req, httpd_err_code_t error) { remote_ip = http_alloc_get_socket_address(req, 0, &port); ESP_LOGW_LOC(TAG, "%s requested invalid URL: [%s]", remote_ip, req->uri); - if (network_status_lock_structure(portMAX_DELAY)) { - sta_ip_address = strdup_psram(status.net.ip.ip); - network_status_unlock_structure(); - } else { - ESP_LOGE(TAG, "Unable to obtain local IP address from WiFi Manager."); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, NULL); - } + sta_ip_address = strdup_psram(sys_status->net.ip.ip); ESP_LOGV_LOC(TAG, "Getting host name from request"); char* req_host = alloc_get_http_header(req, "Host"); @@ -1326,25 +1159,7 @@ esp_err_t status_get_handler(httpd_req_t* req) { if (err != ESP_OK) { return err; } - - ESP_LOGD(TAG, "Creating binding"); - pb_ostream_t filestream = {&out_http_binding, req, SIZE_MAX, 0}; - ESP_LOGD(TAG, "Starting encode"); - if (!pb_encode(&filestream, sys_Config_fields, (void*)&status)) { - ESP_LOGE(TAG, "Encoding failed: %s\n", PB_GET_ERROR(&filestream)); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, PB_GET_ERROR(&filestream)); - } - else { - ESP_LOGD(TAG, "Encoded size: %d", filestream.bytes_written); - if (filestream.bytes_written == 0) { - ESP_LOGE(TAG, "Empty status!"); - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Empty status!"); - } - } - - // update status for next status call - network_async_update_status(); - + network_status_send_object(req); return ESP_OK; } diff --git a/components/wifi-manager/http_server_handlers.h b/components/wifi-manager/http_server_handlers.h index 78f487c7..d880c5a6 100644 --- a/components/wifi-manager/http_server_handlers.h +++ b/components/wifi-manager/http_server_handlers.h @@ -1,71 +1,86 @@ /* -Copyright (c) 2017-2021 Sebastien L -*/ + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ #ifndef HTTP_SERVER_H_INCLUDED #define HTTP_SERVER_H_INCLUDED -#include -#include -#include -#include -#include "esp_http_server.h" -#include "network_manager.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_wifi.h" -#include "nvs_flash.h" -#include "esp_log.h" #include "driver/gpio.h" -#include "mdns.h" +#include "esp_console.h" +#include "esp_http_server.h" +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "freertos/task.h" #include "lwip/api.h" #include "lwip/err.h" +#include "lwip/ip.h" +#include "lwip/memp.h" #include "lwip/netdb.h" #include "lwip/opt.h" -#include "lwip/memp.h" -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" #include "lwip/priv/api_msg.h" #include "lwip/priv/tcp_priv.h" #include "lwip/priv/tcpip_priv.h" -#include "esp_vfs.h" -#include "esp_console.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "mdns.h" +#include "network_manager.h" +#include "nvs_flash.h" +#include +#include +#include +#include #ifdef __cplusplus extern "C" { #endif -#define ESP_LOGE_LOC(t,str, ...) ESP_LOGE(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define ESP_LOGI_LOC(t,str, ...) ESP_LOGI(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define ESP_LOGD_LOC(t,str, ...) ESP_LOGD(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define ESP_LOGW_LOC(t,str, ...) ESP_LOGW(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define ESP_LOGV_LOC(t,str, ...) ESP_LOGV(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ESP_LOGE_LOC(t, str, ...) ESP_LOGE(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ESP_LOGI_LOC(t, str, ...) ESP_LOGI(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ESP_LOGD_LOC(t, str, ...) ESP_LOGD(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ESP_LOGW_LOC(t, str, ...) ESP_LOGW(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ESP_LOGV_LOC(t, str, ...) ESP_LOGV(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__) +esp_err_t root_get_handler(httpd_req_t* req); +esp_err_t resource_filehandler(httpd_req_t* req); -esp_err_t root_get_handler(httpd_req_t *req); -esp_err_t resource_filehandler(httpd_req_t *req); +esp_err_t connect_post_handler(httpd_req_t* req); +esp_err_t connect_delete_handler(httpd_req_t* req); +esp_err_t reboot_ota_post_handler(httpd_req_t* req); +esp_err_t reboot_post_handler(httpd_req_t* req); +esp_err_t recovery_post_handler(httpd_req_t* req); +esp_err_t flash_post_handler(httpd_req_t* req); +esp_err_t status_get_handler(httpd_req_t* req); +esp_err_t messages_get_handler(httpd_req_t* req); +esp_err_t console_cmd_get_handler(httpd_req_t* req); +esp_err_t console_cmd_post_handler(httpd_req_t* req); +esp_err_t ap_scan_handler(httpd_req_t* req); +esp_err_t redirect_ev_handler(httpd_req_t* req); +esp_err_t redirect_200_ev_handler(httpd_req_t* req); +esp_err_t data_post_handler(httpd_req_t* req); -esp_err_t config_get_handler(httpd_req_t *req); -esp_err_t config_post_handler(httpd_req_t *req); -esp_err_t connect_post_handler(httpd_req_t *req); -esp_err_t connect_delete_handler(httpd_req_t *req); -esp_err_t reboot_ota_post_handler(httpd_req_t *req); -esp_err_t reboot_post_handler(httpd_req_t *req); -esp_err_t recovery_post_handler(httpd_req_t *req); -esp_err_t flash_post_handler(httpd_req_t *req); -esp_err_t status_get_handler(httpd_req_t *req); -esp_err_t messages_get_handler(httpd_req_t *req); -esp_err_t console_cmd_get_handler(httpd_req_t *req); -esp_err_t console_cmd_post_handler(httpd_req_t *req); -esp_err_t ap_scan_handler(httpd_req_t *req); -esp_err_t redirect_ev_handler(httpd_req_t *req); -esp_err_t redirect_200_ev_handler(httpd_req_t *req); -esp_err_t configurator_post_handler(httpd_req_t *req); -esp_err_t configurator_get_handler(httpd_req_t *req); - -esp_err_t err_handler(httpd_req_t *req, httpd_err_code_t error); -#define SCRATCH_BUFSIZE (10240) +esp_err_t err_handler(httpd_req_t* req, httpd_err_code_t error); +#define SCRATCH_BUFSIZE (8192) #define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128) typedef struct rest_server_context { @@ -76,36 +91,41 @@ typedef struct rest_server_context { * @brief RTOS task for the HTTP server. Do not start manually. * @see void http_server_start() */ -void http_server(void *pvParameters); +void http_server(void* pvParameters); /* @brief helper function that processes one HTTP request at a time */ -void http_server_netconn_serve(struct netconn *conn); +void http_server_netconn_serve(struct netconn* conn); /* @brief create the task for the http server */ esp_err_t http_server_start(); /** - * @brief gets a char* pointer to the first occurence of header_name withing the complete http request request. + * @brief gets a char* pointer to the first occurence of header_name withing the complete http + * request request. * - * For optimization purposes, no local copy is made. memcpy can then be used in coordination with len to extract the - * data. + * For optimization purposes, no local copy is made. memcpy can then be used in coordination with + * len to extract the data. * * @param request the full HTTP raw request. * @param header_name the header that is being searched. * @param len the size of the header value if found. * @return pointer to the beginning of the header value. */ -char* http_server_get_header(char *request, char *header_name, int *len); +char* http_server_get_header(char* request, char* header_name, int* len); -void strreplace(char *src, char *str, char *rep); +void strreplace(char* src, char* str, char* rep); /* @brief lock the json config object */ bool http_server_lock_json_object(TickType_t xTicksToWait); /* @brief unlock the json config object */ void http_server_unlock_json_object(); -httpd_handle_t http_get_server(int *port); -#define PROTECTED_JSON_CALL(a) if(http_server_lock_json_object( portMAX_DELAY )){ \ a; http_server_unlocklock_json_object(); } else{ ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); } - - +httpd_handle_t http_get_server(int* port); +#define PROTECTED_JSON_CALL(a) \ + if (http_server_lock_json_object(portMAX_DELAY)) { \ + \ a; \ + http_server_unlocklock_json_object(); \ + } else { \ + ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); \ + } #ifdef __cplusplus } diff --git a/components/wifi-manager/network_driver_DM9051.c b/components/wifi-manager/network_driver_DM9051.c index 8cbc8dd2..726e1ada 100644 --- a/components/wifi-manager/network_driver_DM9051.c +++ b/components/wifi-manager/network_driver_DM9051.c @@ -5,19 +5,33 @@ static EXT_RAM_ATTR network_ethernet_driver_t DM9051; static EXT_RAM_ATTR spi_device_interface_config_t devcfg; static EXT_RAM_ATTR esp_netif_config_t cfg_spi; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; - -static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth* ethernet_config) { +static EXT_RAM_ATTR gpio_num_t rst = -1; +static esp_err_t reset_hw(esp_eth_phy_t *phy) +{ + // set reset_gpio_num to a negative value can skip hardware reset phy chip + if (rst >= 0) { + esp_rom_gpio_pad_select_gpio_x(rst); + gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); + gpio_set_level_x(rst, 0); + /* assert nRST signal on LAN87xx a little longer than the minimum specified in datasheet */ + esp_rom_delay_us(150); + gpio_set_level_x(rst, 1); + } + return ESP_OK; +} +static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config* ethernet_config) { #ifdef CONFIG_ETH_SPI_ETHERNET_DM9051 eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_dm9051_config_t eth_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); // we assume that isr has been installed already - eth_config.int_gpio_num = ethernet_config->ethType.spi.has_intr?ethernet_config->ethType.spi.intr.pin:-1; + eth_config.int_gpio_num = ethernet_config->ethType.spi.intr; phy_config.phy_addr = -1; - phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1; - + phy_config.reset_gpio_num = ethernet_config->common.rst; + rst = phy_config.reset_gpio_num; esp_eth_mac_t* mac = esp_eth_mac_new_dm9051(ð_config, &mac_config); esp_eth_phy_t* phy = esp_eth_phy_new_dm9051(&phy_config); + phy->reset_hw = reset_hw; esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); return esp_eth_driver_install(&config, &DM9051.handle); #else @@ -25,14 +39,14 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth* ethernet_config) #endif } -static void init_config(sys_Eth* ethernet_config) { +static void init_config(sys_dev_eth_config* ethernet_config) { esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); devcfg.command_bits = 1; devcfg.address_bits = 7; devcfg.mode = 0; devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed devcfg.queue_size = 20; - devcfg.spics_io_num = ethernet_config->ethType.spi.has_cs?ethernet_config->ethType.spi.cs.pin:-1; + devcfg.spics_io_num = ethernet_config->ethType.spi.cs; memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); cfg_spi.base = &esp_netif_config, cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; @@ -41,9 +55,9 @@ static void init_config(sys_Eth* ethernet_config) { DM9051.start = start; } -network_ethernet_driver_t* DM9051_Detect(sys_Eth* ethernet_config) { - if (ethernet_config->common.model != sys_EthModelEnum_DM9051 || - ethernet_config->which_ethType != sys_Eth_spi_tag ) +network_ethernet_driver_t* DM9051_Detect(sys_dev_eth_config* ethernet_config) { + if (ethernet_config->common.model != sys_dev_eth_models_DM9051 || + ethernet_config->which_ethType != sys_dev_eth_config_spi_tag ) return NULL; DM9051.rmii = false; DM9051.spi = true; diff --git a/components/wifi-manager/network_driver_LAN8720.c b/components/wifi-manager/network_driver_LAN8720.c index 1f29c9f2..76f6a1d5 100644 --- a/components/wifi-manager/network_driver_LAN8720.c +++ b/components/wifi-manager/network_driver_LAN8720.c @@ -4,19 +4,34 @@ static EXT_RAM_ATTR network_ethernet_driver_t LAN8720; static EXT_RAM_ATTR esp_netif_config_t cfg_rmii; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; - -static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth * ethernet_config) { +static EXT_RAM_ATTR gpio_num_t rst = -1; +static esp_err_t reset_hw(esp_eth_phy_t *phy) +{ + // set reset_gpio_num to a negative value can skip hardware reset phy chip + if (rst >= 0) { + esp_rom_gpio_pad_select_gpio_x(rst); + gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); + gpio_set_level_x(rst, 0); + /* assert nRST signal on LAN87xx a little longer than the minimum specified in datasheet */ + esp_rom_delay_us(150); + gpio_set_level_x(rst, 1); + } + return ESP_OK; +} +static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethernet_config) { #ifdef CONFIG_ETH_PHY_INTERFACE_RMII eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - mac_config.smi_mdc_gpio_num = ethernet_config->ethType.rmii.has_mdc?ethernet_config->ethType.rmii.mdc.pin:-1; - mac_config.smi_mdio_gpio_num = ethernet_config->ethType.rmii.has_mdio?ethernet_config->ethType.rmii.mdio.pin:-1; + mac_config.smi_mdc_gpio_num = ethernet_config->ethType.rmii.mdc; + mac_config.smi_mdio_gpio_num = ethernet_config->ethType.rmii.mdio; phy_config.phy_addr = 1; - phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1; + phy_config.reset_gpio_num = ethernet_config->common.rst; + rst = phy_config.reset_gpio_num; esp_eth_mac_t* mac = esp_eth_mac_new_esp32(&mac_config); esp_eth_phy_t* phy = esp_eth_phy_new_lan8720(&phy_config); + phy->reset_hw = reset_hw; esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); return esp_eth_driver_install(&config, &LAN8720.handle); #else @@ -24,7 +39,7 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth * ethernet_config #endif } -static void init_config(sys_Eth * ethernet_config) { +static void init_config(sys_dev_eth_config * ethernet_config) { esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); @@ -35,9 +50,9 @@ static void init_config(sys_Eth * ethernet_config) { LAN8720.start = start; } -network_ethernet_driver_t* LAN8720_Detect(sys_Eth * ethernet_config) { - if (ethernet_config->common.model != sys_EthModelEnum_LAN8720 || - ethernet_config->which_ethType != sys_Eth_rmii_tag) +network_ethernet_driver_t* LAN8720_Detect(sys_dev_eth_config * ethernet_config) { + if (ethernet_config->common.model != sys_dev_eth_models_LAN8720 || + ethernet_config->which_ethType != sys_dev_eth_config_rmii_tag) return NULL; #ifdef CONFIG_ETH_PHY_INTERFACE_RMII LAN8720.valid = true; diff --git a/components/wifi-manager/network_driver_W5500.c b/components/wifi-manager/network_driver_W5500.c index cc892987..5d4b8bb0 100644 --- a/components/wifi-manager/network_driver_W5500.c +++ b/components/wifi-manager/network_driver_W5500.c @@ -5,26 +5,41 @@ static EXT_RAM_ATTR network_ethernet_driver_t W5500; static EXT_RAM_ATTR spi_device_interface_config_t devcfg; static EXT_RAM_ATTR esp_netif_config_t cfg_spi; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; +static EXT_RAM_ATTR gpio_num_t rst = -1; +static esp_err_t reset_hw(esp_eth_phy_t *phy) +{ + // set reset_gpio_num to a negative value can skip hardware reset phy chip + if (rst >= 0) { + esp_rom_gpio_pad_select_gpio_x(rst); + gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); + gpio_set_level_x(rst, 0); + esp_rom_delay_us(100); // insert min input assert time + gpio_set_level_x(rst, 1); + } + return ESP_OK; +} -static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth * ethernet_config) { +static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethernet_config) { #ifdef CONFIG_ETH_SPI_ETHERNET_W5500 eth_w5500_config_t eth_config = ETH_W5500_DEFAULT_CONFIG(spi_handle); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - eth_config.int_gpio_num = ethernet_config->ethType.spi.has_intr?ethernet_config->ethType.spi.intr.pin:-1; + eth_config.int_gpio_num = ethernet_config->ethType.spi.intr; phy_config.phy_addr = -1; // let the system automatically find out the phy address - phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1; + rst = ethernet_config->common.rst; + phy_config.reset_gpio_num = rst; esp_eth_mac_t* mac = esp_eth_mac_new_w5500(ð_config, &mac_config); esp_eth_phy_t* phy = esp_eth_phy_new_w5500(&phy_config); + phy->reset_hw = reset_hw; esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); return esp_eth_driver_install(&config, &W5500.handle); #else return ESP_ERR_NOT_SUPPORTED; #endif } -static void init_config(sys_Eth * ethernet_config) { +static void init_config(sys_dev_eth_config * ethernet_config) { // This function is called when the network interface is started // and performs any initialization that requires a valid ethernet // configuration . @@ -34,7 +49,7 @@ static void init_config(sys_Eth * ethernet_config) { devcfg.mode = 0; devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed devcfg.queue_size = 20; - devcfg.spics_io_num = ethernet_config->ethType.spi.has_cs?ethernet_config->ethType.spi.cs.pin:-1; + devcfg.spics_io_num = ethernet_config->ethType.spi.cs; memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); cfg_spi.base = &esp_netif_config, cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; @@ -43,9 +58,9 @@ static void init_config(sys_Eth * ethernet_config) { W5500.start = start; } -network_ethernet_driver_t* W5500_Detect(sys_Eth * ethernet_config) { - if (ethernet_config->common.model != sys_EthModelEnum_W5500 || - ethernet_config->which_ethType != sys_Eth_spi_tag ) +network_ethernet_driver_t* W5500_Detect(sys_dev_eth_config * ethernet_config) { + if (ethernet_config->common.model != sys_dev_eth_models_W5500 || + ethernet_config->which_ethType != sys_dev_eth_config_spi_tag ) return NULL; W5500.init_config = init_config; W5500.spi = true; diff --git a/components/wifi-manager/network_ethernet.c b/components/wifi-manager/network_ethernet.c index 5f90e548..a9c02669 100644 --- a/components/wifi-manager/network_ethernet.c +++ b/components/wifi-manager/network_ethernet.c @@ -2,14 +2,13 @@ #define LOG_LOCAL_LEVEL NETWORK_ETHERNET_LOG_LEVEL #endif #include "network_ethernet.h" -#include "freertos/timers.h" -#include "messaging.h" -#include "network_status.h" -// #include "Configurator.h" -#pragma message("fixme: search for TODO below") +#include "Config.h" #include "accessors.h" #include "esp_log.h" +#include "freertos/timers.h" #include "globdefs.h" +#include "messaging.h" +#include "network_status.h" #include "tools.h" static char TAG[] = "network_ethernet"; @@ -20,22 +19,21 @@ const int LINK_UP_BIT = BIT0; static network_ethernet_driver_t* network_driver = NULL; extern network_ethernet_detect_func_t DM9051_Detect, W5500_Detect, LAN8720_Detect; -static network_ethernet_detect_func_t* drivers[] = { - DM9051_Detect, W5500_Detect, LAN8720_Detect, NULL}; +static network_ethernet_detect_func_t* drivers[] = {DM9051_Detect, W5500_Detect, LAN8720_Detect, NULL}; #define ETH_TIMEOUT_MS (30 * 1000) network_ethernet_driver_t* network_ethernet_driver_autodetect() { - sys_Eth* eth_config; - sys_EthCommon* eth_common; + sys_dev_eth_config * eth_config; + sys_dev_eth_common* eth_common; if (!SYS_ETH(eth_config) || !SYS_ETH_COMMON(eth_common)) { ESP_LOGD(TAG, "Ethernet not configured"); return NULL; } - for (uint8_t i = _sys_EthModelEnum_MIN; i < _sys_EthModelEnum_MAX; i++) { + for (uint8_t i = _sys_dev_eth_models_MIN; i < _sys_dev_eth_models_MAX; i++) { network_ethernet_driver_t* found_driver = drivers[i](eth_config); if (found_driver) { - ESP_LOGI(TAG, "Detected driver %s ", sys_EthModelEnum_name(eth_common->model)); + ESP_LOGI(TAG, "Detected driver %s ", sys_dev_eth_models_name(eth_common->model)); network_driver = found_driver; return found_driver; } @@ -43,22 +41,17 @@ network_ethernet_driver_t* network_ethernet_driver_autodetect() { return NULL; } -static void eth_event_handler( - void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); +static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); esp_netif_t* network_ethernet_get_interface() { return eth_netif; } -bool network_ethernet_is_up() { - return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0; -} +bool network_ethernet_is_up() { return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0; } bool network_ethernet_enabled() { return network_driver != NULL && network_driver->handle != NULL; } bool network_ethernet_wait_for_link(uint16_t max_wait_ms) { if (!network_ethernet_enabled()) return false; bool link_up = (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0; if (!link_up) { ESP_LOGD(TAG, "Waiting for Ethernet link to be established..."); - link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT, pdFALSE, pdTRUE, - max_wait_ms / portTICK_PERIOD_MS) & - LINK_UP_BIT) != 0; + link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT, pdFALSE, pdTRUE, max_wait_ms / portTICK_PERIOD_MS) & LINK_UP_BIT) != 0; if (!link_up) { ESP_LOGW(TAG, "Ethernet Link timeout."); } else { @@ -72,47 +65,41 @@ static void ETH_Timeout(void* timer_id); void destroy_network_ethernet() {} static void network_ethernet_print_config(const network_ethernet_driver_t* eth_config) { - sys_Eth* sys_eth; + sys_dev_eth_config * sys_eth; int mdc = -1, mdio = -1, rst = -1, intr = -1, cs = -1; - int16_t speed = 0; + uint32_t speed = 0; int8_t host = 0; if (SYS_ETH(sys_eth)) { - if (sys_eth->which_ethType == sys_Eth_spi_tag) { - if (sys_eth->ethType.spi.has_cs) { - cs = sys_eth->ethType.spi.cs.pin; - } - if (sys_eth->ethType.spi.has_intr) { - intr = sys_eth->ethType.spi.intr.pin; - } - speed = sys_eth->ethType.spi.speed; - host = sys_eth->ethType.spi.host; + rst = sys_eth->common.rst; - } else if (sys_eth->which_ethType == sys_Eth_rmii_tag) { - if (sys_eth->ethType.rmii.has_mdc) { - mdc = sys_eth->ethType.rmii.mdc.pin; - } - if (sys_eth->ethType.rmii.has_mdio) { - mdio = sys_eth->ethType.rmii.mdio.pin; - } + if (sys_eth->which_ethType == sys_dev_eth_config_spi_tag) { + cs = sys_eth->ethType.spi.cs; + intr = sys_eth->ethType.spi.intr; + speed = sys_eth->ethType.spi.speed; + host = sys_eth->ethType.spi.host - sys_dev_common_hosts_Host0; + + } else if (sys_eth->which_ethType == sys_dev_eth_config_rmii_tag) { + mdc = sys_eth->ethType.rmii.mdc; + mdio = sys_eth->ethType.rmii.mdio; } } ESP_LOGI(TAG, "Ethernet config => model: %s, valid: %s, type: %s, mdc:%d, mdio:%d, rst:%d, intr:%d, " "cs:%d, speed:%d, host:%d", - sys_EthModelEnum_name(eth_config->model), eth_config->valid ? "YES" : "NO", - eth_config->spi ? "SPI" : "RMII", mdc, mdio, rst, intr, cs, speed, host); + sys_dev_eth_models_name(eth_config->model), eth_config->valid ? "YES" : "NO", eth_config->spi ? "SPI" : "RMII", mdc, mdio, rst, intr, cs, speed, + host); } void init_network_ethernet() { esp_err_t err = ESP_OK; ESP_LOGI(TAG, "Attempting to initialize Ethernet"); - sys_Eth* sys_eth; - if(!SYS_ETH(sys_eth)){ - ESP_LOGD(TAG,"No ethernet configured"); + sys_dev_eth_config * sys_eth; + if (!SYS_ETH(sys_eth)) { + ESP_LOGD(TAG, "No ethernet configured"); return; } - network_ethernet_driver_t*driver= network_ethernet_driver_autodetect(); + network_ethernet_driver_t* driver = network_ethernet_driver_autodetect(); if (!driver || !driver->valid) { ESP_LOGI(TAG, "No Ethernet configuration, or configuration invalid"); return; @@ -122,13 +109,13 @@ void init_network_ethernet() { network_ethernet_print_config(driver); eth_netif = esp_netif_new(network_driver->cfg_netif); - esp_eth_set_default_handlers(eth_netif); + // esp_eth_set_default_handlers(eth_netif); esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL); ethernet_event_group = xEventGroupCreate(); xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT); spi_device_handle_t spi_handle = NULL; - if (sys_eth->which_ethType == sys_Eth_spi_tag) { - err = spi_bus_add_device(sys_eth->ethType.spi.host, network_driver->devcfg, &spi_handle); + if (sys_eth->which_ethType == sys_dev_eth_config_spi_tag) { + err = spi_bus_add_device(sys_eth->ethType.spi.host - sys_dev_common_hosts_Host0, network_driver->devcfg, &spi_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "SPI host failed : %s", esp_err_to_name(err)); } @@ -139,7 +126,7 @@ void init_network_ethernet() { if (err == ESP_OK) { uint8_t mac_address[6]; esp_read_mac(mac_address, ESP_MAC_ETH); - char* mac_string = network_manager_alloc_get_mac_string(mac_address); + char* mac_string = alloc_get_formatted_mac_string(mac_address); ESP_LOGD(TAG, "Assigning mac address %s to ethernet interface", STR_OR_BLANK(mac_string)); FREE_AND_NULL(mac_string); esp_eth_ioctl(network_driver->handle, ETH_CMD_S_MAC_ADDR, mac_address); @@ -153,8 +140,7 @@ void init_network_ethernet() { err = esp_eth_start(network_driver->handle); } if (err != ESP_OK) { - messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, - "Configuring Ethernet failed: %s", esp_err_to_name(err)); + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Configuring Ethernet failed: %s", esp_err_to_name(err)); if (spi_handle) { spi_bus_remove_device(spi_handle); } @@ -162,14 +148,10 @@ void init_network_ethernet() { } } -void network_ethernet_start_timer() { - ETH_timer = - xTimerCreate("ETH check", pdMS_TO_TICKS(ETH_TIMEOUT_MS), pdFALSE, NULL, ETH_Timeout); -} +void network_ethernet_start_timer() { ETH_timer = xTimerCreate("ETH check", pdMS_TO_TICKS(ETH_TIMEOUT_MS), pdFALSE, NULL, ETH_Timeout); } /** Event handler for Ethernet events */ -static void eth_event_handler( - void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { +static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { uint8_t mac_addr[6] = {0}; /* we can get the ethernet driver handle from event data */ if (event_base == ETH_EVENT) { @@ -179,8 +161,8 @@ static void eth_event_handler( xEventGroupSetBits(ethernet_event_group, LINK_UP_BIT); esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); ESP_LOGI(TAG, ""); - ESP_LOGI(TAG, "Ethernet Link Up, HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], - mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + ESP_LOGI(TAG, "Ethernet Link Up, HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], + mac_addr[5]); network_async_link_up(); break; case ETHERNET_EVENT_DISCONNECTED: diff --git a/components/wifi-manager/network_ethernet.h b/components/wifi-manager/network_ethernet.h index 0858ef07..0aae961e 100644 --- a/components/wifi-manager/network_ethernet.h +++ b/components/wifi-manager/network_ethernet.h @@ -1,10 +1,33 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ #pragma once #include "network_manager.h" #include "accessors.h" #include #include "esp_netif_defaults.h" -#include "Configurator.h" +#include "Config.h" +#include "esp_rom_gpio.h" #ifdef __cplusplus extern "C" { @@ -14,17 +37,17 @@ typedef struct { bool valid; bool rmii; bool spi; - sys_EthModelEnum model; + sys_dev_eth_models model; esp_eth_handle_t handle; esp_netif_config_t * cfg_netif; spi_device_interface_config_t * devcfg; // This function is called when the network interface is started // and performs any initialization that requires a valid ethernet // configuration . - void (*init_config)(sys_Eth * config); - esp_err_t (*start)(spi_device_handle_t spi_handle,sys_Eth * config); + void (*init_config)(sys_dev_eth_config * config); + esp_err_t (*start)(spi_device_handle_t spi_handle,sys_dev_eth_config * config); } network_ethernet_driver_t; -typedef network_ethernet_driver_t* network_ethernet_detect_func_t(sys_Eth * config); +typedef network_ethernet_driver_t* network_ethernet_detect_func_t(sys_dev_eth_config * config); network_ethernet_driver_t* network_ethernet_driver_autodetect(); void destroy_network_ethernet(); void init_network_ethernet(); diff --git a/components/wifi-manager/network_manager.c b/components/wifi-manager/network_manager.c index 313c7662..f1c12a7e 100644 --- a/components/wifi-manager/network_manager.c +++ b/components/wifi-manager/network_manager.c @@ -6,13 +6,13 @@ Copyright (c) 2017-2021 Sebastien L #define LOG_LOCAL_LEVEL NETWORK_MANAGER_LOG_LEVEL #endif #include "network_manager.h" +#include "network_ethernet.h" +#include "network_status.h" +#include "network_wifi.h" #include #include #include #include -#include "network_ethernet.h" -#include "network_status.h" -#include "network_wifi.h" #include "dns_server.h" #include "esp_log.h" @@ -28,7 +28,7 @@ Copyright (c) 2017-2021 Sebastien L #include "esp_app_format.h" #include "esp_event.h" -#include "esp_ota_ops.h" + #include "esp_wifi.h" #include "esp_wifi_types.h" #include "lwip/api.h" @@ -38,16 +38,14 @@ Copyright (c) 2017-2021 Sebastien L #include "mdns.h" #include "messaging.h" -// #include "Configurator.h" -#pragma message("fixme: look for TODO below") #include "tools.h" #include "trace.h" +#include "Config.h" #include "accessors.h" #include "esp_err.h" #include "http_server_handlers.h" #include "network_manager.h" -#include "Configurator.h" QueueHandle_t network_queue; BaseType_t network_task_handle; @@ -55,14 +53,13 @@ static const char TAG[] = "network"; static TaskHandle_t task_network_manager = NULL; RTC_NOINIT_ATTR static bool s_wifi_prioritized; -extern esp_reset_reason_t xReason; typedef struct network_callback { network_status_reached_cb cb; nm_state_t state; int sub_state; const char* from; SLIST_ENTRY(network_callback) - next; //!< next callback + next; //!< next callback } network_callback_t; /** linked list of command structures */ @@ -70,12 +67,11 @@ static SLIST_HEAD(cb_list, network_callback) s_cb_list; network_t NM; - //! Create and initialize the array of state machines. state_machine_t* const SM[] = {(state_machine_t*)&NM}; static void network_timer_cb(void* timer_id); -int get_root_id(const state_t * state); -const state_t* get_root( const state_t* const state); +int get_root_id(const state_t* state); +const state_t* get_root(const state_t* const state); static void network_task(void* pvParameters); void network_start_stop_dhcp_client(esp_netif_t* netif, bool start) { @@ -86,56 +82,52 @@ void network_start_stop_dhcp_client(esp_netif_t* netif, bool start) { ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp. "); return; } - if((err=esp_netif_dhcpc_get_status(netif, &status))!=ESP_OK){ - ESP_LOGE(TAG,"Error retrieving dhcp status : %s", esp_err_to_name(err)); - return; + if ((err = esp_netif_dhcpc_get_status(netif, &status)) != ESP_OK) { + ESP_LOGE(TAG, "Error retrieving dhcp status : %s", esp_err_to_name(err)); + return; } - switch (status) - { - case ESP_NETIF_DHCP_STARTED: - if(start){ + switch (status) { + case ESP_NETIF_DHCP_STARTED: + if (start) { ESP_LOGD(TAG, "DHCP client already started"); - } - else { + } else { ESP_LOGI(TAG, "Stopping DHCP client"); err = esp_netif_dhcpc_stop(netif); - if(err!=ESP_OK){ - ESP_LOGE(TAG,"Error stopping DHCP Client : %s",esp_err_to_name(err)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } break; - case ESP_NETIF_DHCP_STOPPED: - if(start){ - ESP_LOGI(TAG, "Starting DHCP client"); + case ESP_NETIF_DHCP_STOPPED: + if (start) { + ESP_LOGI(TAG, "ESP_NETIF_DHCP_STOPPED Starting DHCP client"); err = esp_netif_dhcpc_start(netif); - if(err!=ESP_OK){ - ESP_LOGE(TAG,"Error stopping DHCP Client : %s",esp_err_to_name(err)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } - } - else { + } else { ESP_LOGI(TAG, "DHCP client already started"); } break; - case ESP_NETIF_DHCP_INIT: - if(start){ - ESP_LOGI(TAG, "Starting DHCP client"); + case ESP_NETIF_DHCP_INIT: + if (start) { + ESP_LOGI(TAG, "ESP_NETIF_DHCP_INIT: Starting DHCP client"); err = esp_netif_dhcpc_start(netif); - if(err!=ESP_OK){ - ESP_LOGE(TAG,"Error stopping DHCP Client : %s",esp_err_to_name(err)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } - } - else { + } else { ESP_LOGI(TAG, "Stopping DHCP client"); err = esp_netif_dhcpc_stop(netif); - if(err!=ESP_OK){ - ESP_LOGE(TAG,"Error stopping DHCP Client : %s",esp_err_to_name(err)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } break; - default: - ESP_LOGW(TAG,"Unknown DHCP status"); - break; + default: + ESP_LOGW(TAG, "Unknown DHCP status"); + break; } } void network_start_stop_dhcps(esp_netif_t* netif, bool start) { @@ -146,99 +138,92 @@ void network_start_stop_dhcps(esp_netif_t* netif, bool start) { ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp server. "); return; } - if((err=esp_netif_dhcps_get_status(netif, &status))!=ESP_OK){ - ESP_LOGE(TAG,"Error retrieving dhcp server status : %s", esp_err_to_name(err)); - return; + if ((err = esp_netif_dhcps_get_status(netif, &status)) != ESP_OK) { + ESP_LOGE(TAG, "Error retrieving dhcp server status : %s", esp_err_to_name(err)); + return; } - switch (status) - { - case ESP_NETIF_DHCP_STARTED: - if(start){ + switch (status) { + case ESP_NETIF_DHCP_STARTED: + if (start) { ESP_LOGD(TAG, "DHCP server already started"); - } - else { + } else { ESP_LOGI(TAG, "Stopping DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif)); } break; - case ESP_NETIF_DHCP_STOPPED: - if(start){ + case ESP_NETIF_DHCP_STOPPED: + if (start) { ESP_LOGI(TAG, "Starting DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif)); - } - else { + } else { ESP_LOGI(TAG, "DHCP server already stopped"); } break; - case ESP_NETIF_DHCP_INIT: - if(start){ + case ESP_NETIF_DHCP_INIT: + if (start) { ESP_LOGI(TAG, "Starting DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif)); - } - else { + } else { ESP_LOGI(TAG, "Stopping DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif)); } break; - default: - ESP_LOGW(TAG,"Unknown DHCP status"); - break; + default: + ESP_LOGW(TAG, "Unknown DHCP status"); + break; } } -/********************************************************************************************* +/********************************************************************************************* * String conversion routines */ - - -#define ADD_ROOT(name,...) CASE_TO_STR(name); -#define ADD_ROOT_LEAF(name,...) CASE_TO_STR(name); -#define ADD_LEAF(name,...) CASE_TO_STR(name); +#define ADD_ROOT(name, ...) CASE_TO_STR(name); +#define ADD_ROOT_LEAF(name, ...) CASE_TO_STR(name); +#define ADD_LEAF(name, ...) CASE_TO_STR(name); #define ADD_EVENT(name) CASE_TO_STR(name); #define ADD_FIRST_EVENT(name) CASE_TO_STR(name); -static const char* state_to_string(const state_t * state) { - if(!state) { +static const char* state_to_string(const state_t* state) { + if (!state) { return ""; } - switch (state->Parent?state->Parent->Id:state->Id) { + switch (state->Parent ? state->Parent->Id : state->Id) { ALL_NM_STATE - default: - break; + default: + break; } return "Unknown"; } static const char* wifi_state_to_string(mn_wifi_active_state_t state) { switch (state) { - ALL_WIFI_STATE(,) - default: - break; + ALL_WIFI_STATE(, ) + default: + break; } return "Unknown"; } static const char* eth_state_to_string(mn_eth_active_state_t state) { switch (state) { - ALL_ETH_STATE(,) - default: - break; + ALL_ETH_STATE(, ) + default: + break; } return "Unknown"; } static const char* wifi_configuring_state_to_string(mn_wifi_configuring_state_t state) { switch (state) { - ALL_WIFI_CONFIGURING_STATE(,) - default: - break; + ALL_WIFI_CONFIGURING_STATE(, ) + default: + break; } return "Unknown"; } -static const char* sub_state_to_string(const state_t * state) { - if(!state) { +static const char* sub_state_to_string(const state_t* state) { + if (!state) { return "N/A"; } int root_id = get_root_id(state); - switch (root_id) - { + switch (root_id) { case NETWORK_ETH_ACTIVE_STATE: return eth_state_to_string(state->Id); break; @@ -252,12 +237,12 @@ static const char* sub_state_to_string(const state_t * state) { return "*"; } -static const char* event_to_string(network_event_t state) { +const char* network_event_to_string(network_event_t state) { switch (state) { ALL_NM_EVENTS - default: - break; + default: + break; } return "Unknown"; } @@ -268,57 +253,60 @@ static const char* event_to_string(network_event_t state) { #undef ADD_ROOT_LEAF #undef ADD_LEAF -typedef struct { - int parent_state; - int sub_state_last ; +typedef struct { + int parent_state; + int sub_state_last; } max_sub_states_t; -static const max_sub_states_t state_max[] = { -{ .parent_state = NETWORK_INSTANTIATED_STATE, .sub_state_last = 0 }, -{.parent_state = NETWORK_ETH_ACTIVE_STATE, .sub_state_last = TOTAL_ETH_ACTIVE_STATE-1 }, -{.parent_state = NETWORK_WIFI_ACTIVE_STATE, .sub_state_last = TOTAL_WIFI_ACTIVE_STATE-1 }, -{.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE-1 }, -{.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE-1 }, -{.parent_state =-1} -}; +static const max_sub_states_t state_max[] = {{.parent_state = NETWORK_INSTANTIATED_STATE, .sub_state_last = 0}, + {.parent_state = NETWORK_ETH_ACTIVE_STATE, .sub_state_last = TOTAL_ETH_ACTIVE_STATE - 1}, + {.parent_state = NETWORK_WIFI_ACTIVE_STATE, .sub_state_last = TOTAL_WIFI_ACTIVE_STATE - 1}, + {.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE - 1}, + {.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE - 1}, {.parent_state = -1}}; - - -void network_start() { - - if(cold_boot){ +void check_queue() { + if (!network_queue) { + ESP_LOGD(TAG, " Creating message queue"); + network_queue = xQueueCreate(6, sizeof(queue_message)); + } +} +void network_initialize_task() { + if (cold_boot) { ESP_LOGI(TAG, "Setting wifi priotitized flag to false"); s_wifi_prioritized = false; } - ESP_LOGD(TAG, " Creating message queue"); - network_queue = xQueueCreate(3, sizeof(queue_message)); - ESP_LOGD(TAG, " Creating network manager task"); - network_task_handle = xTaskCreate(&network_task, "network", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_network_manager); + check_queue(); + ESP_LOGD(TAG, "Creating network manager task"); + network_task_handle = xTaskCreate(&network_task, "network", 4096 * 2, NULL, ESP_TASK_TIMER_PRIO, &task_network_manager); + } static void event_logger(uint32_t state_machine, uint32_t state, uint32_t event) { - ESP_LOGD(TAG, "Handling network manager event state Id %d->[%s]", state, event_to_string(event)); + ESP_LOGD(TAG, "Handling network manager event state Id %d->[%s]", state, network_event_to_string(event)); } -static const char * get_state_machine_result_string(state_machine_result_t result) { - switch(result) { - case EVENT_HANDLED: - return "EVENT_HANDLED"; - case EVENT_UN_HANDLED: - return "EVENT_UN_HANDLED"; - case TRIGGERED_TO_SELF: - return "TRIGGERED_TO_SELF"; +static const char* get_state_machine_result_string(state_machine_result_t result) { + switch (result) { + case EVENT_HANDLED: + return "EVENT_HANDLED"; + case EVENT_UN_HANDLED: + return "EVENT_UN_HANDLED"; + case TRIGGERED_TO_SELF: + return "TRIGGERED_TO_SELF"; } return "Unknown"; } static void result_logger(uint32_t state, state_machine_result_t result) { - ESP_LOGD(TAG, "Network Manager Result: %s, New State id: %d", get_state_machine_result_string(result) , state); + ESP_LOGD(TAG, "Network Manager Result: %s, New State id: %d", get_state_machine_result_string(result), state); } static void network_task(void* pvParameters) { queue_message msg; BaseType_t xStatus; + network_initialize_state_machine_globals(); initialize_network_handlers((state_machine_t*)&NM); - network_async(EN_START); + // make sure that the start event processes before everything + // else, as some critical initialization happen there. + network_async_front(EN_START); /* main processing loop */ for (;;) { xStatus = xQueueReceive(network_queue, &msg, portMAX_DELAY); @@ -328,7 +316,8 @@ static void network_task(void* pvParameters) { NM.event_parameters = &msg; NM.Machine.Event = msg.trigger; if (dispatch_event(SM, 1, event_logger, result_logger) == EVENT_UN_HANDLED) { - network_manager_format_from_to_states(ESP_LOG_ERROR,"Unhandled Event",NULL,NM.Machine.State,msg.trigger,false,"network manager"); + network_manager_format_from_to_states( + ESP_LOG_ERROR, "Unhandled Event", NULL, NM.Machine.State, msg.trigger, false, "network manager"); } } /* end of if status=pdPASS */ } /* end of for loop */ @@ -336,17 +325,15 @@ static void network_task(void* pvParameters) { vTaskDelete(NULL); } - - - int get_max_substate(nm_state_t state){ - for(int i=0;state_max[i].parent_state!=-1;i++){ - if(state_max[i].parent_state == state){ - return state_max[i].sub_state_last; - } - } - return -1; - } -esp_err_t network_register_state_callback(nm_state_t state,int sub_state, const char* from, network_status_reached_cb cb) { +int get_max_substate(nm_state_t state) { + for (int i = 0; state_max[i].parent_state != -1; i++) { + if (state_max[i].parent_state == state) { + return state_max[i].sub_state_last; + } + } + return -1; +} +esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const char* from, network_status_reached_cb cb) { network_callback_t* item = NULL; if (!cb) { return ESP_ERR_INVALID_ARG; @@ -355,7 +342,7 @@ esp_err_t network_register_state_callback(nm_state_t state,int sub_state, const if (item == NULL) { return ESP_ERR_NO_MEM; } - if(sub_state != -1 && sub_state>get_max_substate(state)){ + if (sub_state != -1 && sub_state > get_max_substate(state)) { // sub state has to be valid return ESP_ERR_INVALID_ARG; } @@ -363,7 +350,7 @@ esp_err_t network_register_state_callback(nm_state_t state,int sub_state, const item->state = state; item->cb = cb; item->from = from; - item->sub_state=sub_state; + item->sub_state = sub_state; network_callback_t* last = SLIST_FIRST(&s_cb_list); if (last == NULL) { SLIST_INSERT_HEAD(&s_cb_list, item, next); @@ -376,77 +363,70 @@ esp_err_t network_register_state_callback(nm_state_t state,int sub_state, const } return ESP_OK; } -const state_t* get_root( const state_t* const state){ - if(!state) return NULL; - return state->Parent==NULL?state: get_root(state->Parent); +const state_t* get_root(const state_t* const state) { + if (!state) return NULL; + return state->Parent == NULL ? state : get_root(state->Parent); } -int get_root_id(const state_t * state){ - if(!state) return -1; - return state->Parent==NULL?state->Id: get_root_id(state->Parent); +int get_root_id(const state_t* state) { + if (!state) return -1; + return state->Parent == NULL ? state->Id : get_root_id(state->Parent); } -static bool is_root_state(const state_t * state){ - return state->Parent==NULL; +static bool is_root_state(const state_t* state) { return state->Parent == NULL; } +static bool is_current_state(const state_t* state, nm_state_t state_id, int sub_state_id) { + return get_root(state)->Id == state_id && (sub_state_id == -1 || (!is_root_state(state) && state->Id == sub_state_id)); } -static bool is_current_state(const state_t* state, nm_state_t state_id, int sub_state_id){ - return get_root(state)->Id == state_id && (sub_state_id==-1 || (!is_root_state(state) && state->Id == sub_state_id) ); -} -void network_execute_cb(state_machine_t* const state_machine, const char * caller) { + +void network_execute_cb(state_machine_t* const state_machine, const char* caller) { network_callback_t* it; SLIST_FOREACH(it, &s_cb_list, next) { - if (is_current_state(state_machine->State,it->state, it->sub_state)) { - char * cb_prefix= messaging_alloc_format_string("BEGIN Executing Callback %s", it->from) ; - NETWORK_DEBUG_STATE_MACHINE(true,STR_OR_BLANK(cb_prefix),state_machine,false, STR_OR_BLANK(caller)); + if (is_current_state(state_machine->State, it->state, it->sub_state)) { + char* cb_prefix = messaging_alloc_format_string("BEGIN Executing Callback %s", it->from); + NETWORK_DEBUG_STATE_MACHINE(true, STR_OR_BLANK(cb_prefix), state_machine, false, STR_OR_BLANK(caller)); FREE_AND_NULL(cb_prefix); - it->cb((nm_state_t)get_root(state_machine->State)->Id, is_root_state(state_machine->State)?-1:state_machine->State->Id); - cb_prefix= messaging_alloc_format_string("END Executing Callback %s", it->from) ; - NETWORK_DEBUG_STATE_MACHINE(false,STR_OR_BLANK(cb_prefix),state_machine,false, STR_OR_BLANK(caller)); + it->cb((nm_state_t)get_root(state_machine->State)->Id, is_root_state(state_machine->State) ? -1 : state_machine->State->Id); + cb_prefix = messaging_alloc_format_string("END Executing Callback %s", it->from); + NETWORK_DEBUG_STATE_MACHINE(false, STR_OR_BLANK(cb_prefix), state_machine, false, STR_OR_BLANK(caller)); FREE_AND_NULL(cb_prefix); } } } bool network_is_wifi_prioritized() { - sys_EthCommon * common = NULL; + sys_dev_eth_common* common = NULL; bool result = s_wifi_prioritized; - bool valid_model = SYS_ETH_COMMON(common) && common->model == sys_EthModelEnum_UNSPECIFIED_ETHMODEL; - if(result){ - result = network_wifi_get_known_count()>0 || !valid_model; - ESP_LOGD(TAG,"Wifi is prioritized with %d known access points.%s %s", - network_wifi_get_known_count(), - valid_model?" And a valid ethernet adapter":"",result?"Wifi prioritized":"Ethernet prioritized"); + bool valid_model = SYS_ETH_COMMON(common) && common->model != sys_dev_eth_models_NONE; + if (result) { + result = network_wifi_get_known_count() > 0 || !valid_model; + ESP_LOGD(TAG, "Wifi is prioritized with %d known access points.%s %s", network_wifi_get_known_count(), + valid_model ? " And a valid ethernet adapter" : "", result ? "Wifi prioritized" : "Ethernet prioritized"); } return result; } void network_prioritize_wifi(bool activate) { - if(s_wifi_prioritized == activate) return; + if (s_wifi_prioritized == activate) return; s_wifi_prioritized = activate; - ESP_LOGI(TAG,"Wifi is %s prioritized",activate?"":"not"); + ESP_LOGI(TAG, "Wifi is %sprioritized", activate ? "" : "not "); } - -void network_manager_format_state_machine(esp_log_level_t level, const char* prefix, state_machine_t* state_machine, bool show_source, const char * caller) { +void network_manager_format_state_machine( + esp_log_level_t level, const char* prefix, state_machine_t* state_machine, bool show_source, const char* caller) { state_t const* source_state = NULL; state_t const* current_state = NULL; network_event_t event = -1; - MEMTRACE_PRINT_DELTA(); + if (state_machine) { - source_state = ((network_t *)state_machine)->source_state; + source_state = ((network_t*)state_machine)->source_state; current_state = state_machine->State; event = state_machine->Event; - network_manager_format_from_to_states(level, prefix, source_state, current_state, event, show_source,caller); + network_manager_format_from_to_states(level, prefix, source_state, current_state, event, show_source, caller); + } else { + ESP_LOG_LEVEL(level, TAG, "%s - %s -> [%s]", STR_OR_BLANK(caller), prefix, network_event_to_string(event)); } - else { - ESP_LOG_LEVEL(level, TAG, "%s - %s -> [%s]", - STR_OR_BLANK(caller), - prefix, - event_to_string(event)); - } - - } -void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, const state_t * from_state,const state_t * current_state, network_event_t event,bool show_source, const char * caller) { +void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, const state_t* from_state, const state_t* current_state, + network_event_t event, bool show_source, const char* caller) { const char* source_state = ""; const char* source_sub_state = ""; const char* state = "N/A"; @@ -463,132 +443,154 @@ void network_manager_format_from_to_states(esp_log_level_t level, const char* pr source_sub_state = sub_state_to_string(from_state); } if (show_source) { - ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s)->%s(%s) [%s]", - STR_OR_BLANK(caller), - prefix, - source_state, - source_sub_state, - state, - sub_state, - event_to_string(event)); + ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s)->%s(%s) [%s]", STR_OR_BLANK(caller), prefix, source_state, source_sub_state, state, sub_state, + network_event_to_string(event)); } else { - ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s) [%s]", - STR_OR_BLANK(caller), - prefix, - state, - sub_state, - event_to_string(event)); + ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s) [%s]", STR_OR_BLANK(caller), prefix, state, sub_state, network_event_to_string(event)); } } +#define xSafeQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait) \ + check_queue(); \ + xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait); +#define xSafeQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait) \ + check_queue(); \ + xQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait); void network_async(network_event_t trigger) { queue_message msg; - memset(&msg,0x00,sizeof(msg)); + memset(&msg, 0x00, sizeof(msg)); msg.trigger = trigger; - ESP_LOGD(TAG, "Posting event %s directly", event_to_string(trigger)); - xQueueSendToBack(network_queue, &msg, portMAX_DELAY); + ESP_LOGD(TAG, "Posting event %s directly", network_event_to_string(trigger)); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } -void network_async_fail() { - network_async(EN_FAIL); -} -void network_async_success() { - network_async(EN_SUCCESS); -} -void network_async_connected(){ - network_async(EN_CONNECTED); -} -void network_async_link_up() { - network_async(EN_LINK_UP); -} -void network_async_link_down() { - network_async(EN_LINK_DOWN); -} -void network_async_configure() { - network_async(EN_CONFIGURE); -} -void network_async_got_ip() { - network_async(EN_GOT_IP); -} -void network_async_eth_got_ip() { - network_async(EN_ETH_GOT_IP); -} -void network_async_timer() { - network_async(EN_TIMER); -} -void network_async_start() { - network_async(EN_START); -} -void network_async_scan() { - network_async(EN_SCAN); -} - -void network_async_update_status() { - network_async(EN_UPDATE_STATUS); -} - -void network_async_delete() { - network_async(EN_DELETE); -} - -void network_async_scan_done() { - network_async(EN_SCAN_DONE); -} -void network_async_connect(const char * ssid, const char * password) { +void network_async_got_ip(network_event_t trigger,ip_event_got_ip_t*event_data) { queue_message msg; - memset(&msg,0x00,sizeof(msg)); + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = trigger; + msg.ctx.got_ip_event_data = (ip_event_got_ip_t*)clone_obj_psram(event_data,sizeof(ip_event_got_ip_t)); + ESP_LOGD(TAG, "Posting event %s", network_event_to_string(trigger)); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} +void network_async_front(network_event_t trigger) { + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = trigger; + ESP_LOGD(TAG, "Posting event %s directly to front of the queue", network_event_to_string(trigger)); + xSafeQueueSendToFront(network_queue, &msg, portMAX_DELAY); +} + +void network_async_commit_protowrapper(void* protoWrapperBase) { + queue_message msg; + memset(&msg, 0, sizeof(msg)); + msg.trigger = EN_COMMIT_CHANGES; + msg.ctx.strval = (char*)protoWrapperBase; // Cast to void pointer + ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} + +void network_async_fail() { network_async(EN_FAIL); } +void network_async_success() { network_async(EN_SUCCESS); } +void network_async_connected() { network_async(EN_CONNECTED); } +void network_async_link_up() { network_async(EN_LINK_UP); } +void network_async_link_down() { network_async(EN_LINK_DOWN); } +void network_async_configure() { network_async(EN_CONFIGURE); } +void network_async_eth_got_ip() { network_async(EN_ETH_GOT_IP); } +void network_async_timer() { network_async(EN_TIMER); } +void network_async_scan() { network_async(EN_SCAN); } + +void network_async_update_status() { network_async(EN_UPDATE_STATUS); } + +void network_async_delete() { network_async(EN_DELETE); } + +void network_async_scan_done() { network_async(EN_SCAN_DONE); } +void network_async_delete_connection(const char * ssid){ + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = EN_REMOVE; + msg.ctx.credentials.ssid = strdup_psram(ssid); + ESP_LOGD(TAG, "Posting event %s for ssid %s", network_event_to_string(msg.trigger),ssid); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} +void network_async_connect(const char* ssid, const char* password) { + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); msg.trigger = EN_CONNECT_NEW; - msg.ssid = strdup_psram(ssid); - if(password && strlen(password) >0){ - msg.password = strdup_psram(password); + msg.ctx.credentials.ssid = strdup_psram(ssid); + if (password && strlen(password) > 0) { + msg.ctx.credentials.password = strdup_psram(password); } - ESP_LOGD(TAG, "Posting event %s", event_to_string(msg.trigger)); - xQueueSendToBack(network_queue, &msg, portMAX_DELAY); + ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} +void network_async_add(const char* ssid, const char* password) { + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = EN_ADD; + msg.ctx.credentials.ssid = strdup_psram(ssid); + msg.ctx.credentials.password = strdup_psram(STR_OR_BLANK(password)); + ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } void network_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event) { queue_message msg; - memset(&msg,0x00,sizeof(msg)); + memset(&msg, 0x00, sizeof(msg)); msg.trigger = EN_LOST_CONNECTION; - ESP_LOGD(TAG, "Posting event %s", event_to_string(msg.trigger)); - msg.disconnected_event = clone_obj_psram(disconnected_event,sizeof(wifi_event_sta_disconnected_t)); - if(msg.disconnected_event){ - xQueueSendToBack(network_queue, &msg, portMAX_DELAY); - } - else { - ESP_LOGE(TAG,"Unable to post lost connection event."); + ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); + msg.ctx.disconnected_event = clone_obj_psram(disconnected_event, sizeof(wifi_event_sta_disconnected_t)); + if (msg.ctx.disconnected_event) { + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); + } else { + ESP_LOGE(TAG, "Unable to post lost connection event."); } } void network_async_reboot(reboot_type_t rtype) { queue_message msg; - memset(&msg,0x00,sizeof(msg)); + memset(&msg, 0x00, sizeof(msg)); msg.trigger = EN_REBOOT; - msg.rtype = rtype; - ESP_LOGD(TAG, "Posting event %s - type %d", event_to_string(msg.trigger),rtype); - xQueueSendToBack(network_queue, &msg, portMAX_DELAY); + msg.ctx.rtype = rtype; + ESP_LOGD(TAG, "Posting event %s - type %d", network_event_to_string(msg.trigger), rtype); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} +void network_async_callback_withret(void* ctx, network_manager_ret_cb_t cb) { + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = EN_EXECUTE_CALLBACK; + msg.ctx.cb_ctx.ret_cb = cb; + msg.ctx.cb_ctx.cb = NULL; + msg.ctx.cb_ctx.ctx = ctx; + ESP_LOGD(TAG, "Posting event %s %s", network_event_to_string(msg.trigger), "with return"); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); +} +void network_async_callback(void* ctx, network_manager_cb_t cb) { + queue_message msg; + memset(&msg, 0x00, sizeof(msg)); + msg.trigger = EN_EXECUTE_CALLBACK; + msg.ctx.cb_ctx.cb = cb; + msg.ctx.cb_ctx.ret_cb = NULL; + msg.ctx.cb_ctx.ctx = ctx; + ESP_LOGD(TAG, "Posting event %s %s", network_event_to_string(msg.trigger), "without return"); + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } void network_reboot_ota(char* url) { queue_message msg; - memset(&msg,0x00,sizeof(msg)); + memset(&msg, 0x00, sizeof(msg)); if (url == NULL) { msg.trigger = EN_REBOOT; - msg.rtype = OTA; - ESP_LOGD(TAG, "Posting event %s - type %d", event_to_string(msg.trigger),msg.rtype); + msg.ctx.rtype = OTA; + ESP_LOGD(TAG, "Posting event %s - type %d", network_event_to_string(msg.trigger), msg.ctx.rtype); } else { msg.trigger = EN_REBOOT_URL; - ESP_LOGD(TAG, "Posting event %s - type reboot URL", event_to_string(msg.trigger)); - msg.strval = strdup_psram(url); + ESP_LOGD(TAG, "Posting event %s - type reboot URL", network_event_to_string(msg.trigger)); + msg.ctx.strval = strdup_psram(url); } - - xQueueSendToBack(network_queue, &msg, portMAX_DELAY); + + xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } -network_t* network_get_state_machine() { - return &NM; -} +network_t* network_get_state_machine() { return &NM; } -static void network_timer_cb(void* timer_id) { - network_async_timer(); -} +static void network_timer_cb(void* timer_id) { network_async_timer(); } esp_netif_t* network_get_active_interface() { if (NM.wifi_ap_netif && (network_wifi_is_ap_mode() || network_wifi_is_ap_sta_mode())) { return NM.wifi_ap_netif; @@ -600,12 +602,12 @@ esp_netif_t* network_get_active_interface() { bool network_is_interface_connected(esp_netif_t* interface) { esp_err_t err = ESP_OK; tcpip_adapter_ip_info_t ipInfo; - if(!interface){ + if (!interface) { return false; } err = network_get_ip_info_for_netif(interface, &ipInfo); - if(err != ESP_OK){ - ESP_LOGD(TAG,"network_get_ip_info_for_netif returned %s", esp_err_to_name(err)); + if (err != ESP_OK) { + ESP_LOGD(TAG, "network_get_ip_info_for_netif returned %s", esp_err_to_name(err)); } return ((err == ESP_OK) && (ipInfo.ip.addr != IPADDR_ANY)); } @@ -613,33 +615,34 @@ static esp_netif_t* get_connected_interface() { esp_netif_t* interface = NULL; for (int i = 0; i < 4; i++) { switch (i) { - case 0: - // try the active interface - interface = network_get_active_interface(); - break; - case 1: - interface = NM.wifi_ap_netif; - break; - case 2: - interface = NM.wifi_netif; - break; - case 3: - interface = NM.eth_netif; - break; - default: - break; + case 0: + // try the active interface + interface = network_get_active_interface(); + break; + case 1: + interface = NM.wifi_ap_netif; + break; + case 2: + interface = NM.wifi_netif; + break; + case 3: + interface = NM.eth_netif; + break; + default: + break; } if (interface && network_is_interface_connected(interface)) { - ESP_LOGD(TAG,"Found connected interface in iteration #%d",i); + ESP_LOGD(TAG, "Found connected interface in iteration #%d", i); return interface; } } - ESP_LOGD(TAG,"No connected interface found"); + ESP_LOGD(TAG, "No connected interface found"); return NULL; } esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo) { esp_netif_ip_info_t loc_ip_info; - if (!ipInfo ) { + ESP_LOGD(TAG,"%s Getting IP info","network_get_ip_info_for_netif"); + if (!ipInfo) { ESP_LOGE(TAG, "Invalid pointer for ipInfo"); return ESP_ERR_INVALID_ARG; } @@ -647,101 +650,82 @@ esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_inf ESP_LOGE(TAG, "Invalid pointer for netif"); return ESP_ERR_INVALID_ARG; } - memset(ipInfo,0x00,sizeof(tcpip_adapter_ip_info_t)); - esp_err_t err= esp_netif_get_ip_info(netif, &loc_ip_info); - if(err==ESP_OK){ - ip4_addr_set(&(ipInfo->ip),&loc_ip_info.ip); - ip4_addr_set(&(ipInfo->gw),&loc_ip_info.gw); - ip4_addr_set(&(ipInfo->netmask),&loc_ip_info.netmask); + ESP_LOGD(TAG,"%s Pointers were valid","network_get_ip_info_for_netif"); + memset(ipInfo, 0x00, sizeof(tcpip_adapter_ip_info_t)); + esp_err_t err = esp_netif_get_ip_info(netif, &loc_ip_info); + if (err == ESP_OK) { + ESP_LOGD(TAG,"%s Setting ip4 address","network_get_ip_info_for_netif"); + ip4_addr_set(&(ipInfo->ip), &loc_ip_info.ip); + ip4_addr_set(&(ipInfo->gw), &loc_ip_info.gw); + ip4_addr_set(&(ipInfo->netmask), &loc_ip_info.netmask); } return err; } esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo) { - esp_netif_t* netif= get_connected_interface(); - if(netif){ - return network_get_ip_info_for_netif(netif,ipInfo); + esp_netif_t* netif = get_connected_interface(); + if (netif) { + return network_get_ip_info_for_netif(netif, ipInfo); } return ESP_FAIL; } -esp_err_t network_get_hostname(const char** hostname) { - return esp_netif_get_hostname(get_connected_interface(), hostname); -} +esp_err_t network_get_hostname(const char** hostname) { return esp_netif_get_hostname(get_connected_interface(), hostname); } -void network_set_timer(uint16_t duration, const char * tag) { +void network_set_timer(uint16_t duration, const char* tag) { if (duration > 0) { - if(tag){ + if (tag) { ESP_LOGD(TAG, "Setting timer tag to %s", tag); NM.timer_tag = strdup_psram(tag); } if (!NM.state_timer) { - ESP_LOGD(TAG, "Starting %s timer with period of %u ms.", STR_OR_ALT(NM.timer_tag,"anonymous"), duration); + ESP_LOGD(TAG, "Starting %s timer with period of %u ms.", STR_OR_ALT(NM.timer_tag, "anonymous"), duration); NM.state_timer = xTimerCreate("background STA", pdMS_TO_TICKS(duration), pdFALSE, NULL, network_timer_cb); } else { - ESP_LOGD(TAG, "Changing %s timer period to %u ms.", STR_OR_ALT(NM.timer_tag,"anonymous"),duration); + ESP_LOGD(TAG, "Changing %s timer period to %u ms.", STR_OR_ALT(NM.timer_tag, "anonymous"), duration); xTimerChangePeriod(NM.state_timer, pdMS_TO_TICKS(duration), portMAX_DELAY); } xTimerStart(NM.state_timer, portMAX_DELAY); } else if (NM.state_timer) { - ESP_LOGD(TAG,"Stopping timer %s",STR_OR_ALT(NM.timer_tag,"anonymous")); + ESP_LOGD(TAG, "Stopping timer %s", STR_OR_ALT(NM.timer_tag, "anonymous")); xTimerStop(NM.state_timer, portMAX_DELAY); FREE_AND_NULL(NM.timer_tag); } - } void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { ip_event_got_ip_t* s = NULL; - esp_netif_ip_info_t* ip_info = NULL; - - if (event_base != IP_EVENT) - return; + if (event_base != IP_EVENT) return; switch (event_id) { - case IP_EVENT_ETH_GOT_IP: - case IP_EVENT_STA_GOT_IP: - s = (ip_event_got_ip_t*)event_data; - ip_info = &s->ip_info; - ESP_LOGI(TAG, "Got an IP address from interface %s. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s", - event_id == IP_EVENT_ETH_GOT_IP ? "Eth" : event_id == IP_EVENT_STA_GOT_IP ? "Wifi" - : "Unknown", - IP2STR(&ip_info->ip), - IP2STR(&ip_info->gw), - IP2STR(&ip_info->netmask), - s->ip_changed ? "Address was changed" : "Address unchanged"); - network_async(event_id == IP_EVENT_ETH_GOT_IP ? EN_ETH_GOT_IP : EN_GOT_IP); - break; - case IP_EVENT_STA_LOST_IP: - ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP"); - break; - case IP_EVENT_AP_STAIPASSIGNED: - ESP_LOGD(TAG, "IP_EVENT_AP_STAIPASSIGNED"); - break; - case IP_EVENT_GOT_IP6: - ESP_LOGD(TAG, "IP_EVENT_GOT_IP6"); - break; - default: - break; + case IP_EVENT_ETH_GOT_IP: + case IP_EVENT_STA_GOT_IP: + s = (ip_event_got_ip_t*)event_data; + network_async_got_ip(event_id== IP_EVENT_ETH_GOT_IP ? EN_ETH_GOT_IP : EN_GOT_IP,s); + break; + case IP_EVENT_STA_LOST_IP: + ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP"); + break; + case IP_EVENT_AP_STAIPASSIGNED: + ESP_LOGD(TAG, "IP_EVENT_AP_STAIPASSIGNED"); + break; + case IP_EVENT_GOT_IP6: + ESP_LOGD(TAG, "IP_EVENT_GOT_IP6"); + break; + default: + break; } } void network_set_hostname(esp_netif_t* interface) { esp_err_t err; - ESP_LOGD(TAG, "Retrieving host name from nvs"); - if (!platform->has_names || strlen(platform->names.device) == 0 ) { - ESP_LOGE(TAG, "Could not retrieve host name from nvs"); - } else { - ESP_LOGD(TAG, "Setting host name to : %s", platform->names.device); - if ((err = esp_netif_set_hostname(interface, platform->names.device)) != ESP_OK) { - ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err)); - } + ESP_LOGD(TAG, "network_set_hostname. Retrieving host name from config structure"); + char* temp = NULL; + + if (!platform || !platform->has_names || strlen(platform->names.device) == 0) { + temp = alloc_get_fallback_unique_name(); + ESP_LOGE(TAG, "Device name not set. Falling back to %s", temp); } -} -#define LOCAL_MAC_SIZE 20 -char* network_manager_alloc_get_mac_string(uint8_t mac[6]) { - char* macStr = malloc_init_external(LOCAL_MAC_SIZE); - if(macStr){ - snprintf(macStr, LOCAL_MAC_SIZE, MACSTR, MAC2STR(mac)); + ESP_LOGD(TAG, "Setting host name to : %s", temp ? temp : platform->names.device); + if ((err = esp_netif_set_hostname(interface, temp ? temp : platform->names.device)) != ESP_OK) { + ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err)); } - return macStr; + if (temp) free(temp); } - - diff --git a/components/wifi-manager/network_manager.h b/components/wifi-manager/network_manager.h index 1edfa132..cd23b0cb 100644 --- a/components/wifi-manager/network_manager.h +++ b/components/wifi-manager/network_manager.h @@ -1,3 +1,26 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + #pragma once #include "esp_system.h" @@ -22,6 +45,7 @@ extern "C" { ADD_EVENT(EN_GOT_IP)\ ADD_EVENT(EN_ETH_GOT_IP)\ ADD_EVENT(EN_DELETE)\ + ADD_EVENT(EN_REMOVE)\ ADD_EVENT(EN_TIMER)\ ADD_EVENT(EN_START)\ ADD_EVENT(EN_SCAN)\ @@ -30,12 +54,15 @@ extern "C" { ADD_EVENT(EN_SCAN_DONE)\ ADD_EVENT(EN_CONNECT)\ ADD_EVENT(EN_CONNECT_NEW)\ + ADD_EVENT(EN_ADD)\ ADD_EVENT(EN_REBOOT)\ ADD_EVENT(EN_REBOOT_URL)\ ADD_EVENT(EN_LOST_CONNECTION)\ ADD_EVENT(EN_ETHERNET_FALLBACK)\ ADD_EVENT(EN_UPDATE_STATUS)\ - ADD_EVENT(EN_CONNECTED) + ADD_EVENT(EN_CONNECTED)\ + ADD_EVENT(EN_COMMIT_CHANGES)\ + ADD_EVENT(EN_EXECUTE_CALLBACK) #define ADD_EVENT(name) name, #define ADD_FIRST_EVENT(name) name=1, typedef enum { @@ -50,14 +77,33 @@ typedef enum { RESTART, } reboot_type_t; +typedef void (*network_manager_cb_t)(void * ctx); +typedef esp_err_t (*network_manager_ret_cb_t)(void * ctx); + +typedef struct { + void * ctx; + network_manager_cb_t cb; + network_manager_ret_cb_t ret_cb; +} callback_ctx_t; typedef struct { - network_event_t trigger; char * ssid; char * password; - reboot_type_t rtype; - char* strval; - wifi_event_sta_disconnected_t* disconnected_event; +} network_credentials_t; +typedef struct { + network_event_t trigger; + + union + { + reboot_type_t rtype; + char* strval; + wifi_event_sta_disconnected_t* disconnected_event; + callback_ctx_t cb_ctx; + network_credentials_t credentials; + ip_event_got_ip_t* got_ip_event_data; + } ctx; + esp_netif_t *netif; + } queue_message; typedef struct @@ -71,6 +117,7 @@ typedef struct int64_t last_connected; uint16_t num_disconnect; uint16_t retries; + uint16_t initial_retries; bool wifi_connected; esp_netif_t *wifi_netif; esp_netif_t *eth_netif; @@ -90,23 +137,28 @@ typedef struct * --------------------- External function prototype --------------------- */ -void network_start(); +void network_initialize_task(); + + network_t * network_get_state_machine(); void network_event_simple(network_event_t trigger); void network_event(network_event_t trigger, void* param); void network_async_event(network_event_t trigger, void* param); void network_async(network_event_t trigger); +void network_async_front(network_event_t trigger); void network_async_fail(); void network_async_success(); void network_async_link_up(); void network_async_link_down(); void network_async_configure(); -void network_async_got_ip(); +void network_async_got_ip(network_event_t trigger,ip_event_got_ip_t*event_data); void network_async_timer(); -void network_async_start(); +void network_async_add(const char* ssid, const char* password); +void network_async_commit_protowrapper(void* protoWrapperBase); void network_async_scan(); void network_async_scan_done(); void network_async_connect(const char * ssid, const char * password); +void network_async_delete_connection(const char * ssid); void network_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event); void network_async_reboot(reboot_type_t rtype); void network_reboot_ota(char* url); @@ -115,58 +167,11 @@ void network_async_update_status(); void network_async_eth_got_ip(); void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); bool network_is_interface_connected(esp_netif_t * interface); - - - - - - -/* - * --------------------- Inline functions --------------------- - */ - - - - - - -/** - * @brief Defines the maximum size of a SSID name. 32 is IEEE standard. - * @warning limit is also hard coded in wifi_config_t. Never extend this value. - */ -#define MAX_SSID_SIZE 32 - -/** - * @brief Defines the maximum size of a WPA2 passkey. 64 is IEEE standard. - * @warning limit is also hard coded in wifi_config_t. Never extend this value. - */ -#define MAX_PASSWORD_SIZE 64 -#define MAX_COMMAND_LINE_SIZE 201 - -/** - * @brief Defines the maximum number of access points that can be scanned. - * - * To save memory and avoid nasty out of memory errors, - * we can limit the number of APs detected in a wifi scan. - */ -#define MAX_AP_NUM 15 - - - -/** - * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up. - * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries) - */ -#define WIFI_MANAGER_MAX_RETRY CONFIG_WIFI_MANAGER_MAX_RETRY - -/** @brief Defines the task priority of the wifi_manager. - * - * Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. - * For this particular reason, minimum task priority is 1. It it highly not recommended to set - * it to 1 though as the sub-tasks will now have a priority of 0 which is the priority - * of freeRTOS' idle task. - */ -#define WIFI_MANAGER_TASK_PRIORITY CONFIG_WIFI_MANAGER_TASK_PRIORITY +void network_check_recovery_running(); +void network_async_callback(void * ctx, network_manager_cb_t cb); +void network_async_callback_withret(void * ctx, network_manager_ret_cb_t cb); +const char* network_event_to_string(network_event_t state); +void network_initialize_state_machine_globals(); /** @brief Defines the auth mode as an access point * Value must be of type wifi_auth_mode_t @@ -181,11 +186,6 @@ bool network_is_interface_connected(esp_netif_t * interface); /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */ #define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID -/** @brief Defines access point's password. - * @warning In the case of an open access point, the password must be a null string "" or "\0" if you want to be verbose but waste one byte. - * In addition, the AP_AUTHMODE must be WIFI_AUTH_OPEN - */ -#define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD /** @brief Defines access point's bandwidth. @@ -195,45 +195,14 @@ bool network_is_interface_connected(esp_netif_t * interface); */ #define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20 -/** @brief Defines access point's channel. - * Channel selection is only effective when not connected to another AP. - * Good practice for minimal channel interference to use - * For 20 MHz: 1, 6 or 11 in USA and 1, 5, 9 or 13 in most parts of the world - * For 40 MHz: 3 in USA and 3 or 11 in most parts of the world - */ + #define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL - -/** @brief Defines the access point's default IP address. Default: "10.10.0.1 */ -#define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP - -/** @brief Defines the access point's gateway. This should be the same as your IP. Default: "10.10.0.1" */ #define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY -/** @brief Defines the access point's netmask. Default: "255.255.255.0" */ #define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK -/** @brief Defines access point's maximum number of clients. Default: 4 */ -#define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS - -/** @brief Defines access point's beacon interval. 100ms is the recommended default. */ -#define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL - -/** @brief Defines if esp32 shall run both AP + STA when connected to another AP. - * Value: 0 will have the own AP always on (APSTA mode) - * Value: 1 will turn off own AP when connected to another AP (STA only mode when connected) - * Turning off own AP when connected to another AP minimize channel interference and increase throughput - */ -#define DEFAULT_STA_ONLY 1 - -/** @brief Defines if wifi power save shall be enabled. - * Value: WIFI_PS_NONE for full power (wifi modem always on) - * Value: WIFI_PS_MODEM for power save (wifi modem sleep periodically) - * Note: Power save is only effective when in STA only mode - */ -#define DEFAULT_STA_POWER_SAVE WIFI_PS_MIN_MODEM - void network_reboot_ota(char * url); @@ -303,7 +272,6 @@ void network_prioritize_wifi(bool activate); void initialize_network_handlers(state_machine_t* state_machine); void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, state_t const * from_state, state_t const* current_state, network_event_t event,bool show_source, const char * caller ); void network_manager_format_state_machine(esp_log_level_t level, const char* prefix, state_machine_t * state_machine, bool show_source, const char * caller) ; -char* network_manager_alloc_get_mac_string(uint8_t mac[6]); #if defined(LOG_LOCAL_LEVEL) #if LOG_LOCAL_LEVEL >=5 @@ -319,7 +287,8 @@ char* network_manager_alloc_get_mac_string(uint8_t mac[6]); #define network_exit_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"BEGIN EXIT":"END EXIT",State_Machine,false,"") #define network_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,"") -#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) if(begin) network_manager_format_from_to_states(ESP_LOG_DEBUG, prefix, source,target, event, print_source,caller )#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__); +#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) if(begin) network_manager_format_from_to_states(ESP_LOG_DEBUG, prefix, source,target, event, print_source,caller ) +#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__); #define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,cb_prefix,state_machine,print_from,caller) #endif #endif diff --git a/components/wifi-manager/network_manager_handlers.c b/components/wifi-manager/network_manager_handlers.c index c7fe3819..a8f3a993 100644 --- a/components/wifi-manager/network_manager_handlers.c +++ b/components/wifi-manager/network_manager_handlers.c @@ -1,14 +1,14 @@ #ifdef NETWORK_HANDLERS_LOG_LEVEL #define LOG_LOCAL_LEVEL NETWORK_HANDLERS_LOG_LEVEL #endif +#include "network_ethernet.h" #include "network_manager.h" +#include "network_status.h" +#include "network_wifi.h" #include #include #include #include -#include "network_ethernet.h" -#include "network_status.h" -#include "network_wifi.h" #include "dns_server.h" #include "esp_log.h" @@ -34,35 +34,33 @@ #include "mdns.h" #include "messaging.h" -// #include "Configurator.h" -#pragma message("fixme: look for TODO below") +#include "Config.h" + #include "trace.h" #include "accessors.h" +#include "bootstate.h" #include "esp_err.h" -#include "tools.h" #include "http_server_handlers.h" #include "network_manager.h" +#include "tools.h" -static const char TAG[]="network_handlers"; +static const char TAG[] = "network_handlers"; EXT_RAM_ATTR static state_t network_states[TOTAL_NM_STATE]; EXT_RAM_ATTR static state_t Wifi_Active_State[TOTAL_WIFI_ACTIVE_STATE]; EXT_RAM_ATTR static state_t Eth_Active_State[TOTAL_ETH_ACTIVE_STATE]; EXT_RAM_ATTR static state_t Wifi_Configuring_State[TOTAL_WIFI_CONFIGURING_STATE]; - static void network_interface_coexistence(state_machine_t* state_machine); -static state_machine_result_t local_traverse_state(state_machine_t* const state_machine, - const state_t* const target_state, const char * caller) ; -static state_machine_result_t local_switch_state(state_machine_t* state_machine, - const state_t* const target_state, const char * caller); -void network_execute_cb(state_machine_t* const state_machine, const char * caller); -int get_root_id(const state_t * state); -const state_t* get_root( const state_t* const state); +static state_machine_result_t local_traverse_state(state_machine_t* const state_machine, const state_t* const target_state, const char* caller); +static state_machine_result_t local_switch_state(state_machine_t* state_machine, const state_t* const target_state, const char* caller); +void network_execute_cb(state_machine_t* const state_machine, const char* caller); +int get_root_id(const state_t* state); +const state_t* get_root(const state_t* const state); -#define ADD_ROOT(name,...) ADD_ROOT_FORWARD_DECLARATION(name,...) -#define ADD_ROOT_LEAF(name,...) ADD_ROOT_LEAF_FORWARD_DECLARATION(name,...) -#define ADD_LEAF(name,...) ADD_LEAF_FORWARD_DECLARATION(name,...) +#define ADD_ROOT(name, ...) ADD_ROOT_FORWARD_DECLARATION(name, ...) +#define ADD_ROOT_LEAF(name, ...) ADD_ROOT_LEAF_FORWARD_DECLARATION(name, ...) +#define ADD_LEAF(name, ...) ADD_LEAF_FORWARD_DECLARATION(name, ...) ALL_NM_STATE ALL_ETH_STATE(, ) ALL_WIFI_STATE(, ) @@ -78,242 +76,301 @@ ALL_WIFI_CONFIGURING_STATE(, ) #define ADD_LEAF(NAME, PARENT, LEVEL) ADD_LEAF_(NAME, PARENT, LEVEL) #define ADD_ROOT_LEAF(NAME) ADD_ROOT_LEAF_(NAME) -#define ADD_ROOT_(NAME, CHILD) \ - [NAME] = { \ - .Handler = NAME##_handler, \ - .Entry = NAME##_entry_handler, \ - .Exit = NAME##_exit_handler, \ - .Level = 0, \ - .Parent = NULL, \ - .Id = NAME, \ - .Node = CHILD, \ +#define ADD_ROOT_(NAME, CHILD) \ + [NAME] = { \ + .Handler = NAME##_handler, \ + .Entry = NAME##_entry_handler, \ + .Exit = NAME##_exit_handler, \ + .Level = 0, \ + .Parent = NULL, \ + .Id = NAME, \ + .Node = CHILD, \ }, -#define ADD_ROOT_LEAF_(NAME) \ - [NAME] = { \ - .Handler = NAME##_handler, \ - .Entry = NAME##_entry_handler, \ - .Exit = NAME##_exit_handler, \ - .Id = NAME, \ - .Parent = NULL, \ +#define ADD_ROOT_LEAF_(NAME) \ + [NAME] = { \ + .Handler = NAME##_handler, \ + .Entry = NAME##_entry_handler, \ + .Exit = NAME##_exit_handler, \ + .Id = NAME, \ + .Parent = NULL, \ }, -#define ADD_LEAF_(NAME, PARENT, LEVEL) \ - [NAME] = { \ - .Handler = NAME##_handler, \ - .Entry = NAME##_entry_handler, \ - .Exit = NAME##_exit_handler, \ - .Id = NAME, \ - .Level = LEVEL, \ - .Parent = PARENT, \ +#define ADD_LEAF_(NAME, PARENT, LEVEL) \ + [NAME] = { \ + .Handler = NAME##_handler, \ + .Entry = NAME##_entry_handler, \ + .Exit = NAME##_exit_handler, \ + .Id = NAME, \ + .Level = LEVEL, \ + .Parent = PARENT, \ }, -static void network_initialize_state_machine_globals(){ - static state_t loc_network_states[] = - { - ALL_NM_STATE}; +void network_initialize_state_machine_globals() { + static state_t loc_network_states[] = {ALL_NM_STATE}; - static state_t loc_Wifi_Active_State[] = { - ALL_WIFI_STATE(&network_states[NETWORK_WIFI_ACTIVE_STATE], 1) - }; - static state_t loc_Eth_Active_State[]={ - ALL_ETH_STATE(&network_states[NETWORK_ETH_ACTIVE_STATE], 1) + static state_t loc_Wifi_Active_State[] = {ALL_WIFI_STATE(&network_states[NETWORK_WIFI_ACTIVE_STATE], 1)}; + static state_t loc_Eth_Active_State[] = {ALL_ETH_STATE(&network_states[NETWORK_ETH_ACTIVE_STATE], 1) }; - static state_t loc_Wifi_Configuring_State[]={ - ALL_WIFI_CONFIGURING_STATE(&network_states[NETWORK_WIFI_CONFIGURING_ACTIVE_STATE], 1) - }; - memcpy(&network_states,&loc_network_states,sizeof(network_states)); - memcpy(&Eth_Active_State,&loc_Eth_Active_State,sizeof(Eth_Active_State)); - memcpy(&Wifi_Active_State,&loc_Wifi_Active_State,sizeof(Wifi_Active_State)); - memcpy(&Wifi_Configuring_State,&loc_Wifi_Configuring_State,sizeof(Wifi_Configuring_State)); + static state_t loc_Wifi_Configuring_State[] = {ALL_WIFI_CONFIGURING_STATE(&network_states[NETWORK_WIFI_CONFIGURING_ACTIVE_STATE], 1)}; + memcpy(&network_states, &loc_network_states, sizeof(network_states)); + memcpy(&Eth_Active_State, &loc_Eth_Active_State, sizeof(Eth_Active_State)); + memcpy(&Wifi_Active_State, &loc_Wifi_Active_State, sizeof(Wifi_Active_State)); + memcpy(&Wifi_Configuring_State, &loc_Wifi_Configuring_State, sizeof(Wifi_Configuring_State)); } #undef ADD_ROOT #undef ADD_ROOT_LEAF #undef ADD_LEAF - -#define HANDLE_GLOBAL_EVENT(m) \ - if (handle_global_event(m) == EVENT_HANDLED) \ - return EVENT_HANDLED; +static void network_handle_got_ip(network_event_t trigger, ip_event_got_ip_t* event_data) { + esp_netif_ip_info_t* ip_info = NULL; + ip_info = &event_data->ip_info; + ESP_LOGI(TAG, "Got an IP address from interface %s. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s", + trigger == EN_ETH_GOT_IP ? "Eth" : "Wifi", IP2STR(&ip_info->ip), IP2STR(&ip_info->gw), IP2STR(&ip_info->netmask), + event_data->ip_changed ? "Address was changed" : "Address unchanged"); +} +#define HANDLE_GLOBAL_EVENT(m) \ + if (handle_global_event(m) == EVENT_HANDLED) return EVENT_HANDLED; static void network_connect_active_ssid(state_machine_t* const State_Machine) { network_t* const nm = (network_t*)State_Machine; - if (network_wifi_connect_active_ssid() != ESP_OK) { - ESP_LOGE(TAG, "Oups. Something went wrong!"); + esp_err_t err = network_wifi_connect_active_ssid(); + if (err != ESP_OK) { nm->wifi_connected = false; - ESP_LOGD(TAG, "Checking if ethernet interface is connected"); - if (network_is_interface_connected(nm->eth_netif)) { - ESP_LOGD(TAG, "Ethernet connection is found. Try to fallback there"); - network_async(EN_ETHERNET_FALLBACK); + + if (err == ESP_ERR_NOT_FOUND) { + network_async_fail(); } else { - // returning to AP mode - nm->STA_duration = nm->sta_polling_min_ms; - ESP_LOGD(TAG, "No ethernet and no wifi configured. Go to configuration mode"); - network_async_configure(); + ESP_LOGE(TAG, "Oups. Something went wrong while trying to connect to the active ssid!"); + ESP_LOGD(TAG, "Checking if ethernet interface is connected"); + if (network_is_interface_connected(nm->eth_netif)) { + ESP_LOGD(TAG, "Ethernet connection is found. Try to fallback there"); + network_async(EN_ETHERNET_FALLBACK); + } else { + // returning to AP mode + nm->STA_duration = nm->sta_polling_min_ms; + ESP_LOGD(TAG, "No ethernet and no wifi configured. Go to configuration mode"); + network_async_configure(); + } } + } else { + nm->STA_duration = nm->sta_polling_min_ms; + /* create timer for background STA connection */ + network_set_timer(nm->STA_duration, "Wifi Polling timeout"); } } -void initialize_network_handlers(state_machine_t* state_machine){ - MEMTRACE_PRINT_DELTA(); - network_initialize_state_machine_globals(); - MEMTRACE_PRINT_DELTA(); - NETWORK_INSTANTIATED_STATE_handler(state_machine); - MEMTRACE_PRINT_DELTA(); -} +void initialize_network_handlers(state_machine_t* state_machine) { NETWORK_INSTANTIATED_STATE_handler(state_machine); } static state_machine_result_t handle_global_event(state_machine_t* state_machine) { - network_t * net_sm= ((network_t *)state_machine); + network_t* net_sm = ((network_t*)state_machine); + esp_err_t err = ESP_OK; + state_machine_result_t result = EVENT_UN_HANDLED; + ESP_LOGD(TAG, "Processing event %s", network_event_to_string(net_sm->Machine.Event)); switch (net_sm->Machine.Event) { - case EN_UPDATE_STATUS: - // handle the event, but don't swicth - MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - start"); - // todo: fix this - // network_status_update_basic_info(); - MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - end"); - return EVENT_HANDLED; - /* code */ + case EN_UPDATE_STATUS: + // handle the event, but don't swicth + // todo: fix this + // network_status_update_basic_info(); + return EVENT_HANDLED; + /* code */ + break; + case EN_REMOVE: + if (net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { + ESP_LOGD(TAG, "Deleting ssid credentials for %s", net_sm->event_parameters->ctx.credentials.ssid); + result = network_wifi_remove_ssid(net_sm->event_parameters->ctx.credentials.ssid) == ESP_OK ? EVENT_HANDLED : EVENT_UN_HANDLED; + FREE_AND_NULL(net_sm->event_parameters->ctx.credentials.ssid); + } + return result; + break; + case EN_ADD: + if (net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { + ESP_LOGD(TAG, "Adding ssid credentials for %s, password %s", net_sm->event_parameters->ctx.credentials.ssid, + STR_OR_BLANK(net_sm->event_parameters->ctx.credentials.password)); + result = + network_wifi_add_ssid(net_sm->event_parameters->ctx.credentials.ssid, net_sm->event_parameters->ctx.credentials.password) == ESP_OK + ? EVENT_HANDLED + : EVENT_UN_HANDLED; + FREE_AND_NULL(net_sm->event_parameters->ctx.credentials.ssid); + FREE_AND_NULL(net_sm->event_parameters->ctx.credentials.password); + } else { + ESP_LOGE(TAG, "Invalid ssid for event EN_ADD"); + } + return result; + break; + case EN_REBOOT: + ESP_LOGD(TAG, "Called for reboot type %d", net_sm->event_parameters->ctx.rtype); + switch (net_sm->event_parameters->ctx.rtype) { + case OTA: + ESP_LOGD(TAG, " Calling guided_restart_ota."); + guided_restart_ota(); break; - case EN_REBOOT: - ESP_LOGD(TAG,"Called for reboot type %d",net_sm->event_parameters->rtype); - switch (net_sm->event_parameters->rtype) { - case OTA: - ESP_LOGD(TAG, " Calling guided_restart_ota."); - guided_restart_ota(); - break; - case RECOVERY: - ESP_LOGD(TAG, " Calling guided_factory."); - guided_factory(); - break; - case RESTART: - ESP_LOGD(TAG, " Calling simple_restart."); - simple_restart(); - break; - - default: - break; - } - return EVENT_UN_HANDLED; + case RECOVERY: + ESP_LOGD(TAG, " Calling guided_factory."); + guided_factory(); break; - case EN_REBOOT_URL: - if (net_sm->event_parameters->strval) { - start_ota(net_sm->event_parameters->strval, NULL, 0); - FREE_AND_NULL(net_sm->event_parameters->strval); - } - return EVENT_UN_HANDLED; + case RESTART: + ESP_LOGD(TAG, " Calling simple_restart."); + simple_restart(); break; default: break; + } + // If configuratin could not be locked because of pending events, + // another reboot event will be queued. So in the meantime + // consider this event as handled + return EVENT_HANDLED; + break; + case EN_REBOOT_URL: + if (net_sm->event_parameters->ctx.strval) { + start_ota(net_sm->event_parameters->ctx.strval, NULL, 0); + FREE_AND_NULL(net_sm->event_parameters->ctx.strval); + } + return EVENT_UN_HANDLED; + break; + case EN_COMMIT_CHANGES: + config_commit_protowrapper((void*)net_sm->event_parameters->ctx.strval); + return EVENT_HANDLED; + break; + case EN_EXECUTE_CALLBACK: + ESP_LOGD(TAG, "Executing Callback"); + if (!net_sm->event_parameters->ctx.cb_ctx.cb && !net_sm->event_parameters->ctx.cb_ctx.ret_cb) { + ESP_LOGE(TAG, "Invalid callback"); + return EVENT_UN_HANDLED; + } else if (net_sm->event_parameters->ctx.cb_ctx.cb) { + ESP_LOGD(TAG, "Executing Callback with no return value"); + net_sm->event_parameters->ctx.cb_ctx.cb(net_sm->event_parameters->ctx.cb_ctx.ctx); + ESP_LOGD(TAG, "Done executing callback"); + return EVENT_HANDLED; + } else if (net_sm->event_parameters->ctx.cb_ctx.ret_cb) { + ESP_LOGD(TAG, "Executing Callback with return value"); + err = net_sm->event_parameters->ctx.cb_ctx.ret_cb(net_sm->event_parameters->ctx.cb_ctx.ctx); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error processing event"); + return EVENT_UN_HANDLED; + } + ESP_LOGD(TAG, "Done executing callback"); + return EVENT_HANDLED; + } + break; + + default: + break; } + return EVENT_UN_HANDLED; } - - - -/********************************************************************************************* +/********************************************************************************************* * INSTANTIATED_STATE */ static state_machine_result_t NETWORK_INSTANTIATED_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); + network_handler_entry_print(State_Machine, true); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t NETWORK_INSTANTIATED_STATE_handler(state_machine_t* const State_Machine) { - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; - network_t* const nm = (network_t *)State_Machine; + network_t* const nm = (network_t*)State_Machine; State_Machine->State = &network_states[NETWORK_INSTANTIATED_STATE]; State_Machine->Event = EN_START; - // config_get_uint16t_from_str("pollmx",&nm->sta_polling_max_ms,600); - // nm->sta_polling_max_ms = nm->sta_polling_max_ms * 1000; - // config_get_uint16t_from_str("apdelay",&nm->ap_duration_ms,20); - // nm->ap_duration_ms = nm->ap_duration_ms * 1000; - // config_get_uint16t_from_str("pollmin",&nm->sta_polling_min_ms,15); - // nm->sta_polling_min_ms = nm->sta_polling_min_ms*1000; - // config_get_uint16t_from_str("ethtmout",&nm->eth_link_down_reboot_ms,30); - // nm->eth_link_down_reboot_ms = nm->eth_link_down_reboot_ms*1000; - // config_get_uint16t_from_str("dhcp_tmout",&nm->dhcp_timeout,30); - // nm->dhcp_timeout = nm->dhcp_timeout*1000; - ESP_LOGI(TAG,"Network manager configuration: polling max %d, polling min %d, ap delay %d, dhcp timeout %d, eth timeout %d", - nm->sta_polling_max_ms,nm->sta_polling_min_ms,nm->ap_duration_ms,nm->dhcp_timeout, nm->eth_link_down_reboot_ms); + nm->sta_polling_max_ms = (platform && platform->net.sta_polling_max_s > 0 ? platform->net.sta_polling_max_s : 600) * 1000; + nm->ap_duration_ms = (platform && platform->net.ap_duration_s > 0 ? platform->net.ap_duration_s : 20) * 1000; + nm->sta_polling_min_ms = (platform && platform->net.sta_polling_min_s > 0 ? platform->net.sta_polling_min_s : 15) * 1000; + nm->eth_link_down_reboot_ms = (platform && platform->dev.eth.common.ethtmout_s > 0 ? platform->dev.eth.common.ethtmout_s : 30) * 1000; + nm->dhcp_timeout = (platform && platform->net.dhcp_tmout_s > 0 ? platform->net.dhcp_tmout_s : 30) * 1000; + ESP_LOGI(TAG, + "Network manager configuration: polling max %d, polling min %d, ap delay %d, dhcp timeout " + "%d, eth timeout %d", + nm->sta_polling_max_ms, nm->sta_polling_min_ms, nm->ap_duration_ms, nm->dhcp_timeout, nm->eth_link_down_reboot_ms); HANDLE_GLOBAL_EVENT(State_Machine); - if (State_Machine->Event == EN_START) { - result= local_traverse_state(State_Machine, &network_states[NETWORK_INITIALIZING_STATE],__FUNCTION__); + #ifndef TESTPROJECT + if(!platform){ + ESP_LOGE(TAG,"Configuration not initialized."); } - network_handler_print(State_Machine,false); + else + { + if (platform && State_Machine->Event == EN_START) { + result = local_traverse_state(State_Machine, &network_states[NETWORK_INITIALIZING_STATE], __FUNCTION__); + } + } + #else + ESP_LOGI(TAG,"network message ignored in test mode"); + result= EVENT_HANDLED; + #endif + + network_handler_print(State_Machine, false); return result; } static state_machine_result_t NETWORK_INSTANTIATED_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * INITIALIZING_STATE */ static state_machine_result_t NETWORK_INITIALIZING_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - - MEMTRACE_PRINT_DELTA_MESSAGE(" Initializing tcp_ip adapter"); - esp_netif_init(); - MEMTRACE_PRINT_DELTA_MESSAGE(" Creating the default event loop"); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - MEMTRACE_PRINT_DELTA_MESSAGE("Initializing network status"); - init_network_status(); - MEMTRACE_PRINT_DELTA_MESSAGE("Loading wifi global configuration"); + network_handler_entry_print(State_Machine, true); + // Initialize nvs; this is needed by the wifi driver + ESP_LOGI(TAG, "Initializing flash nvs "); + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(TAG, "%s. Erasing nvs flash", esp_err_to_name(err)); + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } network_wifi_global_init(); - MEMTRACE_PRINT_DELTA_MESSAGE(" Registering event handler"); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + init_network_status(); esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &network_ip_event_handler, NULL); - MEMTRACE_PRINT_DELTA_MESSAGE(" Initializing network done. Starting http server"); // send a message to start the connections - http_server_start(); - MEMTRACE_PRINT_DELTA_MESSAGE("Executing Callback"); + http_server_start(); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t NETWORK_INITIALIZING_STATE_handler(state_machine_t* const State_Machine) { - - network_handler_print(State_Machine,true); + + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; HANDLE_GLOBAL_EVENT(State_Machine); switch (State_Machine->Event) { - case EN_START: + case EN_START: if (network_is_wifi_prioritized()) { - ESP_LOGI(TAG, "WiFi connection is prioritized. Starting WiFi"); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__); - } - else if(is_recovery_running){ - ESP_LOGI(TAG, "Running recovery. Skipping ethernet, starting WiFi"); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__); - } - else { - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_STARTING_STATE],__FUNCTION__); - } - break; - default: - result= EVENT_UN_HANDLED; + ESP_LOGI(TAG, "WiFi connection is prioritized. Starting WiFi"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); + } else if (is_recovery_running) { + ESP_LOGI(TAG, "Running recovery. Skipping ethernet, starting WiFi"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); + } else { + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_STARTING_STATE], __FUNCTION__); + } + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t NETWORK_INITIALIZING_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * ETH_STARTING_STATE */ static state_machine_result_t ETH_STARTING_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); + network_handler_entry_print(State_Machine, true); ESP_LOGD(TAG, "Looking for ethernet Interface"); - network_t* const nm = (network_t *)State_Machine; + network_t* const nm = (network_t*)State_Machine; init_network_ethernet(); if (!network_ethernet_enabled()) { network_async_fail(); @@ -321,264 +378,280 @@ static state_machine_result_t ETH_STARTING_STATE_entry_handler(state_machine_t* nm->eth_netif = network_ethernet_get_interface(); } NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t ETH_STARTING_STATE_handler(state_machine_t* const State_Machine) { state_machine_result_t result = EVENT_HANDLED; - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); HANDLE_GLOBAL_EVENT(State_Machine); switch (State_Machine->Event) { - case EN_FAIL: - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__); - break; - case EN_SUCCESS: - result= local_traverse_state(State_Machine, &network_states[NETWORK_ETH_ACTIVE_STATE],__FUNCTION__); - break; - default: - ESP_LOGE(TAG, "No handler"); - result= EVENT_UN_HANDLED; + case EN_FAIL: + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); + break; + case EN_SUCCESS: + result = local_traverse_state(State_Machine, &network_states[NETWORK_ETH_ACTIVE_STATE], __FUNCTION__); + break; + default: + ESP_LOGE(TAG, "No handler"); + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t ETH_STARTING_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * NETWORK_ETH_ACTIVE_STATE */ static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - network_t* const nm = (network_t *)State_Machine; - network_set_timer(nm->eth_link_down_reboot_ms,"Ethernet link not detected" ); + network_handler_entry_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; + ESP_LOGD(TAG,"Entering ETH Active state. Setting timer"); + network_set_timer(nm->eth_link_down_reboot_ms, "Ethernet link not detected"); + ESP_LOGD(TAG,"Entering ETH Active state. Executing callback(s)"); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_handler(state_machine_t* const State_Machine) { - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; - network_t* const nm = (network_t *)State_Machine; + network_t* const nm = (network_t*)State_Machine; + switch (State_Machine->Event) { - case EN_CONNECT_NEW: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_CONNECTING_NEW_STATE],__FUNCTION__); - break; - case EN_LINK_UP: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKUP_STATE],__FUNCTION__); - break; - case EN_LINK_DOWN: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKDOWN_STATE],__FUNCTION__); - break; - case EN_ETH_GOT_IP: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__); - break; - case EN_ETHERNET_FALLBACK: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__); - break; - case EN_TIMER: - ESP_LOGW(TAG, "Timeout %s. Rebooting to wifi",STR_OR_ALT(nm->timer_tag,"Ethernet link not detected")); - network_prioritize_wifi(true); - simple_restart(); - //result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__); - break; - case EN_SCAN: - ESP_LOGW(TAG,"Wifi scan cannot be executed in this state"); - //todo: fix this! - // network_wifi_built_known_ap_list(); - result = EVENT_HANDLED; - break; - case EN_DELETE: { - ESP_LOGD(TAG, "WiFi disconnected by user"); - network_wifi_clear_config(); - network_status_update_ip_info(sys_UPDATE_REASONS_R_USER_DISCONNECT); - result= EVENT_HANDLED; - } break; - default: - HANDLE_GLOBAL_EVENT(State_Machine); - result=EVENT_UN_HANDLED; + case EN_CONNECT_NEW: + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_CONNECTING_NEW_STATE], __FUNCTION__); + break; + case EN_LINK_UP: + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKUP_STATE], __FUNCTION__); + break; + case EN_LINK_DOWN: + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKDOWN_STATE], __FUNCTION__); + break; + case EN_ETH_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE], __FUNCTION__); + break; + case EN_ETHERNET_FALLBACK: + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE], __FUNCTION__); + break; + case EN_TIMER: + ESP_LOGW(TAG, "Timeout %s. Rebooting to wifi", STR_OR_ALT(nm->timer_tag, "Ethernet link not detected")); + network_prioritize_wifi(true); + simple_restart(); + // result= local_traverse_state(State_Machine, + // &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__); + break; + case EN_SCAN: + ESP_LOGW(TAG, "Wifi scan cannot be executed in this state"); + // todo: fix this! + // network_wifi_built_known_ap_list(); + result = EVENT_HANDLED; + break; + case EN_DELETE: { + ESP_LOGD(TAG, "WiFi disconnected by user"); + network_wifi_clear_config(); + network_status_update_ip_info(sys_status_reasons_R_USER_DISCONNECT); + + result = EVENT_HANDLED; + } break; + default: + HANDLE_GLOBAL_EVENT(State_Machine); + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } - - -/********************************************************************************************* +/********************************************************************************************* * ETH_CONNECTING_NEW_STATE */ static state_machine_result_t ETH_CONNECTING_NEW_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); network_start_stop_dhcp_client(nm->wifi_netif, true); - network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password); - FREE_AND_NULL(nm->event_parameters->ssid); - FREE_AND_NULL(nm->event_parameters->password); + network_wifi_connect(nm->event_parameters->ctx.credentials.ssid, nm->event_parameters->ctx.credentials.password); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.ssid); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.password); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t ETH_CONNECTING_NEW_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { - case EN_GOT_IP: - result= local_traverse_state(State_Machine, &network_states[WIFI_CONNECTED_STATE],__FUNCTION__); - break; - case EN_LOST_CONNECTION: - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT); - messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to connect to new WiFi access point."); - // no existing configuration, or wifi wasn't the active connection when connection - // attempt was made - network_async(EN_ETHERNET_FALLBACK); - result = EVENT_HANDLED; - break; + network_t* const nm = (network_t*)State_Machine; - default: - result= EVENT_UN_HANDLED; + switch (State_Machine->Event) { + case EN_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + result = local_traverse_state(State_Machine, &network_states[WIFI_CONNECTED_STATE], __FUNCTION__); + break; + case EN_LOST_CONNECTION: + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to connect to new WiFi access point."); + // no existing configuration, or wifi wasn't the active connection when connection + // attempt was made + network_async(EN_ETHERNET_FALLBACK); + result = EVENT_HANDLED; + break; + + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t ETH_CONNECTING_NEW_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * ETH_ACTIVE_LINKDOWN */ static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - network_t* const nm = (network_t *)State_Machine; - network_set_timer(nm->eth_link_down_reboot_ms, "Ethernet link down" ); + network_handler_entry_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; + network_set_timer(nm->eth_link_down_reboot_ms, "Ethernet link down"); NETWORK_EXECUTE_CB(State_Machine); messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Ethernet link down."); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_handler(state_machine_t* const State_Machine) { - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return EVENT_UN_HANDLED; } static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - network_exit_handler_print(State_Machine,false); - + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + network_exit_handler_print(State_Machine, false); + return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * ETH_ACTIVE_LINKUP_STATE */ static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - network_t* const nm = (network_t *)State_Machine; - network_set_timer(nm->dhcp_timeout, "DHCP timeout" ); + network_handler_entry_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; + network_set_timer(nm->dhcp_timeout, "DHCP timeout"); NETWORK_EXECUTE_CB(State_Machine); messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "Ethernet link up."); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_handler(state_machine_t* const State_Machine) { state_machine_result_t result = EVENT_UN_HANDLED; - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * WIFI_UP_STATE */ static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); + network_handler_entry_print(State_Machine, true); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; - switch (State_Machine->Event) - { - case EN_LINK_UP: - ESP_LOGW(TAG, "Ethernet link up in wifi mode"); - break; - case EN_ETH_GOT_IP: - network_interface_coexistence(State_Machine); - break; - case EN_GOT_IP: - network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__); - break; - case EN_SCAN: - if (network_wifi_start_scan() == ESP_OK) { - result= EVENT_HANDLED; - } - break; - case EN_SCAN_DONE: - if(wifi_scan_done() == ESP_OK) { - result= EVENT_HANDLED; - } - break; - case EN_CONNECT_NEW: - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_STATE],__FUNCTION__); - break; - case EN_DELETE: - result= local_traverse_state(State_Machine,&Wifi_Active_State[WIFI_USER_DISCONNECTED_STATE],__FUNCTION__); - break; - case EN_ETHERNET_FALLBACK: - result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__); - break; - default: - break; + network_t* const nm = (network_t*)State_Machine; + switch (State_Machine->Event) { + case EN_LINK_UP: + ESP_LOGW(TAG, "Ethernet link up in wifi mode"); + break; + case EN_ETH_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + network_interface_coexistence(State_Machine); + break; + case EN_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + + network_status_update_ip_info(sys_status_reasons_R_CONNECTION_OK); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE], __FUNCTION__); + break; + case EN_SCAN: + if (network_wifi_start_scan() == ESP_OK) { + result = EVENT_HANDLED; + } + break; + case EN_SCAN_DONE: + if (wifi_scan_done() == ESP_OK) { + result = EVENT_HANDLED; + } + network_async_success(); + break; + case EN_CONNECT_NEW: + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_STATE], __FUNCTION__); + break; + case EN_DELETE: + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_USER_DISCONNECTED_STATE], __FUNCTION__); + break; + + case EN_ETHERNET_FALLBACK: + result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE], __FUNCTION__); + break; + default: + break; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * WIFI_INITIALIZING_STATE */ static state_machine_result_t WIFI_INITIALIZING_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); - if(!nm->wifi_netif){ + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + if (!nm->wifi_netif) { nm->wifi_netif = network_wifi_start(); } if (!is_wifi_up()) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration"); return EVENT_UN_HANDLED; } - if (network_wifi_get_known_count()>0) { + if (network_wifi_get_known_count() > 0) { ESP_LOGI(TAG, "Existing wifi config found. Attempting to connect."); network_async_success(); } else { @@ -587,82 +660,86 @@ static state_machine_result_t WIFI_INITIALIZING_STATE_entry_handler(state_machin network_async_configure(); } NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_INITIALIZING_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; switch (State_Machine->Event) { - case EN_CONFIGURE: - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); - break; - case EN_SUCCESS: - result= local_switch_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_STATE],__FUNCTION__); - break; - default: - result= EVENT_UN_HANDLED; + case EN_CONFIGURE: + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); + break; + case EN_SUCCESS: + ESP_LOGI(TAG, "Traversing to Connecting state"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_INITIALIZING_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } - -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONFIGURING_ACTIVE_STATE */ static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - network_t* const nm = (network_t *)State_Machine; + network_handler_entry_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; nm->wifi_ap_netif = network_wifi_config_ap(); dns_server_start(nm->wifi_ap_netif); network_wifi_start_scan(); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; + state_machine_result_t result = EVENT_HANDLED; switch (State_Machine->Event) { - case EN_SCAN: - if (network_wifi_start_scan() == ESP_OK) { - result= EVENT_HANDLED; - } - break; - case EN_SCAN_DONE: - ESP_LOGD(TAG,"Network configuration active, wifi scan completed"); - if(wifi_scan_done() == ESP_OK) { - result= EVENT_HANDLED; - } - break; - case EN_CONNECT_NEW: - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_STATE],__FUNCTION__); - break; - case EN_LINK_UP: - ESP_LOGW(TAG, "Ethernet link up in wifi mode"); - break; - case EN_ETH_GOT_IP: - network_interface_coexistence(State_Machine); - break; - default: - result =EVENT_UN_HANDLED; + case EN_SCAN: + if (network_wifi_start_scan() == ESP_OK) { + result = EVENT_HANDLED; + } + break; + case EN_SCAN_DONE: + ESP_LOGD(TAG, "Network configuration active, wifi scan completed"); + if (wifi_scan_done() == ESP_OK) { + result = EVENT_HANDLED; + } + break; + case EN_CONNECT_NEW: + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_STATE], __FUNCTION__); + break; + case EN_LINK_UP: + ESP_LOGW(TAG, "Ethernet link up in wifi mode"); + break; + case EN_ETH_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + network_interface_coexistence(State_Machine); + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) { network_exit_handler_print(State_Machine, true); /* bring down DNS hijack */ ESP_LOGD(TAG, " Stopping DNS."); - dns_server_stop(); + dns_server_stop(); ESP_LOGD(TAG, "Changing wifi mode to STA."); network_wifi_set_sta_mode(); network_exit_handler_print(State_Machine, false); @@ -670,401 +747,452 @@ static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_exit_handler return EVENT_HANDLED; } - -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONFIGURING_STATE */ static state_machine_result_t WIFI_CONFIGURING_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); + network_handler_entry_print(State_Machine, true); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONFIGURING_STATE_handler(state_machine_t* const State_Machine) { - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return EVENT_UN_HANDLED; } static state_machine_result_t WIFI_CONFIGURING_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONFIGURING_CONNECT_STATE */ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); network_start_stop_dhcp_client(nm->wifi_netif, true); - network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password); - FREE_AND_NULL(nm->event_parameters->ssid); - FREE_AND_NULL(nm->event_parameters->password); + network_wifi_connect(nm->event_parameters->ctx.credentials.ssid, nm->event_parameters->ctx.credentials.password); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.ssid); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.password); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); - network_t* const nm = (network_t *)State_Machine; + network_handler_print(State_Machine, true); + network_t* const nm = (network_t*)State_Machine; state_machine_result_t result = EVENT_HANDLED; switch (State_Machine->Event) { - case EN_CONNECTED: - result=EVENT_HANDLED; - ESP_LOGI(TAG,"Wifi was connected. Waiting for IP address"); - network_set_timer(nm->dhcp_timeout,"DHCP Timeout"); - break; - case EN_GOT_IP: - network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK); - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_SUCCESS_STATE],__FUNCTION__); - break; - case EN_LOST_CONNECTION: - if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { - ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect."); - } - else { - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT); - result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); - } - break; - case EN_TIMER: - ESP_LOGW(TAG,"Connection timeout. (%s)",STR_OR_ALT(nm->timer_tag, "Unknown")); - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT); - result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); - break; - default: - result= EVENT_UN_HANDLED; + case EN_CONNECTED: + result = EVENT_HANDLED; + ESP_LOGI(TAG, "Wifi was connected. Waiting for IP address"); + network_set_timer(nm->dhcp_timeout, "DHCP Timeout"); + network_wifi_set_connected(true); + break; + case EN_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + network_status_update_ip_info(sys_status_reasons_R_CONNECTION_OK); + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_SUCCESS_STATE], __FUNCTION__); + break; + case EN_LOST_CONNECTION: + if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + ESP_LOGI(TAG, "Wifi was disconnected from previous access point. Waiting to connect."); + } else { + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); + } + break; + case EN_TIMER: + ESP_LOGW(TAG, "Connection timeout. (%s)", STR_OR_ALT(nm->timer_tag, "Unknown")); + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); + network_exit_handler_print(State_Machine, true); - FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event); - network_set_timer(0,NULL); - network_exit_handler_print(State_Machine,false); + FREE_AND_NULL(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event); + network_set_timer(0, NULL); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONFIGURING_CONNECT_SUCCESS_STATE */ static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); - network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK); + network_handler_entry_print(State_Machine, true); + network_status_update_ip_info(sys_status_reasons_R_CONNECTION_OK); ESP_LOGD(TAG, "Saving wifi configuration."); // todo: fix this! // network_wifi_save_sta_config(); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_handler(state_machine_t* const State_Machine) { - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - network_t* const nm = (network_t *)State_Machine; + network_t* const nm = (network_t*)State_Machine; switch (State_Machine->Event) { - case EN_UPDATE_STATUS: - // todo: fix this - // network_status_update_basic_info(); - network_set_timer(nm->ap_duration_ms,"Access point teardown"); // set a timer to tear down the AP mode - break; - case EN_TIMER: - // todo: fix this - // network_status_update_basic_info(); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__); - break; - default: - result= EVENT_UN_HANDLED; + case EN_UPDATE_STATUS: + // todo: fix this + // network_status_update_basic_info(); + network_set_timer(nm->ap_duration_ms, "Access point teardown"); // set a timer to tear down the AP mode + break; + case EN_TIMER: + // todo: fix this + // network_status_update_basic_info(); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; } // Process global handler at the end, since we want to overwrite // UPDATE_STATUS with our own logic above HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } - - - -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONNECTING_STATE */ static state_machine_result_t WIFI_CONNECTING_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + nm->initial_retries = 0; network_start_stop_dhcp_client(nm->wifi_netif, true); network_connect_active_ssid(State_Machine); - nm->STA_duration = nm->sta_polling_min_ms; - /* create timer for background STA connection */ - network_set_timer(nm->STA_duration,"Wifi Polling timeout"); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); state_machine_result_t result = EVENT_HANDLED; - network_t* const nm = (network_t *)State_Machine; - network_handler_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_print(State_Machine, true); switch (State_Machine->Event) { - case EN_CONNECTED: - // nothing to do here. Let's wait for IP address - break; - case EN_TIMER: - // try connecting again. - // todo: implement multi-ap logic - ESP_LOGI(TAG, "Timer: %s ",STR_OR_ALT(nm->timer_tag,"Ethernet link not detected")); + case EN_CONNECTED: + // nothing to do here. Let's wait for IP address + break; + case EN_TIMER: + if (nm->initial_retries < (platform!=NULL && platform->net.max_initial_wifi_attempt>0?platform->net.max_initial_wifi_attempt:5)) { + nm->initial_retries++; + ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->initial_retries, platform->net.max_initial_wifi_attempt); + ESP_LOGI(TAG, "Timer: %s ", STR_OR_ALT(nm->timer_tag, "Ethernet link not detected")); network_connect_active_ssid(State_Machine); - break; - case EN_LOST_CONNECTION: - if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_AUTH_EXPIRE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_EXPIRE) { - ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect."); - } - else if(nm->event_parameters->disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) { - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT); - result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); - } - break; - default: - result = EVENT_UN_HANDLED; + } else { + } + break; + case EN_LOST_CONNECTION: + if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || + nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_AUTH_EXPIRE || + nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_EXPIRE) { + ESP_LOGI(TAG, "Wifi was disconnected from previous access point. Waiting to connect."); + } else if (nm->event_parameters->ctx.disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) { + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); + } + break; + case EN_FAIL: + // this would happen if there is no previously connected AP + ESP_LOGD(TAG, "No active access point. switching to scan"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_SCAN_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONNECTING_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* + * WIFI_CONNECTING_STATE + */ +static state_machine_result_t WIFI_CONNECTING_SCAN_STATE_entry_handler(state_machine_t* const State_Machine) { + ESP_LOGD(TAG, "Entering Scan State"); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + network_async_scan(); + NETWORK_EXECUTE_CB(State_Machine); + network_handler_entry_print(State_Machine, false); + return EVENT_HANDLED; +} +static state_machine_result_t WIFI_CONNECTING_SCAN_STATE_handler(state_machine_t* const State_Machine) { + HANDLE_GLOBAL_EVENT(State_Machine); + state_machine_result_t result = EVENT_HANDLED; + network_handler_print(State_Machine, true); + switch (State_Machine->Event) { + case EN_SUCCESS: + // scan completed, we can try to connect to a known AP now + network_wifi_activate_strongest_ssid(); + result = local_switch_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; + } + network_handler_print(State_Machine, false); + return result; +} +static state_machine_result_t WIFI_CONNECTING_SCAN_STATE_exit_handler(state_machine_t* const State_Machine) { + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); + return EVENT_HANDLED; +} + +/********************************************************************************************* * WIFI_CONNECTING_NEW_STATE */ static state_machine_result_t WIFI_CONNECTING_NEW_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); network_start_stop_dhcp_client(nm->wifi_netif, true); - network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password); - FREE_AND_NULL(nm->event_parameters->ssid); - FREE_AND_NULL(nm->event_parameters->password); + network_wifi_connect(nm->event_parameters->ctx.credentials.ssid, nm->event_parameters->ctx.credentials.password); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.ssid); + FREE_AND_NULL(nm->event_parameters->ctx.credentials.password); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { - case EN_GOT_IP: - network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__); - break; - case EN_CONNECTED: - ESP_LOGD(TAG,"Successfully connected to the new access point. Waiting for IP Address"); - result = EVENT_HANDLED; - break; - case EN_LOST_CONNECTION: - if(((network_t *)State_Machine)->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE){ - ESP_LOGD(TAG,"Successfully disconnected from the existing access point. "); - return EVENT_HANDLED; - } - ESP_LOGW(TAG,"Trying to connect failed"); - result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_FAILED_STATE],__FUNCTION__); - break; + network_t* const nm = (network_t*)State_Machine; - default: - result= EVENT_UN_HANDLED; + switch (State_Machine->Event) { + case EN_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + + network_status_update_ip_info(sys_status_reasons_R_CONNECTION_OK); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE], __FUNCTION__); + break; + case EN_CONNECTED: + ESP_LOGD(TAG, "Successfully connected to the new access point. Waiting for IP Address"); + result = EVENT_HANDLED; + break; + case EN_LOST_CONNECTION: + if (((network_t*)State_Machine)->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + ESP_LOGD(TAG, "Successfully disconnected from the existing access point. "); + return EVENT_HANDLED; + } + ESP_LOGW(TAG, "Trying to connect failed"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_FAILED_STATE], __FUNCTION__); + break; + + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONNECTING_NEW_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event); - network_exit_handler_print(State_Machine,false); - + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + FREE_AND_NULL(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event); + network_exit_handler_print(State_Machine, false); + return EVENT_HANDLED; } - - -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONNECTING_NEW_FAILED_STATE */ static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); - if (nm->wifi_connected ) { + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + if (nm->wifi_connected) { // Wifi was already connected to an existing access point. Restore connection - network_connect_active_ssid(State_Machine); - } - + network_connect_active_ssid(State_Machine); + } + NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { - case EN_GOT_IP: - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT_AND_RESTORE); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__); - break; - case EN_CONNECTED: - ESP_LOGD(TAG,"Successfully connected to the previous access point. Waiting for IP Address"); - result = EVENT_HANDLED; - break; - case EN_LOST_CONNECTION: - network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT); - messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to fall back to previous access point."); - result = EVENT_HANDLED; - break; + network_t* const nm = (network_t*)State_Machine; - default: - result= EVENT_UN_HANDLED; + switch (State_Machine->Event) { + case EN_GOT_IP: + network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); + FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); + + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT_AND_RESTORE); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE], __FUNCTION__); + break; + case EN_CONNECTED: + ESP_LOGD(TAG, "Successfully connected to the previous access point. Waiting for IP Address"); + result = EVENT_HANDLED; + break; + case EN_LOST_CONNECTION: + network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); + messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to fall back to previous access point."); + result = EVENT_HANDLED; + break; + + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_set_timer(0,NULL); - FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event); - network_exit_handler_print(State_Machine,false); - + network_exit_handler_print(State_Machine, true); + network_set_timer(0, NULL); + FREE_AND_NULL(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event); + network_exit_handler_print(State_Machine, false); + return EVENT_HANDLED; } - - -/********************************************************************************************* +/********************************************************************************************* * WIFI_CONNECTED_STATE */ static state_machine_result_t WIFI_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + ESP_LOGD(TAG,"Entered WIFI_CONNECTED_STATE "); nm->last_connected = esp_timer_get_time(); // cancel timeout pulse - network_set_timer(0,NULL); - ESP_LOGD(TAG, "Checking if wifi config changed."); - if (network_wifi_sta_config_changed()) { - ESP_LOGD(TAG, "Wifi Config changed. Saving it."); - configurator_raise_changed(); - } - ESP_LOGD(TAG, "Updating the ip info json."); + network_set_timer(0, NULL); network_interface_coexistence(State_Machine); nm->wifi_connected = true; NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_CONNECTED_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; + network_t* const nm = (network_t*)State_Machine; switch (State_Machine->Event) { - case EN_LOST_CONNECTION: - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__); - break; - default: - result = EVENT_UN_HANDLED; - break; + case EN_LOST_CONNECTION: + if (is_restarting()) { + // ignore this as we're restarting + return EVENT_HANDLED; + } + if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + ESP_LOGD(TAG, "User disconnected from wifi. Re-initializing connection"); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); + } else { + ESP_LOGD(TAG, "Lost connection for a reason other than disconnecting. "); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE], __FUNCTION__); + } + + break; + default: + result = EVENT_UN_HANDLED; + break; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + FREE_AND_NULL(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } - -/********************************************************************************************* +/********************************************************************************************* * WIFI_USER_DISCONNECTED_STATE */ static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) { - network_handler_entry_print(State_Machine,true); + network_handler_entry_print(State_Machine, true); ESP_LOGD(TAG, " WiFi disconnected by user"); network_wifi_clear_config(); - network_status_update_ip_info(sys_UPDATE_REASONS_R_USER_DISCONNECT); + network_status_update_ip_info(sys_status_reasons_R_USER_DISCONNECT); NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; switch (State_Machine->Event) { - case EN_LOST_CONNECTION: - // this is a success! we're actually asking to disconnect - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); + case EN_LOST_CONNECTION: + // this is a success! we're actually asking to disconnect + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); break; - default: - result= EVENT_UN_HANDLED; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -/********************************************************************************************* +/********************************************************************************************* * WIFI_LOST_CONNECTION_STATE */ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); ESP_LOGE(TAG, " WiFi Connection lost."); messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost"); - network_status_update_ip_info(sys_UPDATE_REASONS_R_LOST_CONNECTION); - //todo: fix this! - // network_status_safe_reset_sta_ip_string(); - if (nm->last_connected > 0) - nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000)); + network_status_update_ip_info(sys_status_reasons_R_LOST_CONNECTION); + // todo: fix this! + // network_status_safe_reset_sta_ip_string(); + if (nm->last_connected > 0) nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000)); nm->last_connected = 0; nm->num_disconnect++; - ESP_LOGW(TAG, " Wifi disconnected. Number of disconnects: %d, Average time connected: %d", nm->num_disconnect, nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0); - if (nm->retries < WIFI_MANAGER_MAX_RETRY) { + ESP_LOGW(TAG, " Wifi disconnected. Number of disconnects: %d, Average time connected: %d", nm->num_disconnect, + nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0); + if (nm->retries < (platform && platform->net.max_wifi_retry>0?platform->net.max_wifi_retry:5)) { nm->retries++; - ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->retries, WIFI_MANAGER_MAX_RETRY); + ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->retries, platform->net.max_wifi_retry); network_async(EN_CONNECT); } else { /* In this scenario the connection was lost beyond repair */ nm->retries = 0; - ESP_LOGD(TAG,"Checking if ethernet interface is connected"); + ESP_LOGD(TAG, "Checking if ethernet interface is connected"); if (network_is_interface_connected(nm->eth_netif)) { ESP_LOGW(TAG, "Cannot connect to Wifi. Falling back to Ethernet "); network_async(EN_ETHERNET_FALLBACK); } else { - network_status_update_ip_info(sys_UPDATE_REASONS_R_LOST_CONNECTION); + network_status_update_ip_info(sys_status_reasons_R_LOST_CONNECTION); wifi_mode_t mode; ESP_LOGW(TAG, " All connect retry attempts failed."); /* put us in softAP mode first */ esp_wifi_get_mode(&mode); if (WIFI_MODE_APSTA != mode) { - nm->STA_duration = nm->sta_polling_min_ms; + nm->STA_duration = nm->sta_polling_min_ms; network_async_configure(); } else if (nm->STA_duration < nm->sta_polling_max_ms) { nm->STA_duration *= 1.25; @@ -1077,108 +1205,102 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac } NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t WIFI_LOST_CONNECTION_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); - network_t* const nm = (network_t *)State_Machine; + network_t* const nm = (network_t*)State_Machine; state_machine_result_t result = EVENT_HANDLED; - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); switch (State_Machine->Event) { - case EN_CONFIGURE: - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__); - break; - case EN_TIMER: - ESP_LOGI(TAG, "Timer: %s ",STR_OR_ALT(nm->timer_tag,"Lost connection")); - result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__); - break; - case EN_CONNECT: - result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONNECTING_STATE],__FUNCTION__); - break; - default: - result= EVENT_UN_HANDLED; + case EN_CONFIGURE: + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); + break; + case EN_TIMER: + ESP_LOGI(TAG, "Timer: %s ", STR_OR_ALT(nm->timer_tag, "Lost connection")); + result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE], __FUNCTION__); + break; + case EN_CONNECT: + result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONNECTING_STATE], __FUNCTION__); + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t WIFI_LOST_CONNECTION_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + FREE_AND_NULL(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } - -/********************************************************************************************* +/********************************************************************************************* * ETH_ACTIVE_CONNECTED_STATE */ static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) { - network_t* const nm = (network_t *)State_Machine; - network_handler_entry_print(State_Machine,true); - network_status_update_ip_info(sys_UPDATE_REASONS_R_ETHERNET_CONNECTED); + network_t* const nm = (network_t*)State_Machine; + network_handler_entry_print(State_Machine, true); + network_status_update_ip_info(sys_status_reasons_R_ETHERNET_CONNECTED); nm->ethernet_connected = true; - // start a wifi Scan so web ui is populated with available entries NETWORK_EXECUTE_CB(State_Machine); - network_handler_entry_print(State_Machine,false); + network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; } static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_handler(state_machine_t* const State_Machine) { HANDLE_GLOBAL_EVENT(State_Machine); state_machine_result_t result = EVENT_HANDLED; - network_handler_print(State_Machine,true); + network_handler_print(State_Machine, true); switch (State_Machine->Event) { - case EN_TIMER: - ESP_LOGD(TAG, "Ignoring ethernet link up timer check"); - result= EVENT_HANDLED; - break; - default: - result= EVENT_UN_HANDLED; + case EN_TIMER: + ESP_LOGD(TAG, "Ignoring ethernet link up timer check"); + result = EVENT_HANDLED; + break; + default: + result = EVENT_UN_HANDLED; } - network_handler_print(State_Machine,false); + network_handler_print(State_Machine, false); return result; } static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) { - network_exit_handler_print(State_Machine,true); - network_exit_handler_print(State_Machine,false); + network_exit_handler_print(State_Machine, true); + network_exit_handler_print(State_Machine, false); return EVENT_HANDLED; } -static state_machine_result_t local_switch_state(state_machine_t* state_machine, - const state_t* const target_state, const char * caller) { +static state_machine_result_t local_switch_state(state_machine_t* state_machine, const state_t* const target_state, const char* caller) { const state_t* source = state_machine->State; - NETWORK_PRINT_TRANSITION(true, "BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller); + NETWORK_PRINT_TRANSITION(true, "BEGIN SWITCH", ((network_t*)state_machine)->source_state, target_state, state_machine->Event, true, caller); state_machine_result_t result = switch_state(state_machine, target_state); - NETWORK_PRINT_TRANSITION( false,"BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller); - ((network_t *)state_machine)->source_state = source; + NETWORK_PRINT_TRANSITION(false, "BEGIN SWITCH", ((network_t*)state_machine)->source_state, target_state, state_machine->Event, true, caller); + ((network_t*)state_machine)->source_state = source; return result; } -static state_machine_result_t local_traverse_state(state_machine_t* const state_machine, - const state_t* const target_state, const char * caller) { - const state_t * source = state_machine->State; - NETWORK_PRINT_TRANSITION( true,"BEGIN TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true, caller); +static state_machine_result_t local_traverse_state(state_machine_t* const state_machine, const state_t* const target_state, const char* caller) { + const state_t* source = state_machine->State; + NETWORK_PRINT_TRANSITION(true, "BEGIN TRAVERSE", ((network_t*)state_machine)->source_state, target_state, state_machine->Event, true, caller); state_machine_result_t result = traverse_state(state_machine, target_state); - NETWORK_PRINT_TRANSITION( false,"END TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller); - ((network_t *)state_machine)->source_state = source; + NETWORK_PRINT_TRANSITION(false, "END TRAVERSE", ((network_t*)state_machine)->source_state, target_state, state_machine->Event, true, caller); + ((network_t*)state_machine)->source_state = source; return result; } static void network_interface_coexistence(state_machine_t* state_machine) { // this function is called whenever both wifi and ethernet are // found to be active at the same time - network_t* nm = (network_t *)state_machine; + network_t* nm = (network_t*)state_machine; if (nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) { - // char* eth_reboot = config_alloc_get_default(NVS_TYPE_STR, "eth_boot", "N", 0); - // network_prioritize_wifi(false); - // if (strcasecmp(eth_reboot, "N")) { - // ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting"); - // simple_restart(); - // } else { - // ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using Wifi interface until next reboot"); - // } - // FREE_AND_NULL(eth_reboot); - // TODO: Add support for the commented code - } else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE){ + network_prioritize_wifi(false); + if (platform && !platform->net.eth_boot) { + ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting"); + simple_restart(); + } else { + ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using " + "Wifi interface until next reboot"); + } + } else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi Connected with Ethernet active. System reload needed"); simple_restart(); } diff --git a/components/wifi-manager/network_services.h b/components/wifi-manager/network_services.h index 31c7e951..8bbbf081 100644 --- a/components/wifi-manager/network_services.h +++ b/components/wifi-manager/network_services.h @@ -1,3 +1,26 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + #pragma once #include "esp_netif.h" @@ -27,6 +50,7 @@ extern "C" { #define ALL_WIFI_STATE(PARENT, LEVEL)\ ADD_LEAF(WIFI_INITIALIZING_STATE,PARENT,LEVEL)\ ADD_LEAF(WIFI_CONNECTING_STATE,PARENT,LEVEL)\ + ADD_LEAF(WIFI_CONNECTING_SCAN_STATE,PARENT,LEVEL)\ ADD_LEAF(WIFI_CONNECTING_NEW_STATE,PARENT,LEVEL)\ ADD_LEAF(WIFI_CONNECTING_NEW_FAILED_STATE,PARENT,LEVEL)\ ADD_LEAF(WIFI_CONNECTED_STATE,PARENT,LEVEL)\ diff --git a/components/wifi-manager/network_status.c b/components/wifi-manager/network_status.c deleted file mode 100644 index 29a08e0f..00000000 --- a/components/wifi-manager/network_status.c +++ /dev/null @@ -1,188 +0,0 @@ -#ifdef NETWORK_STATUS_LOG_LEVEL -#define LOG_LOCAL_LEVEL NETWORK_STATUS_LOG_LEVEL -#endif - -#include "network_status.h" -#include -#ifdef CONFIG_BT_ENABLED -#include "bt_app_core.h" -#endif -#include "esp_log.h" -#include "lwip/inet.h" -#include "monitor.h" -#include "network_ethernet.h" -#include "network_wifi.h" -// #include "Configurator.h" -#pragma message("fixme: search for TODO below") -#include "platform_esp32.h" -#include "tools.h" -#include "trace.h" -#ifndef CONFIG_SQUEEZELITE_ESP32_RELEASE_URL -#pragma message "Defaulting release url" -#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" -#endif -static const char TAG[] = "network_status"; -sys_Status status; -SemaphoreHandle_t network_status_structure_mutex = NULL; -static TaskHandle_t network_structure_locked_task = NULL; -static void (*chained_notify)(in_addr_t, u16_t, u16_t); -static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport); - -#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX - -void init_network_status() { - chained_notify = server_notify; - server_notify = connect_notify; - ESP_LOGD(TAG, "init_network_status. Creating mutexes"); - network_status_structure_mutex = xSemaphoreCreateMutex(); - ESP_LOGD(TAG, "Getting release url "); - - } -void destroy_network_status() { - vSemaphoreDelete(network_status_structure_mutex); - network_status_structure_mutex = NULL; -} - -void network_status_unlock_structure() { - ESP_LOGV(TAG, "Unlocking json buffer!"); - network_structure_locked_task = NULL; - xSemaphoreGive(network_status_structure_mutex); -} - -bool network_status_lock_structure(TickType_t xTicksToWait) { - ESP_LOGV(TAG, "Locking structure buffer"); - - TaskHandle_t calling_task = xTaskGetCurrentTaskHandle(); - if (calling_task == network_structure_locked_task) { - ESP_LOGV(TAG, "structure buffer already locked to current task"); - return true; - } - - if (network_status_structure_mutex) { - if (xSemaphoreTake(network_status_structure_mutex, xTicksToWait) == pdTRUE) { - ESP_LOGV(TAG, "structure locked!"); - network_structure_locked_task = calling_task; - return true; - } else { - ESP_LOGE(TAG, "Semaphore take failed. Unable to lock structure mutex"); - return false; - } - } else { - ESP_LOGV(TAG, "Unable to lock structure mutex"); - return false; - } -} - -char* network_status_get_sta_ip_string() { - return status.has_net && status.net.has_ip?status.net.ip.ip:"0.0.0.0"; -} -void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) { - if (network_status_lock_structure(portMAX_DELAY)) { - status.has_LMS = true; - strncpy(status.LMS.ip, inet_ntoa(ip), sizeof(status.LMS.ip)); - status.LMS.port = hport; - status.LMS.cport = cport; - ESP_LOGI(TAG, "LMS IP: %s, hport: %d, cport: %d", status.LMS.ip, status.LMS.port, status.LMS.cport); - network_status_unlock_structure(); - } -} -static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) { - set_lms_server_details(ip, hport, cport); - if (chained_notify) - (*chained_notify)(ip, hport, cport); - network_async_update_status(); -} - -void network_status_set_basic_info() { - if (network_status_lock_structure(portMAX_DELAY)) { - network_t* nm = network_get_state_machine(); - sys_GPIO * gpio = NULL; - const esp_app_desc_t* desc = esp_ota_get_app_description(); - status.has_platform = true; - strncpy(status.platform.project, desc->project_name, sizeof(status.platform.project)); -#ifdef CONFIG_FW_PLATFORM_NAME - strncpy(status.platform.name, CONFIG_FW_PLATFORM_NAME, sizeof(status.platform.name)); -#endif - strncpy(status.platform.version, desc->version, sizeof(status.platform.version)); - strncpy(status.platform.version, desc->version, sizeof(status.platform.version)); - status.platform.recovery = is_recovery_running; - status.platform.depth = 16; -#if DEPTH == 16 || DEPTH == 32 - status.platform.depth = DEPTH; -#endif - status.has_hw = true; - - status.hw.jack_inserted = jack_inserted_svc(); - status.hw.has_jack_inserted = SYS_GPIOS_NAME(jack,gpio) && gpio->pin>=0; - status.hw.has_spk_fault = SYS_GPIOS_NAME(spkfault,gpio) && gpio->pin>=0; - status.hw.spk_fault = spkfault_svc(); - status.hw.batt_voltage = battery_value_svc(); - status.has_net = true; - status.net.has_wifi = true; - status.net.wifi.disconnect_count = nm->num_disconnect; - status.net.wifi.avg_conn_time = nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0; - -#ifdef CONFIG_BT_ENABLED - if(platform->has_services && platform->services.has_bt_sink && platform->services.bt_sink.enabled){ - status.has_bt = true; - status.bt.bt_status = bt_app_source_get_a2d_state(); - status.bt.bt_media_state = bt_app_source_get_media_state(); - } -#endif - - if (network_ethernet_enabled()) { - status.net.eth_up = network_ethernet_is_up(); - } - ESP_LOGV(TAG, "network_status_get_basic_info done"); - network_status_unlock_structure(); - } else { - ESP_LOGW(TAG, "Unable to lock status json buffer. "); - } -} -void network_status_update_address(esp_netif_ip_info_t* ip_info) { - status.has_net = true; - status.net.has_ip = true; - strncpy(status.net.ip.ip,ip4addr_ntoa((ip4_addr_t*)&ip_info->ip),sizeof(status.net.ip.ip)); - strncpy(status.net.ip.netmask,ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask),sizeof(status.net.ip.netmask)); - strncpy(status.net.ip.gw,ip4addr_ntoa((ip4_addr_t*)&ip_info->gw),sizeof(status.net.ip.gw)); -} -void network_status_update_ip_info(sys_UPDATE_REASONS update_reason_code) { - ESP_LOGV(TAG, "network_status_update_ip_info called"); - esp_netif_ip_info_t ip_info; - if (network_status_lock_structure(portMAX_DELAY)) { - /* generate the connection info with success */ - - network_status_set_basic_info(); - status.net.updt_reason = update_reason_code; - status.net.wifi.has_connected_sta = false; - status.net.wifi.connected_sta.connected = false; - - ESP_LOGD(TAG,"Updating ip info with reason code %d. Checking if Wifi interface is connected",update_reason_code); - if (network_is_interface_connected(network_wifi_get_interface()) || update_reason_code == sys_UPDATE_REASONS_R_FAILED_ATTEMPT ) { - status.net.interface = sys_CONNECTED_IF_IF_WIFI; - - esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info); - network_status_update_address(&ip_info); - if (!network_wifi_is_ap_mode()) { - /* wifi is active, and associated to an AP */ - wifi_ap_record_t ap; - esp_wifi_sta_get_ap_info(&ap); - network_wifi_esp_sta_to_sta(&ap, &status.net.wifi.connected_sta); - status.net.wifi.connected_sta.connected = true; - status.net.has_wifi = true; - status.net.wifi.has_connected_sta = true; - } - - } - ESP_LOGD(TAG,"Checking if ethernet interface is connected"); - if (network_is_interface_connected(network_ethernet_get_interface())) { - status.net.interface = sys_CONNECTED_IF_IF_ETHERNET; - esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info); - network_status_update_address(&ip_info); - } - network_status_unlock_structure(); - } else { - ESP_LOGW(TAG, "Unable to lock status json buffer. "); - } - ESP_LOGV(TAG, "wifi_status_generate_ip_info_json done"); -} diff --git a/components/wifi-manager/network_status.cpp b/components/wifi-manager/network_status.cpp new file mode 100644 index 00000000..c4d2f6da --- /dev/null +++ b/components/wifi-manager/network_status.cpp @@ -0,0 +1,194 @@ +#ifdef NETWORK_STATUS_LOG_LEVEL +#define LOG_LOCAL_LEVEL NETWORK_STATUS_LOG_LEVEL +#endif + +#include "network_status.h" +#include +#ifdef CONFIG_BT_ENABLED +#include "bt_app_core.h" +#endif +#include "Config.h" +#include "WifiList.h" +#include "esp_log.h" +#include "lwip/inet.h" +#include "monitor.h" +#include "network_ethernet.h" +#include "network_wifi.h" +#include "platform_esp32.h" +#include "tools.h" +#include "trace.h" +#include "bootstate.h" + +#ifndef CONFIG_SQUEEZELITE_ESP32_RELEASE_URL +#pragma message "Defaulting release url" +#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" +#endif +static const char TAG[] = "network_status"; + +sys_status_data* sys_status = nullptr; + +__attribute__((section(".ext_ram.bss"))) System::PB sys_status_obj("status", &sys_status_data_msg,sizeof(sys_status_data_msg)); + +static void (*chained_notify)(in_addr_t, u16_t, u16_t); +static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport); + +#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX +void network_status_set_static_info() { + ESP_LOGD(TAG, "network_status_set_static_info starting"); + + if (sys_status_obj.Lock()) { + const esp_app_desc_t* desc = esp_ota_get_app_description(); + auto status_obj = sys_status_obj.get(); + status_obj->has_platform = true; + strncpy( + status_obj->platform.project, desc->project_name, sizeof(status_obj->platform.project)); + if (platform->target && strlen(platform->target) > 0) { + if (status_obj->platform.target) { + free(status_obj->platform.target); + } + status_obj->platform.target = strdup_psram(platform->target); + } + strncpy(status_obj->platform.version, desc->version, sizeof(status_obj->platform.version)); + status_obj->platform.recovery = is_recovery_running; + status_obj->platform.depth = 16; +#if DEPTH == 16 || DEPTH == 32 + status_obj->platform.depth = DEPTH; +#endif + status_obj->has_hw = true; + status_obj->hw.supports_jack_inserted = platform->gpios.has_jack &&platform->gpios.jack.pin>=0; + status_obj->hw.supports_spk_fault = platform->gpios.has_spkfault && platform->gpios.spkfault.pin>=0; + status_obj->has_net = true; + status_obj->net.has_wifi = true; + +#ifdef CONFIG_BT_ENABLED + if (platform->has_services && platform->services.has_bt_sink && + platform->services.bt_sink.enabled) { + status_obj->has_bt = true; + } +#endif + ESP_LOGD(TAG, "network_status_set_static_info done"); + sys_status_obj.Unlock(); + } else { + ESP_LOGW(TAG, "Unable to lock status json buffer. "); + } +} + +void init_network_status() { + chained_notify = server_notify; + server_notify = connect_notify; + ESP_LOGD(TAG, "init_network_sys_status->Getting status object"); + sys_status = sys_status_obj.get(); + network_status_set_static_info(); +} + +void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) { + sys_net_server* LMS = &sys_status->LMS; + if (sys_status_obj.Lock()) { + sys_status->has_LMS = true; + strncpy(LMS->ip, inet_ntoa(ip), sizeof(LMS->ip)); + LMS->port = hport; + LMS->cport = cport; + ESP_LOGI(TAG, "LMS IP: %s, hport: %d, cport: %d", LMS->ip, LMS->port, LMS->cport); + sys_status_obj.Unlock(); + } +} + +static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) { + set_lms_server_details(ip, hport, cport); + if (chained_notify) (*chained_notify)(ip, hport, cport); + network_async_update_status(); +} + +void network_status_set_basic_info() { + if (sys_status_obj.Lock()) { + network_t* nm = network_get_state_machine(); + sys_status->hw.jack_inserted = jack_inserted_svc(); + sys_status->hw.spk_fault = spkfault_svc(); + sys_status->hw.batt_voltage = battery_value_svc(); + sys_status->net.wifi.disconnect_count = nm->num_disconnect; + sys_status->net.wifi.avg_conn_time = + nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0; + +#ifdef CONFIG_BT_ENABLED + if (platform->has_services && platform->services.has_bt_sink && + platform->services.bt_sink.enabled) { + sys_status->has_bt = true; + sys_status->bt.bt_status = bt_app_source_get_a2d_state(); + sys_status->bt.bt_media_state = bt_app_source_get_media_state(); + } +#endif + + if (network_ethernet_enabled()) { + sys_status->net.eth_up = network_ethernet_is_up(); + } + ESP_LOGV(TAG, "network_status_get_basic_info done"); + sys_status_obj.Unlock(); + } else { + ESP_LOGW(TAG, "Unable to lock status json buffer. "); + } +} +void network_status_update_address(esp_netif_ip_info_t* ip_info) { + if (sys_status_obj.Lock()) { + sys_status->has_net = true; + sys_status->net.has_ip = true; + strncpy(sys_status->net.ip.ip, ip4addr_ntoa((ip4_addr_t*)&ip_info->ip), + sizeof(sys_status->net.ip.ip)); + strncpy(sys_status->net.ip.netmask, ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask), + sizeof(sys_status->net.ip.netmask)); + strncpy(sys_status->net.ip.gw, ip4addr_ntoa((ip4_addr_t*)&ip_info->gw), + sizeof(sys_status->net.ip.gw)); + sys_status_obj.Unlock(); + } +} +void network_status_update_ip_info(sys_status_reasons update_reason_code) { + ESP_LOGV(TAG, "network_status_update_ip_info called"); + esp_netif_ip_info_t ip_info; + if (sys_status_obj.Lock()) { + /* generate the connection info with success */ + network_status_set_basic_info(); + sys_status->net.updt_reason = update_reason_code; + sys_status->net.wifi.has_connected_sta = false; + sys_status->net.wifi.connected_sta.connected = false; + + ESP_LOGD(TAG, + "Updating ip info with reason code %s. Checking if Wifi interface is connected", + sys_status_reasons_name(update_reason_code)); + if (network_is_interface_connected(network_wifi_get_interface()) || + update_reason_code == sys_status_reasons_R_FAILED_ATTEMPT) { + sys_status->net.interface = sys_status_interfaces_IF_WIFI; + + esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info); + network_status_update_address(&ip_info); + if (!network_wifi_is_ap_mode()) { + /* wifi is active, and associated to an AP */ + wifi_ap_record_t ap; + esp_wifi_sta_get_ap_info(&ap); + WifiList::ToSTAEntry(&ap, sys_status->net.wifi.connected_sta); + sys_status->net.wifi.connected_sta.connected = true; + sys_status->net.has_wifi = true; + sys_status->net.wifi.has_connected_sta = true; + } + } + ESP_LOGD(TAG, "Checking if ethernet interface is connected"); + if (network_is_interface_connected(network_ethernet_get_interface())) { + sys_status->net.interface = sys_status_interfaces_IF_ETHERNET; + esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info); + network_status_update_address(&ip_info); + } + sys_status_obj.Unlock(); + } else { + ESP_LOGW(TAG, "Unable to lock status json buffer. "); + } + ESP_LOGV(TAG, "wifi_status_generate_ip_info_json done"); +} +bool network_status_send_object(httpd_req_t* req) { + try { + auto data = sys_status_obj.Encode(); + httpd_resp_send(req, (const char*)data.data(), data.size()); + return true; + } catch (const std::runtime_error& e) { + std::string errdesc = (std::string("Unable to get status: ") + e.what()); + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, errdesc.c_str()); + } + return false; +} \ No newline at end of file diff --git a/components/wifi-manager/network_status.h b/components/wifi-manager/network_status.h index 10b7bf3d..0ffb82dd 100644 --- a/components/wifi-manager/network_status.h +++ b/components/wifi-manager/network_status.h @@ -1,46 +1,54 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + #pragma once #include "network_manager.h" #include "cJSON.h" -#include "Configurator.h" +#include "PBW.h" +#include "Status.pb.h" +#include "esp_http_server.h" + #ifdef __cplusplus + + +extern System::PB sys_status_obj; + extern "C" { #endif -extern sys_Status status; -char* network_status_alloc_get_ip_info_json(); -/** - * @brief Tries to get access to json buffer mutex. - * - * The HTTP server can try to access the json to serve clients while the wifi manager thread can try - * to update it. These two tasks are synchronized through a mutex. - * - * The mutex is used by both the access point list json and the connection status json.\n - * These two resources should technically have their own mutex but we lose some flexibility to save - * on memory. - * - * This is a simple wrapper around freeRTOS function xSemaphoreTake. - * - * @param xTicksToWait The time in ticks to wait for the semaphore to become available. - * @return true in success, false otherwise. - */ -bool network_status_lock_structure(TickType_t xTicksToWait); -/** - * @brief Releases the json buffer mutex. - */ -void network_status_unlock_structure(); + /** * @brief Generates the connection status json: ssid and IP addresses. * @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful. */ -void network_status_update_ip_info(sys_UPDATE_REASONS update_reason_code); - +void network_status_update_ip_info(sys_status_reasons update_reason_code); +bool network_status_send_object(httpd_req_t* req); void init_network_status(); -void destroy_network_status(); - void network_status_clear_ip(); void network_status_safe_reset_sta_ip(); +extern sys_status_data* sys_status; #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/components/wifi-manager/network_wifi.c b/components/wifi-manager/network_wifi.c deleted file mode 100644 index c9aa3bce..00000000 --- a/components/wifi-manager/network_wifi.c +++ /dev/null @@ -1,960 +0,0 @@ -#ifdef NETWORK_WIFI_LOG_LEVEL -#define LOG_LOCAL_LEVEL NETWORK_WIFI_LOG_LEVEL -#endif -#include "network_wifi.h" -#include "cJSON.h" -#include "dns_server.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_wifi_types.h" -#include "lwip/sockets.h" -#include "messaging.h" -#include "network_status.h" -#include -#pragma message("fixme: search for TODO in the code below") -#include "platform_esp32.h" -#include "tools.h" -#include "trace.h" -#include "accessors.h" -static void network_wifi_event_handler( - void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); -static char* get_disconnect_code_desc(uint8_t reason); -esp_err_t network_wifi_get_blob(void* target, size_t size, const char* key); -static inline const char* ssid_string(const wifi_sta_config_t* sta); -static inline const char* password_string(const wifi_sta_config_t* sta); -static const char* status_file_name = "status.bin"; -#define MAX_CREDENTIALS sizeof(platform->net.credentials) / sizeof(sys_WifiSTAEntry) -static const char TAG[] = "network_wifi"; -esp_netif_t* wifi_netif; -esp_netif_t* wifi_ap_netif; -extern sys_Status status; - -#define UINT_TO_STRING(val) \ - static char loc[sizeof(val) + 1]; \ - memset(loc, 0x00, sizeof(loc)); \ - strlcpy(loc, (char*)val, sizeof(loc)); \ - return loc; - -static inline const char* ssid_string(const wifi_sta_config_t* sta) { UINT_TO_STRING(sta->ssid); } -static inline const char* password_string(const wifi_sta_config_t* sta) { - UINT_TO_STRING(sta->password); -} -static inline const char* ap_ssid_string(const wifi_ap_record_t* ap) { UINT_TO_STRING(ap->ssid); } -bool network_wifi_reset_rssi() { - ESP_LOGD(TAG,"Resetting RSSI"); - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - for (int index = 0; index < platform->net.credentials_count - 1; index++) { - platform->net.credentials[index].rssi = 0; - } - network_status_unlock_structure(); - return true; - } - return false; -} -bool network_wifi_reset_connected() { - ESP_LOGD(TAG,"Resetting Connected"); - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - for (int index = 0; index < platform->net.credentials_count - 1; index++) { - platform->net.credentials[index].connected = false; - } - network_status_unlock_structure(); - return true; - } - return false; -} -void network_wifi_format_bssid(char* buffer, size_t len, const uint8_t* bssid) { - snprintf(buffer, len, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], - bssid[4], bssid[5]); -} -int network_wifi_get_ap_entry_index(const char* ssid) { - for (int i = 0; i < platform->net.credentials_count; i++) { - if (strcmp(platform->net.credentials[i].ssid, ssid) == 0) { - // found the SSID. - return i; - } - } - return -1; -} -sys_WifiSTAEntry * network_wifi_get_ap_entry(const char * ssid){ - sys_WifiSTAEntry * result = NULL; - int index = network_wifi_get_ap_entry_index(ssid); - if(index>=0 && index < platform->net.credentials_count){ - result = &platform->net.credentials[index]; - } - return result; -} -void network_wifi_update_connected(const char * ssid){ - if(!ssid || strlen(ssid) == 0){ - ESP_LOGE(TAG, "Unable to update connected SSID. No ssid received"); - return; - } - sys_WifiSTAEntry * sta = network_wifi_get_ap_entry(ssid); - if (sta && network_status_lock_structure(pdMS_TO_TICKS(1000))) { - sta->connected = true; - network_status_unlock_structure(); - platform->net.has_last_connected = true; - memcpy(&platform->net.last_connected, sta,sizeof(platform->net.last_connected)); - } - -} -size_t network_wifi_get_known_count(){ - size_t result = 0; - for (int i = 0; i < platform->net.credentials_count; i++) { - if(strlen(platform->net.credentials[i].ssid)>0) result ++; - } - return result; - -} - -bool network_wifi_remove_credentials(int index) { - int cur_index = 0; - if (index == -1 || index >= platform->net.credentials_count) { - ESP_LOGW(TAG, "ssid not found or erorr finding SSID"); - return false; - } - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - for (cur_index = index; cur_index < platform->net.credentials_count - 1; cur_index++) { - // Shift following ssid's starting at this slot. - memcpy(&platform->net.credentials[cur_index], &platform->net.credentials[cur_index + 1], - sizeof(sys_WifiSTAEntry)); - } - memset(&platform->net.credentials[cur_index + 1], 0x00, sizeof(sys_WifiSTAEntry)); - platform->net.credentials_count--; - network_status_unlock_structure(); - return true; - } - return false; -} - - -bool network_wifi_remove_ap_entry(const char* ssid) { - int index = network_wifi_get_ap_entry_index(ssid); - return network_wifi_remove_credentials(index); -} - -void network_wifi_sort_last_seen() { - sys_NetworkConfig* config = NULL; - - if (!SYS_NET(config)) return; - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - bool swapped; - do { - swapped = false; - for (int i = 0; i < config->credentials_count - 1; i++) { - if (config->credentials[i].last_seen.seconds < config->credentials[i + 1].last_seen.seconds) { - sys_WifiSTAEntry temp = config->credentials[i]; - config->credentials[i] = config->credentials[i + 1]; - config->credentials[i + 1] = temp; - swapped = true; - } - } - } while (swapped); - network_status_unlock_structure(); - } -} -void network_wifi_sort_strength() { - sys_NetworkConfig* config = platform->has_net ? &platform->net : NULL; - if (!config) return; - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - bool swapped; - do { - swapped = false; - for (int i = 0; i < config->credentials_count - 1; i++) { - if (config->credentials[i].rssi < config->credentials[i + 1].rssi) { - sys_WifiSTAEntry temp = config->credentials[i]; - config->credentials[i] = config->credentials[i + 1]; - config->credentials[i + 1] = temp; - swapped = true; - } - } - } while (swapped); - network_status_unlock_structure(); - } -} -void network_wifi_empty_known_list() { - sys_WifiSTAEntry defaultWifi = sys_WifiSTAEntry_init_default; - sys_NetworkConfig* config = platform->has_net ? &platform->net : NULL; - if (!config) return; - for (int i = 0; i < config->credentials_count - 1; i++) { - memcpy(&config->credentials[i], &defaultWifi, sizeof(config->credentials[i])); - } - config->credentials_count = 0; -} - -const wifi_sta_config_t* network_wifi_get_active_config() { - static wifi_config_t config; - esp_err_t err = ESP_OK; - memset(&config, 0x00, sizeof(config)); - if ((err = esp_wifi_get_config(WIFI_IF_STA, &config)) == ESP_OK) { - return &config.sta; - } else { - ESP_LOGD(TAG, "Could not get wifi STA config: %s", esp_err_to_name(err)); - } - return NULL; -} -sys_WifiSTAEntry* network_wifi_get_free_ssid() { - for (int i = 0; i < MAX_CREDENTIALS; i++) { - if (strlen(platform->net.credentials[i].ssid) == 0) { - return &platform->net.credentials[i]; - } - } - return NULL; -} - -bool network_wifi_add_ap(sys_WifiSTAEntry* item) { - sys_WifiSTAEntry* entry = network_wifi_get_free_ssid(); - if (!entry) { - network_wifi_sort_last_seen(); - network_wifi_remove_credentials(MAX_CREDENTIALS - 1); - platform->net.credentials_count--; - entry = network_wifi_get_free_ssid(); - } - if (!entry) { - ESP_LOGE(TAG, "Unable to find free slot to store wifi"); - return false; - } - memcpy(entry, item, sizeof(sys_WifiSTAEntry)); - platform->net.credentials_count++; - return true; -} - -sys_WifiSTAEntry* network_wifi_get_ssid_info(const char* ssid) { - if (!ssid || strlen(ssid) == 0) return NULL; - for (int i = 0; i < status.net.wifi.scan_result_count; i++) { - if (strcmp(status.net.wifi.scan_result[i].ssid, ssid) == 0) { - return &status.net.wifi.scan_result[i]; - } - } - return NULL; -} - -wifi_auth_mode_t network_wifi_get_auth_mode(sys_WifiAuthTypeEnum auth_type) { - switch (auth_type) { - case sys_WifiAuthTypeEnum_AUTH_OPEN: - return WIFI_AUTH_OPEN; - case sys_WifiAuthTypeEnum_AUTH_WEP: - return WIFI_AUTH_WEP; - case sys_WifiAuthTypeEnum_AUTH_WPA_PSK: - return WIFI_AUTH_WPA_PSK; - case sys_WifiAuthTypeEnum_AUTH_WPA2_PSK: - return WIFI_AUTH_WPA2_PSK; - case sys_WifiAuthTypeEnum_AUTH_WPA_WPA2_PSK: - return WIFI_AUTH_WPA_WPA2_PSK; - case sys_WifiAuthTypeEnum_AUTH_WPA2_ENTERPRISE: - return WIFI_AUTH_WPA2_ENTERPRISE; - case sys_WifiAuthTypeEnum_AUTH_WPA3_PSK: - return WIFI_AUTH_WPA3_PSK; - case sys_WifiAuthTypeEnum_AUTH_WPA2_WPA3_PSK: - return WIFI_AUTH_WPA2_WPA3_PSK; - case sys_WifiAuthTypeEnum_AUTH_WAPI_PSK: - return WIFI_AUTH_WAPI_PSK; - default: - return WIFI_AUTH_OPEN; // Default case - } -} -sys_WifiAuthTypeEnum network_wifi_get_auth_type(const wifi_auth_mode_t mode) { - switch (mode) { - case WIFI_AUTH_OPEN: - return sys_WifiAuthTypeEnum_AUTH_OPEN; - case WIFI_AUTH_WEP: - return sys_WifiAuthTypeEnum_AUTH_WEP; - case WIFI_AUTH_WPA_PSK: - return sys_WifiAuthTypeEnum_AUTH_WPA_PSK; - case WIFI_AUTH_WPA2_PSK: - return sys_WifiAuthTypeEnum_AUTH_WPA2_PSK; - case WIFI_AUTH_WPA_WPA2_PSK: - return sys_WifiAuthTypeEnum_AUTH_WPA_WPA2_PSK; - case WIFI_AUTH_WPA2_ENTERPRISE: - return sys_WifiAuthTypeEnum_AUTH_WPA2_ENTERPRISE; - case WIFI_AUTH_WPA3_PSK: - return sys_WifiAuthTypeEnum_AUTH_WPA3_PSK; - case WIFI_AUTH_WPA2_WPA3_PSK: - return sys_WifiAuthTypeEnum_AUTH_WPA2_WPA3_PSK; - case WIFI_AUTH_WAPI_PSK: - return sys_WifiAuthTypeEnum_AUTH_WAPI_PSK; - case WIFI_AUTH_MAX: - return sys_WifiAuthTypeEnum_AUTH_OPEN; - } - return sys_WifiAuthTypeEnum_AUTH_UNKNOWN; -} - -sys_WifiRadioTypesEnum network_wifi_get_radio_type(const wifi_ap_record_t* sta) { - if (sta == NULL) { - return sys_WifiRadioTypesEnum_PHY_UNKNOWN; - } - - // Check each bit field and return the corresponding enum value - if (sta->phy_11b) { - return sys_WifiRadioTypesEnum_PHY_11B; - } else if (sta->phy_11g) { - return sys_WifiRadioTypesEnum_PHY_11G; - } else if (sta->phy_11n) { - return sys_WifiRadioTypesEnum_PHY_11N; - } else if (sta->phy_lr) { - return sys_WifiRadioTypesEnum_PHY_LR; - } else if (sta->wps) { - return sys_WifiRadioTypesEnum_PHY_WPS; - } else if (sta->ftm_responder) { - return sys_WifiRadioTypesEnum_PHY_FTM_RESPONDER; - } else if (sta->ftm_initiator) { - return sys_WifiRadioTypesEnum_PHY_FTM_INITIATOR; - } - - return sys_WifiRadioTypesEnum_PHY_UNKNOWN; -} -esp_err_t network_wifi_add_update_ap_from_sta_copy(const wifi_sta_config_t* sta) { - esp_err_t err = ESP_OK; - if (!sta) { - ESP_LOGE(TAG, "Invalid access point entry"); - return ESP_ERR_INVALID_ARG; - } - if (!sta->ssid || strlen((char*)sta->ssid) == 0) { - ESP_LOGE(TAG, "Invalid access point ssid"); - return ESP_ERR_INVALID_ARG; - } - sys_WifiSTAEntry item = sys_WifiSTAEntry_init_default; - strncpy(item.ssid, ssid_string(sta), sizeof(item.ssid)); - strncpy(item.password, password_string(sta), sizeof(item.ssid)); - network_wifi_format_bssid(item.bssid, sizeof(item.bssid), sta->bssid); - item.channel = sta->channel; - - sys_WifiSTAEntry* seen = network_wifi_get_ssid_info(item.ssid); - if (seen) { - item.auth_type = seen->auth_type; - item.radio_type = seen->radio_type; - } - err = network_wifi_add_ap(&item); - return err; -} - -bool network_wifi_is_known_ap(const char* ssid) { return network_wifi_get_ap_entry(ssid) != NULL; } - -bool network_wifi_str2mac(const char* mac, uint8_t* values) { - if (6 == sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &values[0], &values[1], &values[2], - &values[3], &values[4], &values[5])) { - return true; - } else { - return false; - } -} - -esp_err_t network_wifi_erase_known_ap() { - network_wifi_empty_known_list(); - return ESP_OK; -} - - -esp_netif_t* network_wifi_get_interface() { return wifi_netif; } -esp_netif_t* network_wifi_get_ap_interface() { return wifi_ap_netif; } -esp_err_t network_wifi_set_sta_mode() { - if (!wifi_netif) { - ESP_LOGE(TAG, "Wifi not initialized. Cannot set sta mode"); - return ESP_ERR_INVALID_STATE; - } - ESP_LOGD(TAG, "Set Mode to STA"); - esp_err_t err = esp_wifi_set_mode(WIFI_MODE_STA); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error setting mode to STA: %s", esp_err_to_name(err)); - } else { - ESP_LOGI(TAG, "Starting wifi"); - err = esp_wifi_start(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error starting wifi: %s", esp_err_to_name(err)); - } - } - return err; -} -esp_netif_t* network_wifi_start() { - MEMTRACE_PRINT_DELTA_MESSAGE("Starting wifi interface as STA mode"); - if (!wifi_netif) { - MEMTRACE_PRINT_DELTA_MESSAGE("Init STA mode - creating default interface. "); - wifi_netif = esp_netif_create_default_wifi_sta(); - MEMTRACE_PRINT_DELTA_MESSAGE("Initializing Wifi. "); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_init(&cfg)); - MEMTRACE_PRINT_DELTA_MESSAGE("Registering wifi Handlers"); - // network_wifi_register_handlers(); - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_instance_register( - WIFI_EVENT, ESP_EVENT_ANY_ID, &network_wifi_event_handler, NULL, NULL)); - MEMTRACE_PRINT_DELTA_MESSAGE("Setting up wifi Storage"); - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - } - MEMTRACE_PRINT_DELTA_MESSAGE("Setting up wifi mode as STA"); - network_wifi_set_sta_mode(); - MEMTRACE_PRINT_DELTA_MESSAGE("Setting hostname"); - network_set_hostname(wifi_netif); - MEMTRACE_PRINT_DELTA_MESSAGE("Done starting wifi interface"); - return wifi_netif; -} -void destroy_network_wifi() { - -} - -bool network_wifi_sta_config_changed() { - bool changed = true; - const wifi_sta_config_t* sta = network_wifi_get_active_config(); - if (!sta || strlen(ssid_string(sta)) == 0) return false; - - sys_WifiSTAEntry* known = network_wifi_get_ap_entry(ssid_string(sta)); - if (known && strcmp(known->ssid, ssid_string(sta)) == 0 && - strcmp((char*)known->password, password_string(sta)) == 0) { - changed = false; - } else { - ESP_LOGI(TAG, "New network configuration found"); - } - return changed; -} - - -static void network_wifi_event_handler( - void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { - if (event_base != WIFI_EVENT) return; - switch (event_id) { - - case WIFI_EVENT_WIFI_READY: - ESP_LOGD(TAG, "WIFI_EVENT_WIFI_READY"); - break; - - case WIFI_EVENT_SCAN_DONE: - ESP_LOGD(TAG, "WIFI_EVENT_SCAN_DONE"); - network_async_scan_done(); - break; - - case WIFI_EVENT_STA_AUTHMODE_CHANGE: - ESP_LOGD(TAG, "WIFI_EVENT_STA_AUTHMODE_CHANGE"); - break; - - case WIFI_EVENT_AP_START: - ESP_LOGD(TAG, "WIFI_EVENT_AP_START"); - break; - - case WIFI_EVENT_AP_STOP: - ESP_LOGD(TAG, "WIFI_EVENT_AP_STOP"); - break; - - case WIFI_EVENT_AP_PROBEREQRECVED: { - wifi_event_ap_probe_req_rx_t* s = (wifi_event_ap_probe_req_rx_t*)event_data; - char* mac = network_manager_alloc_get_mac_string(s->mac); - if (mac) { - ESP_LOGD( - TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s", s->rssi, STR_OR_BLANK(mac)); - } - FREE_AND_NULL(mac); - } break; - case WIFI_EVENT_STA_WPS_ER_SUCCESS: - ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS"); - break; - case WIFI_EVENT_STA_WPS_ER_FAILED: - ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED"); - break; - case WIFI_EVENT_STA_WPS_ER_TIMEOUT: - ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT"); - break; - case WIFI_EVENT_STA_WPS_ER_PIN: - ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_PIN"); - break; - case WIFI_EVENT_AP_STACONNECTED: { - wifi_event_ap_staconnected_t* stac = (wifi_event_ap_staconnected_t*)event_data; - char* mac = network_manager_alloc_get_mac_string(stac->mac); - if (mac) { - ESP_LOGD( - TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s", stac->aid, STR_OR_BLANK(mac)); - } - FREE_AND_NULL(mac); - } break; - case WIFI_EVENT_AP_STADISCONNECTED: - ESP_LOGD(TAG, "WIFI_EVENT_AP_STADISCONNECTED"); - break; - - case WIFI_EVENT_STA_START: - ESP_LOGD(TAG, "WIFI_EVENT_STA_START"); - break; - - case WIFI_EVENT_STA_STOP: - ESP_LOGD(TAG, "WIFI_EVENT_STA_STOP"); - break; - - case WIFI_EVENT_STA_CONNECTED: { - ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. "); - wifi_event_sta_connected_t* s = (wifi_event_sta_connected_t*)event_data; - char* bssid = network_manager_alloc_get_mac_string(s->bssid); - char* ssid = strdup_psram((char*)s->ssid); - if (bssid && ssid) { - ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. Channel: %d, Access point: %s, BSSID: %s ", - s->channel, STR_OR_BLANK(ssid), (bssid)); - network_wifi_update_connected(ssid); - - } - FREE_AND_NULL(bssid); - FREE_AND_NULL(ssid); - network_async(EN_CONNECTED); - - } break; - - case WIFI_EVENT_STA_DISCONNECTED: { - // structwifi_event_sta_disconnected_t - // Argument structure for WIFI_EVENT_STA_DISCONNECTED event - // - // Public Members - // - // uint8_t ssid[32] - // SSID of disconnected AP - // - // uint8_t ssid_len - // SSID length of disconnected AP - // - // uint8_t bssid[6] - // BSSID of disconnected AP - // - // uint8_t reason - // reason of disconnection - wifi_event_sta_disconnected_t* s = (wifi_event_sta_disconnected_t*)event_data; - char* bssid = network_manager_alloc_get_mac_string(s->bssid); - ESP_LOGW(TAG, "WIFI_EVENT_STA_DISCONNECTED. From BSSID: %s, reason code: %d (%s)", - STR_OR_BLANK(bssid), s->reason, get_disconnect_code_desc(s->reason)); - FREE_AND_NULL(bssid); - if (s->reason == WIFI_REASON_ROAMING) { - ESP_LOGI(TAG, "WiFi Roaming to new access point"); - } else { - network_async_lost_connection((wifi_event_sta_disconnected_t*)event_data); - } - } break; - - default: - break; - } -} -void network_wifi_write_file(const char * filename, sys_Status * status_struct){ - FILE* file = open_file("wb", filename); - pb_ostream_t filestream = {&out_file_binding, file, SIZE_MAX, 0}; - ESP_LOGD(TAG, "Starting encode"); - if (!pb_encode(&filestream, sys_Config_fields, (void*)&status)) { - ESP_LOGE(TAG, "Encoding failed: %s\n", PB_GET_ERROR(&filestream)); - } - fclose(file); -} -void network_wifi_global_init() { - pb_istream_t istream =PB_ISTREAM_EMPTY; - ESP_LOGD(TAG, "Loading existing wifi configuration (if any)"); - FILE* file = open_file("rb", status_file_name); - if (!file) { - network_wifi_write_file(status_file_name,&status); - file = open_file("rb", status_file_name); - } - if (!file) { - ESP_LOGE(TAG, "Unable to read status file"); - return; - } - - istream.callback = &in_file_binding; - istream.state = file; - pb_decode(&istream, &sys_Status_msg, &status); - fclose(file); -} - -esp_netif_t* network_wifi_config_ap() { - esp_netif_ip_info_t info; - esp_err_t err = ESP_OK; - wifi_config_t ap_config = { - .ap = {.ssid_len = 0, - .authmode = AP_AUTHMODE, - .ssid_hidden = DEFAULT_AP_SSID_HIDDEN, - .max_connection = DEFAULT_AP_MAX_CONNECTIONS, - .beacon_interval = DEFAULT_AP_BEACON_INTERVAL - - }, - }; - ESP_LOGI(TAG, "Configuring Access Point."); - if (!wifi_ap_netif) { - wifi_ap_netif = esp_netif_create_default_wifi_ap(); - } - if (platform->has_net && platform->net.has_ap && platform->net.ap.has_ip) { - inet_pton(AF_INET, platform->net.ap.ip.ip, - (ip4_addr_t*)&info.ip); /* access point is on a static IP */ - inet_pton(AF_INET, platform->net.ap.ip.gw, - (ip4_addr_t*)&info.gw); /* access point is on a static IP */ - inet_pton(AF_INET, platform->net.ap.ip.netmask, - (ip4_addr_t*)&info.netmask); /* access point is on a static IP */ - } else { - inet_pton( - AF_INET, DEFAULT_AP_IP, (ip4_addr_t*)&info.ip); /* access point is on a static IP */ - inet_pton(AF_INET, CONFIG_DEFAULT_AP_GATEWAY, - (ip4_addr_t*)&info.gw); /* access point is on a static IP */ - inet_pton(AF_INET, CONFIG_DEFAULT_AP_NETMASK, - (ip4_addr_t*)&info.netmask); /* access point is on a st */ - } - - /* In order to change the IP info structure, we have to first stop - * the DHCP server on the new interface - */ - network_start_stop_dhcps(wifi_ap_netif, false); - ESP_LOGD(TAG, "Setting tcp_ip info for access point"); - if ((err = esp_netif_set_ip_info(wifi_ap_netif, &info)) != ESP_OK) { - ESP_LOGE(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s", - esp_err_to_name(err)); - return wifi_ap_netif; - } - network_start_stop_dhcps(wifi_ap_netif, true); - - /* - * Set Access Point configuration - */ - const char* ap_ssid = CONFIG_DEFAULT_AP_SSID; - if (platform->has_names && strlen(platform->names.wifi_ap_name) > 0) { - ap_ssid = platform->names.wifi_ap_name; - } - const char* ap_password = DEFAULT_AP_PASSWORD; - ap_config.ap.channel = CONFIG_DEFAULT_AP_CHANNEL; - if (platform->has_net && platform->net.has_ap) { - if (strlen(platform->net.ap.password) > 0) { - ap_password = platform->net.ap.password; - } - if (platform->net.ap.channel > 0) { - ap_config.ap.channel = platform->net.ap.channel; - } - if (platform->net.ap.auth_mode != sys_WifiAuthTypeEnum_AUTH_UNKNOWN) { - ap_config.ap.authmode = network_wifi_get_auth_mode(platform->net.ap.auth_mode); - } - ap_config.ap.ssid_hidden = platform->net.ap.hidden; - if (platform->net.ap.max_connection > 0) { - ap_config.ap.max_connection = platform->net.ap.max_connection; - } - if (platform->net.ap.beacon_interval > 0) { - ap_config.ap.beacon_interval = platform->net.ap.beacon_interval; - } - } - - strlcpy((char*)ap_config.ap.ssid, ap_ssid, sizeof(ap_config.ap.ssid)); - strlcpy((char*)ap_config.ap.password, ap_password, sizeof(ap_config.ap.password)); - ESP_LOGI(TAG, - "AP SSID: %s, PASSWORD: %s Auth Mode: %d SSID: %s Max Connections: %d Beacon interval: %d", - (char*)ap_config.ap.ssid, (char*)ap_config.ap.password, ap_config.ap.authmode, - ap_config.ap.ssid_hidden ? "HIDDEN" : "VISIBLE", ap_config.ap.max_connection, - ap_config.ap.beacon_interval); - - const char* msg = "Setting wifi mode as WIFI_MODE_APSTA"; - ESP_LOGD(TAG, "%s", msg); - if ((err = esp_wifi_set_mode(WIFI_MODE_APSTA)) != ESP_OK) { - ESP_LOGE(TAG, "%s. Error %s", msg, esp_err_to_name(err)); - return wifi_ap_netif; - } - msg = "Setting wifi AP configuration for WIFI_IF_AP"; - ESP_LOGD(TAG, "%s", msg); - if ((err = esp_wifi_set_config(WIFI_IF_AP, &ap_config)) != ESP_OK) /* stop AP DHCP server */ - { - ESP_LOGE(TAG, "%s . Error %s", msg, esp_err_to_name(err)); - return wifi_ap_netif; - } - - msg = "Setting wifi bandwidth"; - ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_AP_BANDWIDTH); - if ((err = esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH)) != ESP_OK) /* stop AP - DHCP server */ - { - ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); - return wifi_ap_netif; - } - - msg = "Setting wifi power save"; - ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_STA_POWER_SAVE); - - if ((err = esp_wifi_set_ps(DEFAULT_STA_POWER_SAVE)) != ESP_OK) /* stop AP DHCP server */ - { - ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); - return wifi_ap_netif; - } - ESP_LOGD(TAG, "Done configuring Soft Access Point"); - return wifi_ap_netif; -} - -void network_wifi_filter_unique(wifi_ap_record_t* aplist, uint16_t* aps) { - int total_unique; - wifi_ap_record_t* first_free; - total_unique = *aps; - - first_free = NULL; - - for (int i = 0; i < *aps - 1; i++) { - wifi_ap_record_t* ap = &aplist[i]; - - /* skip the previously removed APs */ - if (ap->ssid[0] == 0) continue; - - /* remove the identical SSID+authmodes */ - for (int j = i + 1; j < *aps; j++) { - wifi_ap_record_t* ap1 = &aplist[j]; - if ((strcmp((const char*)ap->ssid, (const char*)ap1->ssid) == 0) && - (ap->authmode == ap1->authmode)) { /* same SSID, different auth mode is skipped */ - /* save the rssi for the display */ - if ((ap1->rssi) > (ap->rssi)) ap->rssi = ap1->rssi; - /* clearing the record */ - memset(ap1, 0, sizeof(wifi_ap_record_t)); - } - } - } - /* reorder the list so APs follow each other in the list */ - for (int i = 0; i < *aps; i++) { - wifi_ap_record_t* ap = &aplist[i]; - /* skipping all that has no name */ - if (ap->ssid[0] == 0) { - /* mark the first free slot */ - if (first_free == NULL) first_free = ap; - total_unique--; - continue; - } - if (first_free != NULL) { - memcpy(first_free, ap, sizeof(wifi_ap_record_t)); - memset(ap, 0, sizeof(wifi_ap_record_t)); - /* find the next free slot */ - for (int j = 0; j < *aps; j++) { - if (aplist[j].ssid[0] == 0) { - first_free = &aplist[j]; - break; - } - } - } - } - /* update the length of the list */ - *aps = total_unique; -} -void network_wifi_clear_scan_results() { - if (!status.net.wifi.scan_result || status.net.wifi.scan_result_count == 0) { - return; - } - free(status.net.wifi.scan_result); - status.net.wifi.scan_result = NULL; - status.net.wifi.scan_result_count = 0; -} -sys_WifiSTAEntry* network_wifi_alloc_scan_results(uint16_t count) { - network_wifi_clear_scan_results(); - status.net.wifi.scan_result = malloc_init_external(count * sizeof(sys_WifiSTAEntry)); - status.net.wifi.scan_result_count = count; - return status.net.wifi.scan_result; -} -void network_wifi_esp_sta_to_sta(wifi_ap_record_t* scan_res, sys_WifiSTAEntry* sta_entry) { - if(!sta_entry){ - return; - } - sta_entry->radio_type = network_wifi_get_radio_type(scan_res); - sta_entry->auth_type = network_wifi_get_auth_type(scan_res->authmode); - network_wifi_format_bssid(sta_entry->bssid, sizeof(sta_entry->bssid), scan_res->bssid); - sta_entry->channel = scan_res->primary; - gettimeofday((struct timeval*)&sta_entry->last_seen, NULL); - sta_entry->rssi = scan_res->rssi; - strncpy(sta_entry->ssid, ap_ssid_string(scan_res), sizeof(sta_entry->ssid)); - // also update any existing credential entry if any - network_wifi_esp_sta_to_sta(scan_res,network_wifi_get_ap_entry(sta_entry->ssid)); -} -bool network_wifi_update_scan_list(wifi_ap_record_t* accessp_records, uint16_t count) { - if (!network_wifi_alloc_scan_results(count)) { - ESP_LOGE(TAG, "Error allocating memory to store scan results"); - return false; - } - // reset RSSI values. This will help when choosing the - // strongest signal to connect to - network_wifi_reset_rssi(); - for (int i = 0; i < status.net.wifi.scan_result_count; i++) { - network_wifi_esp_sta_to_sta(&accessp_records[i], &status.net.wifi.scan_result[i]); - } - network_wifi_sort_strength(); - return true; -} -esp_err_t wifi_scan_done() { - esp_err_t err = ESP_OK; - wifi_ap_record_t* accessp_records = NULL; - /* As input param, it stores max AP number ap_records can hold. As output param, it receives the - * actual AP number this API returns. As a consequence, ap_num MUST be reset to MAX_AP_NUM at - * every scan */ - ESP_LOGD(TAG, "Getting AP list records"); - uint16_t ap_num = MAX_AP_NUM; - if ((err = esp_wifi_scan_get_ap_num(&ap_num)) != ESP_OK) { - ESP_LOGE(TAG, "Failed to retrieve scan results count. Error %s", esp_err_to_name(err)); - return err; - } - if (ap_num <= 0) { - ESP_LOGI(TAG, "No AP found during scan"); - return err; - } - accessp_records = (wifi_ap_record_t*)malloc_init_external(sizeof(wifi_ap_record_t) * ap_num); - if (!accessp_records) { - ESP_LOGE(TAG, "Alloc failed for scan results"); - return ESP_FAIL; - } - if ((err = esp_wifi_scan_get_ap_records(&ap_num, accessp_records)) != ESP_OK) { - ESP_LOGE(TAG, "Failed to retrieve scan results list. Error %s", esp_err_to_name(err)); - } else { - /* make sure the http server isn't trying to access the list while it gets refreshed */ - ESP_LOGD(TAG, "Retrieving scan list"); - /* Will remove the duplicate SSIDs from the list and update ap_num */ - network_wifi_filter_unique(accessp_records, &ap_num); - if (network_status_lock_structure(pdMS_TO_TICKS(1000))) { - network_wifi_update_scan_list(accessp_records, ap_num); - network_status_unlock_structure(); - ESP_LOGD(TAG, "Done retrieving scan list"); - } else { - ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); - err = ESP_FAIL; - } - } - free(accessp_records); - return err; -} -bool is_wifi_up() { return wifi_netif != NULL; } -esp_err_t network_wifi_start_scan() { - wifi_scan_config_t scan_config = {.ssid = 0, - .bssid = 0, - .channel = 0, - .scan_type = WIFI_SCAN_TYPE_ACTIVE, - .show_hidden = true}; - esp_err_t err = ESP_OK; - ESP_LOGI(TAG, "Initiating wifi network scan"); - if (!is_wifi_up()) { - messaging_post_message( - MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot scan"); - return ESP_FAIL; - } - /* if a scan is already in progress this message is simply ignored thanks to the - * WIFI_MANAGER_SCAN_BIT uxBit */ - if ((err = esp_wifi_scan_start(&scan_config, false)) != ESP_OK) { - ESP_LOGW(TAG, "Unable to start scan; %s ", esp_err_to_name(err)); - // set_status_message(WARNING, "Wifi Connecting. Cannot start scan."); - messaging_post_message( - MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Scanning failed: %s", esp_err_to_name(err)); - } - return err; -} - -bool network_wifi_is_ap_mode() { - wifi_mode_t mode; - /* update config to latest and attempt connection */ - return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_AP; -} -bool network_wifi_is_sta_mode() { - wifi_mode_t mode; - /* update config to latest and attempt connection */ - return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_STA; -} -bool network_wifi_is_ap_sta_mode() { - wifi_mode_t mode; - /* update config to latest and attempt connection */ - return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_APSTA; -} - -esp_err_t network_wifi_connect(const char* ssid, const char* password) { - esp_err_t err = ESP_OK; - wifi_config_t config; - memset(&config, 0x00, sizeof(config)); - ESP_LOGD(TAG, "network_wifi_connect"); - network_wifi_reset_connected(); - if (!is_wifi_up()) { - messaging_post_message( - MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot connect"); - return ESP_FAIL; - } - if (!ssid || !password || strlen(ssid) == 0) { - ESP_LOGE(TAG, "Cannot connect wifi. wifi config is null!"); - return ESP_ERR_INVALID_ARG; - } - - wifi_mode_t wifi_mode; - err = esp_wifi_get_mode(&wifi_mode); - if (err == ESP_ERR_WIFI_NOT_INIT) { - ESP_LOGW(TAG, "Wifi not initialized. Attempting to start sta mode"); - network_wifi_start(); - } else if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not retrieve wifi mode : %s", esp_err_to_name(err)); - } else if (wifi_mode != WIFI_MODE_STA && wifi_mode != WIFI_MODE_APSTA) { - ESP_LOGD(TAG, "Changing wifi mode to STA"); - err = network_wifi_set_sta_mode(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Could not set mode to STA. Cannot connect to SSID %s", ssid); - return err; - } - } - // copy configuration and connect - strlcpy((char*)config.sta.ssid, ssid, sizeof(config.sta.ssid)); - if (password) { - strlcpy((char*)config.sta.password, password, sizeof(config.sta.password)); - } - - // First Disconnect - esp_wifi_disconnect(); - - config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; - if ((err = esp_wifi_set_config(WIFI_IF_STA, &config)) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set STA configuration. Error %s", esp_err_to_name(err)); - } - if (err == ESP_OK) { - ESP_LOGI(TAG, "Wifi Connecting to %s...", ssid); - if ((err = esp_wifi_connect()) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initiate wifi connection. Error %s", esp_err_to_name(err)); - } - } - return err; -} - -esp_err_t network_wifi_connect_ssid(const char* ssid) { - sys_WifiSTAEntry* item = network_wifi_get_ssid_info(ssid); - if (item) { - gettimeofday((struct timeval*)&item->last_try, NULL); - return network_wifi_connect(item->ssid, item->password); - } - return ESP_FAIL; -} -esp_err_t network_wifi_connect_active_ssid() { - sys_WifiSTAEntry*connected = NULL; - if(status.has_net && platform->net.has_last_connected && strlen(platform->net.last_connected.ssid)>0){ - connected = &platform->net.last_connected.ssid; - return network_wifi_connect(connected->ssid,connected->password); - } - return ESP_FAIL; -} -void network_wifi_clear_config() { - /* erase configuration */ - const wifi_sta_config_t* sta = network_wifi_get_active_config(); - network_wifi_remove_ap_entry(ssid_string(sta)); - esp_err_t err = ESP_OK; - if ((err = esp_wifi_disconnect()) != ESP_OK) { - ESP_LOGW(TAG, "Could not disconnect from deleted network : %s", esp_err_to_name(err)); - } -} - -char* get_disconnect_code_desc(uint8_t reason) { - switch (reason) { - ENUM_TO_STRING(WIFI_REASON_UNSPECIFIED); - ENUM_TO_STRING(WIFI_REASON_AUTH_EXPIRE); - ENUM_TO_STRING(WIFI_REASON_AUTH_LEAVE); - ENUM_TO_STRING(WIFI_REASON_ASSOC_EXPIRE); - ENUM_TO_STRING(WIFI_REASON_ASSOC_TOOMANY); - ENUM_TO_STRING(WIFI_REASON_NOT_AUTHED); - ENUM_TO_STRING(WIFI_REASON_NOT_ASSOCED); - ENUM_TO_STRING(WIFI_REASON_ASSOC_LEAVE); - ENUM_TO_STRING(WIFI_REASON_ASSOC_NOT_AUTHED); - ENUM_TO_STRING(WIFI_REASON_DISASSOC_PWRCAP_BAD); - ENUM_TO_STRING(WIFI_REASON_DISASSOC_SUPCHAN_BAD); - ENUM_TO_STRING(WIFI_REASON_IE_INVALID); - ENUM_TO_STRING(WIFI_REASON_MIC_FAILURE); - ENUM_TO_STRING(WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT); - ENUM_TO_STRING(WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT); - ENUM_TO_STRING(WIFI_REASON_IE_IN_4WAY_DIFFERS); - ENUM_TO_STRING(WIFI_REASON_GROUP_CIPHER_INVALID); - ENUM_TO_STRING(WIFI_REASON_PAIRWISE_CIPHER_INVALID); - ENUM_TO_STRING(WIFI_REASON_AKMP_INVALID); - ENUM_TO_STRING(WIFI_REASON_UNSUPP_RSN_IE_VERSION); - ENUM_TO_STRING(WIFI_REASON_INVALID_RSN_IE_CAP); - ENUM_TO_STRING(WIFI_REASON_802_1X_AUTH_FAILED); - ENUM_TO_STRING(WIFI_REASON_CIPHER_SUITE_REJECTED); - ENUM_TO_STRING(WIFI_REASON_INVALID_PMKID); - ENUM_TO_STRING(WIFI_REASON_BEACON_TIMEOUT); - ENUM_TO_STRING(WIFI_REASON_NO_AP_FOUND); - ENUM_TO_STRING(WIFI_REASON_AUTH_FAIL); - ENUM_TO_STRING(WIFI_REASON_ASSOC_FAIL); - ENUM_TO_STRING(WIFI_REASON_HANDSHAKE_TIMEOUT); - ENUM_TO_STRING(WIFI_REASON_CONNECTION_FAIL); - ENUM_TO_STRING(WIFI_REASON_AP_TSF_RESET); - ENUM_TO_STRING(WIFI_REASON_ROAMING); - } - return ""; -} diff --git a/components/wifi-manager/network_wifi.cpp b/components/wifi-manager/network_wifi.cpp new file mode 100644 index 00000000..0ddbe5f1 --- /dev/null +++ b/components/wifi-manager/network_wifi.cpp @@ -0,0 +1,805 @@ +#ifdef NETWORK_WIFI_LOG_LEVEL +#define LOG_LOCAL_LEVEL NETWORK_WIFI_LOG_LEVEL +#endif +#include "network_wifi.h" +#include "Config.h" +#include "WifiList.h" +#include "accessors.h" +#include "bootstate.h" +#include "cJSON.h" +#include "dns_server.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_wifi_types.h" +#include "lwip/sockets.h" +#include "messaging.h" +#include "network_status.h" +#include "platform_esp32.h" +#include "tools.h" +#include "trace.h" +#include +#include "esp_sntp.h" + + +WifiList* wifi_config_aps; +EXT_RAM_ATTR WifiList scan_results_aps("scan_results"); + +static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); +static const char* get_disconnect_code_desc(uint8_t reason); +esp_err_t network_wifi_get_blob(void* target, size_t size, const char* key); + +static const char TAG[] = "network_wifi"; +esp_netif_t* wifi_netif; +esp_netif_t* wifi_ap_netif; +extern sys_status_data status; +static void time_sync_notification_cb(struct timeval *tv) +{ + ESP_LOGI(TAG, "Notification of a time synchronization event"); + wifi_config_aps->UpdateFromClock(); + scan_results_aps.UpdateFromClock(); +} +static bool is_initialized() { return (platform != NULL) && platform->has_net; } + +// void network_wifi_update_connected() { +// wifi_config_t config; +// esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); +// if (err != ESP_OK) { +// ESP_LOGE(TAG, "Unable to update connected STA: %s", esp_err_to_name(err)); +// return; +// } + +// auto sta = wifi_config_aps->AddUpdate(&config.sta); +// ESP_LOGD(TAG, "Added/Updated STA %s to credentials list, password: %s", sta.ssid, sta.password); +// wifi_config_aps->PrintWifiSTAEntry(sta); +// if (sys_status_obj.Lock()) { +// sta.connected = true; +// auto status = sys_status_obj.get(); +// status.has_net = true; +// status.net.has_wifi = true; +// memcpy(&status.net.wifi.connected_sta, &sta, sizeof(status.net.wifi.connected_sta)); +// status.net.wifi.has_connected_sta = true; +// sys_status_obj.Unlock(); +// } +// config_raise_changed(false); +// } +size_t network_wifi_get_known_count() { + size_t result = 0; + if (!is_initialized()) { + ESP_LOGE(TAG, "Config not initialized"); + return 0; + } + result = wifi_config_aps->GetCount(); + ESP_LOGD(TAG, "SSID Count from config: %d", result); + + return result; +} + +const wifi_sta_config_t* network_wifi_get_active_config() { + static wifi_config_t config; + esp_err_t err = ESP_OK; + memset(&config, 0x00, sizeof(config)); + if ((err = esp_wifi_get_config(WIFI_IF_STA, &config)) == ESP_OK) { + return &config.sta; + } else { + ESP_LOGD(TAG, "Could not get wifi STA config: %s", esp_err_to_name(err)); + } + return nullptr; +} + +bool network_wifi_is_known_ap(const char* ssid) { return wifi_config_aps->Exists(ssid); } + +esp_netif_t* network_wifi_get_interface() { return wifi_netif; } +esp_netif_t* network_wifi_get_ap_interface() { return wifi_ap_netif; } +esp_err_t network_wifi_set_sta_mode() { + if (!wifi_netif) { + ESP_LOGE(TAG, "Wifi not initialized. Cannot set sta mode"); + return ESP_ERR_INVALID_STATE; + } + ESP_LOGD(TAG, "Set Mode to STA"); + esp_err_t err = esp_wifi_set_mode(WIFI_MODE_STA); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error setting mode to STA: %s", esp_err_to_name(err)); + } else { + ESP_LOGI(TAG, "Starting wifi"); + err = esp_wifi_start(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error starting wifi: %s", esp_err_to_name(err)); + } + } + ESP_LOGD(TAG,"Done setting wifi mode to STA"); + return err; +} +esp_netif_t* network_wifi_start() { + esp_err_t err = ESP_OK; + if (!wifi_netif) { + wifi_netif = esp_netif_create_default_wifi_sta(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + err = esp_wifi_init(&cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error initializing wifi: %s", esp_err_to_name(err)); + return wifi_netif; + } + // network_wifi_register_handlers(); + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &network_wifi_event_handler, NULL, NULL)); + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + } + network_wifi_set_sta_mode(); + network_set_hostname(wifi_netif); + return wifi_netif; +} +void destroy_network_wifi() {} + +bool network_wifi_sta_config_changed() { return wifi_config_aps->Update(network_wifi_get_active_config()); } +esp_err_t network_wifi_set_connected(bool connected) { + wifi_config_t config; + bool state_changed = false; + bool config_changed = false; + ESP_LOGD(TAG, "Resetting connected list"); + if (wifi_config_aps->Lock()) { + wifi_config_aps->ResetConnected(); + wifi_config_aps->Unlock(); + } + ESP_LOGD(TAG, "Erasing connected sta object"); + if (sys_status_obj.get()->net.wifi.has_connected_sta && sys_status_obj.Lock()) { + pb_release(&sys_net_wifi_entry_msg, &sys_status_obj.get()->net.wifi.connected_sta); + sys_status_obj.get()->net.has_wifi = true; + sys_status_obj.get()->has_net = true; + sys_status_obj.get()->net.wifi.has_connected_sta = false; + sys_status_obj.Unlock(); + } + if (stateWrapper.get()->has_connected_sta && stateWrapper.Lock()) { + pb_release(&sys_net_wifi_entry_msg, stateWrapper.get()); + stateWrapper.get()->has_connected_sta = false; + stateWrapper.Unlock(); + state_changed = true; + } + + esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error retrieving wifi config"); + } else { + if (!connected) { + ESP_LOGI(TAG, "Connected list was reset"); + } else { + ESP_LOGI(TAG, "Updating connected sta to %s", WifiList::GetSSID(&config.sta).c_str()); + ESP_LOGD(TAG, "Locking credentials manager"); + if (wifi_config_aps->Lock()) { + ESP_LOGD(TAG, "Adding/updating credentials"); + wifi_config_aps->AddUpdate(&config.sta).connected = true; + ESP_LOGD(TAG, "Unlocking credentials manager"); + config_changed = true; + wifi_config_aps->Unlock(); + } + } + } + if (config_changed) { + ESP_LOGD(TAG, "Raising changed event on the config wrapper object"); + configWrapper.RaiseChangedAsync(); + } + if (state_changed) { + ESP_LOGD(TAG, "Raising changed event on the state wrapper object"); + stateWrapper.RaiseChangedAsync(); + } + return err; +} +static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + if (event_base != WIFI_EVENT) return; + switch (event_id) { + + case WIFI_EVENT_WIFI_READY: + ESP_LOGD(TAG, "WIFI_EVENT_WIFI_READY"); + break; + + case WIFI_EVENT_SCAN_DONE: + ESP_LOGD(TAG, "WIFI_EVENT_SCAN_DONE"); + network_async_scan_done(); + break; + + case WIFI_EVENT_STA_AUTHMODE_CHANGE: + ESP_LOGD(TAG, "WIFI_EVENT_STA_AUTHMODE_CHANGE"); + break; + + case WIFI_EVENT_AP_START: + ESP_LOGD(TAG, "WIFI_EVENT_AP_START"); + break; + + case WIFI_EVENT_AP_STOP: + ESP_LOGD(TAG, "WIFI_EVENT_AP_STOP"); + break; + + case WIFI_EVENT_AP_PROBEREQRECVED: { + wifi_event_ap_probe_req_rx_t* s = (wifi_event_ap_probe_req_rx_t*)event_data; + char* mac = alloc_get_formatted_mac_string(s->mac); + if (mac) { + ESP_LOGD(TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s", s->rssi, STR_OR_BLANK(mac)); + } + FREE_AND_NULL(mac); + } break; + case WIFI_EVENT_STA_WPS_ER_SUCCESS: + ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS"); + break; + case WIFI_EVENT_STA_WPS_ER_FAILED: + ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED"); + break; + case WIFI_EVENT_STA_WPS_ER_TIMEOUT: + ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT"); + break; + case WIFI_EVENT_STA_WPS_ER_PIN: + ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_PIN"); + break; + case WIFI_EVENT_AP_STACONNECTED: { + wifi_event_ap_staconnected_t* stac = (wifi_event_ap_staconnected_t*)event_data; + char* mac = alloc_get_formatted_mac_string(stac->mac); + if (mac) { + ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s", stac->aid, STR_OR_BLANK(mac)); + } + FREE_AND_NULL(mac); + } break; + case WIFI_EVENT_AP_STADISCONNECTED: + ESP_LOGD(TAG, "WIFI_EVENT_AP_STADISCONNECTED"); + break; + + case WIFI_EVENT_STA_START: + ESP_LOGD(TAG, "WIFI_EVENT_STA_START"); + break; + + case WIFI_EVENT_STA_STOP: + ESP_LOGD(TAG, "WIFI_EVENT_STA_STOP"); + break; + + case WIFI_EVENT_STA_CONNECTED: { + ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. "); + network_async(EN_CONNECTED); + + } break; + + case WIFI_EVENT_STA_DISCONNECTED: { + if (is_restarting()) { + ESP_LOGD(TAG, "Disconnect event ignored while restarting"); + return; + } + wifi_event_sta_disconnected_t* s = (wifi_event_sta_disconnected_t*)event_data; + char* bssid = alloc_get_formatted_mac_string(s->bssid); + ESP_LOGW(TAG, "WIFI_EVENT_STA_DISCONNECTED. From BSSID: %s, reason code: %d (%s)", STR_OR_BLANK(bssid), s->reason, + get_disconnect_code_desc(s->reason)); + FREE_AND_NULL(bssid); + + if (s->reason == WIFI_REASON_ROAMING) { + ESP_LOGI(TAG, "WiFi Roaming to new access point"); + } else { + network_async_lost_connection((wifi_event_sta_disconnected_t*)event_data); + network_wifi_set_connected(false); + } + } break; + + default: + break; + } +} + +void network_wifi_global_init() { + ESP_LOGD(TAG, "running network_wifi_global_init"); + assert(platform != nullptr); + wifi_config_aps = reinterpret_cast(platform->net.credentials); + assert(wifi_config_aps != nullptr); + sys_status_obj.get()->has_net = true; + sys_status_obj.get()->net.has_wifi = true; + sys_status_obj.get()->net.wifi.scan_result = reinterpret_cast(&scan_results_aps); + sntp_set_time_sync_notification_cb(time_sync_notification_cb); + +} + +esp_netif_t* network_wifi_config_ap() { + esp_netif_ip_info_t info; + esp_err_t err = ESP_OK; + wifi_config_t ap_config; + memset(&ap_config, 0x00, sizeof(ap_config)); + + ESP_LOGI(TAG, "Configuring Access Point."); + if (!wifi_ap_netif) { + wifi_ap_netif = esp_netif_create_default_wifi_ap(); + } + if (!is_initialized()) { + ESP_LOGE(TAG, "Config not initialized"); + return wifi_ap_netif; + } + if (platform->has_net && platform->net.has_ap && platform->net.ap.has_ip) { + inet_pton(AF_INET, platform->net.ap.ip.ip, (ip4_addr_t*)&info.ip); /* access point is on a static IP */ + inet_pton(AF_INET, platform->net.ap.ip.gw, (ip4_addr_t*)&info.gw); /* access point is on a static IP */ + inet_pton(AF_INET, platform->net.ap.ip.netmask, (ip4_addr_t*)&info.netmask); /* access point is on a static IP */ + } else { + ESP_LOGE(TAG, "Access point not configured. Bailing out"); + return nullptr; + } + ap_config.ap.max_connection = platform->net.ap.max_connection > 0 ? platform->net.ap.max_connection : 4; + ap_config.ap.beacon_interval = platform->net.ap.beacon_interval > 0 ? platform->net.ap.beacon_interval : 100; + ap_config.ap.ssid_hidden = platform->net.ap.hidden; + ap_config.ap.authmode = WifiList::GetESPAuthMode(platform->net.ap.auth_mode); + ap_config.ap.channel = platform->net.ap.channel; + /* In order to change the IP info structure, we have to first stop + * the DHCP server on the new interface + */ + network_start_stop_dhcps(wifi_ap_netif, false); + ESP_LOGD(TAG, "Setting tcp_ip info for access point"); + if ((err = esp_netif_set_ip_info(wifi_ap_netif, &info)) != ESP_OK) { + ESP_LOGE(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s", esp_err_to_name(err)); + return wifi_ap_netif; + } + network_start_stop_dhcps(wifi_ap_netif, true); + + strlcpy((char*)ap_config.ap.ssid, platform->names.wifi_ap_name, sizeof(ap_config.ap.ssid)); + strlcpy((char*)ap_config.ap.password, STR_OR_BLANK(platform->net.ap.password), sizeof(ap_config.ap.password)); + ESP_LOGI(TAG, "AP SSID: %s, PASSWORD: %s Auth Mode: %d SSID: %s Max Connections: %d Beacon interval: %d", (char*)ap_config.ap.ssid, + (char*)ap_config.ap.password, ap_config.ap.authmode, ap_config.ap.ssid_hidden ? "HIDDEN" : "VISIBLE", ap_config.ap.max_connection, + ap_config.ap.beacon_interval); + + const char* msg = "Setting wifi mode as WIFI_MODE_APSTA"; + ESP_LOGD(TAG, "%s", msg); + if ((err = esp_wifi_set_mode(WIFI_MODE_APSTA)) != ESP_OK) { + ESP_LOGE(TAG, "%s. Error %s", msg, esp_err_to_name(err)); + return wifi_ap_netif; + } + msg = "Setting wifi AP configuration for WIFI_IF_AP"; + ESP_LOGD(TAG, "%s", msg); + if ((err = esp_wifi_set_config(WIFI_IF_AP, &ap_config)) != ESP_OK) /* stop AP DHCP server */ + { + ESP_LOGE(TAG, "%s . Error %s", msg, esp_err_to_name(err)); + return wifi_ap_netif; + } + + msg = "Setting wifi bandwidth"; + ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_AP_BANDWIDTH); + if ((err = esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH)) != ESP_OK) /* stop AP + DHCP server */ + { + ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); + return wifi_ap_netif; + } + + msg = "Setting wifi power save"; + ESP_LOGD(TAG, "%s (%s)", msg, sys_net_config_ps_types_name(platform->net.power_save_mode)); + + if ((err = esp_wifi_set_ps((wifi_ps_type_t)platform->net.power_save_mode)) != ESP_OK) /* stop AP DHCP server */ + { + ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); + return wifi_ap_netif; + } + ESP_LOGD(TAG, "Done configuring Soft Access Point"); + return wifi_ap_netif; +} + +void network_wifi_filter_unique(wifi_ap_record_t* aplist, uint16_t* aps) { + int total_unique; + wifi_ap_record_t* first_free; + total_unique = *aps; + + first_free = NULL; + + for (int i = 0; i < *aps - 1; i++) { + wifi_ap_record_t* ap = &aplist[i]; + + /* skip the previously removed APs */ + if (ap->ssid[0] == 0) continue; + + /* remove the identical SSID+authmodes */ + for (int j = i + 1; j < *aps; j++) { + wifi_ap_record_t* ap1 = &aplist[j]; + if ((strcmp((const char*)ap->ssid, (const char*)ap1->ssid) == 0) && + (ap->authmode == ap1->authmode)) { /* same SSID, different auth mode is skipped */ + /* save the rssi for the display */ + if ((ap1->rssi) > (ap->rssi)) ap->rssi = ap1->rssi; + /* clearing the record */ + memset(ap1, 0, sizeof(wifi_ap_record_t)); + } + } + } + /* reorder the list so APs follow each other in the list */ + for (int i = 0; i < *aps; i++) { + wifi_ap_record_t* ap = &aplist[i]; + /* skipping all that has no name */ + if (ap->ssid[0] == 0) { + /* mark the first free slot */ + if (first_free == NULL) first_free = ap; + total_unique--; + continue; + } + if (first_free != NULL) { + memcpy(first_free, ap, sizeof(wifi_ap_record_t)); + memset(ap, 0, sizeof(wifi_ap_record_t)); + /* find the next free slot */ + for (int j = 0; j < *aps; j++) { + if (aplist[j].ssid[0] == 0) { + first_free = &aplist[j]; + break; + } + } + } + } + /* update the length of the list */ + *aps = total_unique; +} + +bool network_wifi_update_scan_list(wifi_ap_record_t* accessp_records, uint16_t count) { + bool changed = false; + // reset RSSI values. This will help when choosing the + // strongest signal to connect to + wifi_config_aps->ResetRSSI(); + // clear current access point list + scan_results_aps.Clear(); + if (count > 0) { + WifiList::PrintWifiSTAEntryTitle(); + ESP_LOGD(TAG, "Found %d AP(s) during scan:",count); + for (int i = 0; i < count; i++) { + auto& entry = scan_results_aps.AddUpdate(&accessp_records[i]); + scan_results_aps.UpdateLastSeen(&accessp_records[i]); + + if (wifi_config_aps->Exists(&accessp_records[i]) && configWrapper.Lock()) { + ESP_LOGD(TAG,"AP with known password. updating last seen"); + changed = wifi_config_aps->Update(&accessp_records[i]) || changed; + changed = wifi_config_aps->UpdateLastSeen(&accessp_records[i]) || changed; + configWrapper.Unlock(); + } + ESP_LOGV(TAG,"Address of entry is %p", static_cast(&entry)); + + if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + WifiList::PrintWifiSTAEntry(entry); + } + } + + } else { + ESP_LOGI(TAG, "No nearby access point found"); + } + if (changed) { + config_raise_changed(false); + } + return true; +} +esp_err_t wifi_scan_done() { + esp_err_t err = ESP_OK; + wifi_ap_record_t* accessp_records = NULL; + ESP_LOGD(TAG, "Getting AP list records"); + uint16_t ap_num = platform->net.max_ap_num; + if ((err = esp_wifi_scan_get_ap_num(&ap_num)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to retrieve scan results count. Error %s", esp_err_to_name(err)); + return err; + } + if (ap_num <= 0) { + ESP_LOGI(TAG, "No AP found during scan"); + return err; + } + accessp_records = (wifi_ap_record_t*)malloc_init_external(sizeof(wifi_ap_record_t) * ap_num); + if (!accessp_records) { + ESP_LOGE(TAG, "Alloc failed for scan results"); + return ESP_FAIL; + } + if ((err = esp_wifi_scan_get_ap_records(&ap_num, accessp_records)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to retrieve scan results list. Error %s", esp_err_to_name(err)); + } else { + /* make sure the http server isn't trying to access the list while it gets refreshed */ + ESP_LOGD(TAG, "Retrieving scan list"); + /* Will remove the duplicate SSIDs from the list and update ap_num */ + network_wifi_filter_unique(accessp_records, &ap_num); + + if (!network_wifi_update_scan_list(accessp_records, ap_num)) { + ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); + err = ESP_FAIL; + } + ESP_LOGD(TAG, "Done retrieving scan list"); + } + free(accessp_records); + return err; +} +bool is_wifi_up() { return wifi_netif != NULL; } +esp_err_t network_wifi_start_scan() { + wifi_scan_config_t scan_config = {.ssid = 0, .bssid = 0, .channel = 0, .show_hidden = true, .scan_type = WIFI_SCAN_TYPE_ACTIVE}; + esp_err_t err = ESP_OK; + ESP_LOGI(TAG, "Initiating wifi network scan"); + if (!is_wifi_up()) { + messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot scan"); + return ESP_FAIL; + } + /* if a scan is already in progress this message is simply ignored thanks to the + * WIFI_MANAGER_SCAN_BIT uxBit */ + if ((err = esp_wifi_scan_start(&scan_config, false)) != ESP_OK) { + ESP_LOGW(TAG, "Unable to start scan; %s ", esp_err_to_name(err)); + // set_status_message(WARNING, "Wifi Connecting. Cannot start scan."); + messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Scanning failed: %s", esp_err_to_name(err)); + } + return err; +} + +bool network_wifi_is_ap_mode() { + wifi_mode_t mode; + /* update config to latest and attempt connection */ + return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_AP; +} +bool network_wifi_is_sta_mode() { + wifi_mode_t mode; + /* update config to latest and attempt connection */ + return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_STA; +} +bool network_wifi_is_ap_sta_mode() { + wifi_mode_t mode; + /* update config to latest and attempt connection */ + return esp_wifi_get_mode(&mode) == ESP_OK && mode == WIFI_MODE_APSTA; +} + +esp_err_t network_wifi_connect(const char* ssid, const char* password) { + esp_err_t err = ESP_OK; + wifi_config_t config; + bool changed = false; + + memset(&config, 0x00, sizeof(config)); + ESP_LOGD(TAG, "network_wifi_connect"); + network_wifi_set_connected(false); + + if (!is_wifi_up()) { + messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot connect"); + return ESP_FAIL; + } + if (!ssid || !password || strlen(ssid) == 0) { + ESP_LOGE(TAG, "Cannot connect wifi. wifi config is null!"); + return ESP_ERR_INVALID_ARG; + } + + wifi_mode_t wifi_mode; + err = esp_wifi_get_mode(&wifi_mode); + if (err == ESP_ERR_WIFI_NOT_INIT) { + ESP_LOGW(TAG, "Wifi not initialized. Attempting to start sta mode"); + network_wifi_start(); + } else if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not retrieve wifi mode : %s", esp_err_to_name(err)); + } else if (wifi_mode != WIFI_MODE_STA && wifi_mode != WIFI_MODE_APSTA) { + ESP_LOGD(TAG, "Changing wifi mode to STA"); + err = network_wifi_set_sta_mode(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not set mode to STA. Cannot connect to SSID %s", ssid); + return err; + } + } + // copy configuration and connect + strlcpy((char*)config.sta.ssid, ssid, sizeof(config.sta.ssid)); + if (password) { + strlcpy((char*)config.sta.password, password, sizeof(config.sta.password)); + } + + config.sta.scan_method = platform->net.wifi_connect_fast_scan ? WIFI_FAST_SCAN : WIFI_ALL_CHANNEL_SCAN; + auto existing = wifi_config_aps->Get(&config.sta); + if (existing != nullptr) { + if (existing->channel > 0 && existing->channel <= 13) { + ESP_LOGD(TAG, "Trying to connect on channel %d", existing->channel); + config.sta.channel = existing->channel; + } else { + ESP_LOGD(TAG, "Access point known, but no channel defined. Scanning"); + } + } + + // First Disconnect + esp_wifi_disconnect(); + + config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; + if ((err = esp_wifi_set_config(WIFI_IF_STA, &config)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set STA configuration. Error %s", esp_err_to_name(err)); + } + if (err == ESP_OK) { + ESP_LOGI(TAG, "Wifi Connecting to %s...", ssid); + if ((err = esp_wifi_connect()) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initiate wifi connection. Error %s", esp_err_to_name(err)); + } else { + if (wifi_config_aps->Lock()) { + ESP_LOGD(TAG, "Storing/updating credentials entry"); + if (wifi_config_aps->Exists(&config.sta)) { + ESP_LOGD(TAG, "Existing entry. Updating it"); + changed = wifi_config_aps->Update(&config.sta); + } else { + ESP_LOGD(TAG, "New entry. Adding it"); + wifi_config_aps->AddUpdate(&config.sta); + } + auto entry = wifi_config_aps->Get(&config.sta); + + if (entry != nullptr) { + wifi_config_aps->UpdateLastTry(&config.sta); + WifiList::PrintWifiSTAEntryTitle(); + WifiList::PrintWifiSTAEntry(*entry); + } + wifi_config_aps->Unlock(); + } + + if (changed) { + configWrapper.RaiseChangedAsync(); + } + } + } + return err; +} + +esp_err_t network_wifi_connect_ssid(const char* ssid) { + sys_net_wifi_entry* item = wifi_config_aps->Get(std::string(ssid)); + if (item != nullptr) { + return network_wifi_connect(item->ssid, item->password); + } else { + ESP_LOGE(TAG, "Attempting to connect to an unknown ssid: %s", ssid); + } + return ESP_FAIL; +} +esp_err_t network_wifi_connect_active_ssid() { + sys_net_wifi_entry* connected = NULL; + if (sys_state->has_connected_sta && strlen(sys_state->connected_sta.ssid) > 0) { + connected = &sys_state->connected_sta; + + if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { + ESP_LOGI(TAG, "Connecting to active access point"); + WifiList::PrintWifiSTAEntryTitle(); + WifiList::PrintWifiSTAEntry(sys_state->connected_sta); + } + return network_wifi_connect(connected->ssid, connected->password); + } + return ESP_ERR_NOT_FOUND; +} +esp_err_t network_wifi_add_ssid(const char* ssid, const char* password) { + bool changed = false; + auto conn = wifi_config_aps->Get(ssid); + if (conn != nullptr) { + ESP_LOGW(TAG, "Existing ssid %s. Updating password", ssid); + if (strcmp(conn->password, password) != 0) { + strncpy(conn->password, password, sizeof(conn->password)); + changed = true; + } else { + ESP_LOGI(TAG, "No change to ssid %s", password); + } + } else { + ESP_LOGI(TAG, "Adding new ssid %s with password %s to credentials", ssid, STR_OR_BLANK(password)); + auto seen = scan_results_aps.Get(ssid); + if (seen) { + ESP_LOGD(TAG,"Adding with extra info from scan"); + wifi_config_aps->AddUpdate(seen, STR_OR_BLANK(password)); + changed = true; + } else { + ESP_LOGD(TAG,"Adding without extra info from scan"); + wifi_config_aps->AddUpdate(ssid, STR_OR_BLANK(password)); + changed = true; + } + } + + if (changed) { + config_raise_changed(false); + } + return ESP_OK; +} +esp_err_t network_wifi_remove_ssid(const char* ssid) { + wifi_config_t config; + + esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error retrieving wifi config"); + } + if ((network_wifi_is_sta_mode() || network_wifi_is_ap_sta_mode()) && WifiList::GetSSID(&config.sta) == ssid) { + ESP_LOGI(TAG, "Disconnecting from deleted ssid: %s", ssid); + esp_wifi_disconnect(); + } + if (wifi_config_aps->RemoveCredential(std::string(ssid))) { + ESP_LOGI(TAG, "SSID %s was removed", ssid); + config_raise_changed(false); + } else { + ESP_LOGI(TAG, "SSID %s could not be removed", ssid); + } + + return ESP_OK; +} +void network_wifi_activate_strongest_ssid() { + sys_state->has_connected_sta = true; + auto strongest = wifi_config_aps->GetStrongestSTA(); + if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + ESP_LOGD(TAG, "Setting strongest AP as active"); + WifiList::PrintWifiSTAEntryTitle(); + WifiList::PrintWifiSTAEntry(strongest); + } + + WifiList::Update(sys_state->connected_sta, strongest); +} +void network_wifi_clear_config() { + /* erase configuration */ + wifi_config_aps->RemoveCredential(network_wifi_get_active_config()); + esp_err_t err = ESP_OK; + if ((err = esp_wifi_disconnect()) != ESP_OK) { + ESP_LOGW(TAG, "Could not disconnect from deleted network : %s", esp_err_to_name(err)); + } +} +void print_wifi_ap_status(const wifi_sta_config_t* ap_status) { + if (ap_status == NULL) { + printf("AP status is NULL\n"); + return; + } + + printf("SSID: %s\n", ap_status->ssid); + printf("Password: %s\n", ap_status->password); + + const char* scan_method = (ap_status->scan_method == WIFI_FAST_SCAN) ? "Fast Scan" : "All Channel Scan"; + printf("Scan Method: %s\n", scan_method); + + printf("BSSID Set: %s\n", ap_status->bssid_set ? "Yes" : "No"); + printf("BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", ap_status->bssid[0], ap_status->bssid[1], ap_status->bssid[2], ap_status->bssid[3], + ap_status->bssid[4], ap_status->bssid[5]); + + printf("Channel: %d\n", ap_status->channel); + printf("Listen Interval: %d\n", ap_status->listen_interval); + + const char* sort_method = (ap_status->sort_method == WIFI_CONNECT_AP_BY_SIGNAL) ? "By Signal" : "By Security"; + printf("Sort Method: %s\n", sort_method); + + printf("RSSI Threshold: %d\n", ap_status->threshold.rssi); + printf("Auth Mode Threshold: %d\n", ap_status->threshold.authmode); + + printf("PMF Capable: %s\n", ap_status->pmf_cfg.capable ? "Yes" : "No"); + printf("PMF Required: %s\n", ap_status->pmf_cfg.required ? "Yes" : "No"); + + // Add other fields as needed +} +void network_wifi_get_status() { + wifi_config_t config; + esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); + if (err == ESP_OK) { + print_wifi_ap_status(&config.sta); + } else { + ESP_LOGE(TAG, "Error getting wifi status: %s", esp_err_to_name(err)); + } + if (wifi_config_aps->GetCount() > 0 || scan_results_aps.GetCount() > 0) { + WifiList::PrintWifiSTAEntryTitle(); + } + ESP_LOGI(TAG, "Known access points:"); + for (int i = 0; i < wifi_config_aps->GetCount(); i++) { + const auto entry = wifi_config_aps->GetIndex(i); + if (entry != nullptr) { + WifiList::PrintWifiSTAEntry(*entry); + } + } + if (scan_results_aps.GetCount() > 0) { + ESP_LOGI(TAG, "List of nearby access points"); + for (int i = 0; i < scan_results_aps.GetCount(); i++) { + const auto entry = scan_results_aps.GetIndex(i); + if (entry != nullptr) { + WifiList::PrintWifiSTAEntry(*entry); + } + } + } +} + +const char* get_disconnect_code_desc(uint8_t reason) { + switch (reason) { + ENUM_TO_STRING(WIFI_REASON_UNSPECIFIED); + ENUM_TO_STRING(WIFI_REASON_AUTH_EXPIRE); + ENUM_TO_STRING(WIFI_REASON_AUTH_LEAVE); + ENUM_TO_STRING(WIFI_REASON_ASSOC_EXPIRE); + ENUM_TO_STRING(WIFI_REASON_ASSOC_TOOMANY); + ENUM_TO_STRING(WIFI_REASON_NOT_AUTHED); + ENUM_TO_STRING(WIFI_REASON_NOT_ASSOCED); + ENUM_TO_STRING(WIFI_REASON_ASSOC_LEAVE); + ENUM_TO_STRING(WIFI_REASON_ASSOC_NOT_AUTHED); + ENUM_TO_STRING(WIFI_REASON_DISASSOC_PWRCAP_BAD); + ENUM_TO_STRING(WIFI_REASON_DISASSOC_SUPCHAN_BAD); + ENUM_TO_STRING(WIFI_REASON_IE_INVALID); + ENUM_TO_STRING(WIFI_REASON_MIC_FAILURE); + ENUM_TO_STRING(WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT); + ENUM_TO_STRING(WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT); + ENUM_TO_STRING(WIFI_REASON_IE_IN_4WAY_DIFFERS); + ENUM_TO_STRING(WIFI_REASON_GROUP_CIPHER_INVALID); + ENUM_TO_STRING(WIFI_REASON_PAIRWISE_CIPHER_INVALID); + ENUM_TO_STRING(WIFI_REASON_AKMP_INVALID); + ENUM_TO_STRING(WIFI_REASON_UNSUPP_RSN_IE_VERSION); + ENUM_TO_STRING(WIFI_REASON_INVALID_RSN_IE_CAP); + ENUM_TO_STRING(WIFI_REASON_802_1X_AUTH_FAILED); + ENUM_TO_STRING(WIFI_REASON_CIPHER_SUITE_REJECTED); + ENUM_TO_STRING(WIFI_REASON_INVALID_PMKID); + ENUM_TO_STRING(WIFI_REASON_BEACON_TIMEOUT); + ENUM_TO_STRING(WIFI_REASON_NO_AP_FOUND); + ENUM_TO_STRING(WIFI_REASON_AUTH_FAIL); + ENUM_TO_STRING(WIFI_REASON_ASSOC_FAIL); + ENUM_TO_STRING(WIFI_REASON_HANDSHAKE_TIMEOUT); + ENUM_TO_STRING(WIFI_REASON_CONNECTION_FAIL); + ENUM_TO_STRING(WIFI_REASON_AP_TSF_RESET); + ENUM_TO_STRING(WIFI_REASON_ROAMING); + } + return ""; +} diff --git a/components/wifi-manager/network_wifi.h b/components/wifi-manager/network_wifi.h index f0d742db..71e96d59 100644 --- a/components/wifi-manager/network_wifi.h +++ b/components/wifi-manager/network_wifi.h @@ -1,12 +1,36 @@ +/* + * + * Sebastien L. 2023, sle118@hotmail.com + * Philippe G. 2023, philippe_44@outlook.com + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + * + * License Overview: + * ---------------- + * The MIT License is a permissive open source license. As a user of this software, you are free to: + * - Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. + * - Use the software for private, commercial, or any other purposes. + * + * Conditions: + * - You must include the above copyright notice and this permission notice in all + * copies or substantial portions of the Software. + * + * The MIT License offers a high degree of freedom and is well-suited for both open source and + * commercial applications. It places minimal restrictions on how the software can be used, + * modified, and redistributed. For more details on the MIT License, please refer to the link above. + */ + #pragma once #include "network_manager.h" -#include "Configurator.h" +#include "Config.h" #ifdef __cplusplus extern "C" { #endif esp_netif_t * network_wifi_start(); void destroy_network_wifi(); +esp_err_t network_wifi_set_connected(bool connected); /** * @brief Registers handler for wifi and ip events @@ -32,8 +56,10 @@ esp_err_t network_wifi_disconnected(queue_message *msg); esp_err_t network_wifi_start_ap(queue_message *msg); esp_err_t network_wifi_handle_event(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); bool is_wifi_up(); -wifi_config_t* network_wifi_set_wifi_sta_config(const char * ssid, const char * password) ; +void network_wifi_get_status(); +esp_err_t network_wifi_add_ssid(const char* ssid, const char* password); void network_wifi_clear_config(); +void network_wifi_get_status(); esp_netif_t *network_wifi_get_interface(); esp_netif_t *network_wifi_get_ap_interface(); bool network_wifi_is_ap_sta_mode(); @@ -43,16 +69,13 @@ bool network_wifi_sta_config_changed(); void network_wifi_global_init(); bool network_wifi_is_known_ap(const char * ssid); esp_err_t network_wifi_connect(const char * ssid, const char * password); -esp_err_t network_wifi_erase_legacy(); esp_err_t network_wifi_connect_ssid(const char * ssid); esp_err_t network_wifi_connect_active_ssid(); -esp_err_t network_wifi_erase_known_ap(); +esp_err_t network_wifi_remove_ssid(const char * ssid); esp_err_t network_wifi_set_sta_mode(); size_t network_wifi_get_known_count(); -size_t network_wifi_get_known_count_in_range(); -esp_err_t network_wifi_connect_next_in_range(); -void network_wifi_esp_sta_to_sta(wifi_ap_record_t* scan_res, sys_WifiSTAEntry* sta_entry); -sys_WifiAuthTypeEnum network_wifi_get_auth_type(const wifi_auth_mode_t mode) ; +void network_wifi_activate_strongest_ssid(); +sys_net_auth_types network_wifi_get_auth_type(const wifi_auth_mode_t mode) ; #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/css/index.css b/components/wifi-manager/webapp/dist/css/index.css new file mode 100644 index 00000000..77964fef --- /dev/null +++ b/components/wifi-manager/webapp/dist/css/index.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v5.3.2 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg,hsla(0,0%,100%,.15),hsla(0,0%,100%,0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33,37,41,.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33,37,41,.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0,0,0,.175);--bs-border-radius:.375rem;--bs-border-radius-sm:.25rem;--bs-border-radius-lg:.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0,0,0,.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0,0,0,.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0,0,0,.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0,0,0,.075);--bs-focus-ring-width:.25rem;--bs-focus-ring-opacity:.25;--bs-focus-ring-color:rgba(13,110,253,.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}*,:after,:before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);background-color:var(--bs-body-bg);color:var(--bs-body-color);font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);margin:0;text-align:var(--bs-body-text-align)}.h1,.h2,.h3,.h4,.h5,h1,h2,h3,h4,h5{color:var(--bs-heading-color);font-weight:500;line-height:1.2;margin-bottom:.5rem;margin-top:0}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}p{margin-top:0}address,p{margin-bottom:1rem}address{font-style:normal;line-height:inherit}ul{margin-bottom:1rem;margin-top:0;padding-left:2rem}ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}b,strong{font-weight:bolder}.small,small{font-size:.875em}sub{bottom:-.25em;font-size:.75em;line-height:0;position:relative;vertical-align:baseline}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}svg{vertical-align:middle}table{border-collapse:collapse;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,th,thead,tr{border:0 solid;border-color:inherit}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,select{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{border-style:none;padding:0}fieldset{border:0;margin:0;min-width:0;padding:0}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{-webkit-appearance:button;font:inherit}output{display:inline-block}progress{vertical-align:baseline}[hidden]{display:none!important}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-left:calc(var(--bs-gutter-x)*-.5);margin-right:calc(var(--bs-gutter-x)*-.5);margin-top:calc(var(--bs-gutter-y)*-1)}.row>*{flex-shrink:0;margin-top:var(--bs-gutter-y);max-width:100%;padding-left:calc(var(--bs-gutter-x)*.5);padding-right:calc(var(--bs-gutter-x)*.5);width:100%}.col{flex:1 0 0%}.col-auto{flex:0 0 auto;width:auto}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb),0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb),0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb),0.075);border-color:var(--bs-table-border-color);margin-bottom:1rem;vertical-align:top;width:100%}.table>:not(caption)>*>*{background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)));color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));padding:.5rem}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#a6b5cc;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000}.table-primary,.table-secondary{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#b5b6b7;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#a7b9b1;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000}.table-success,.table-warning{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#ccc2a4;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#c6acae;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000}.table-danger,.table-light{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#4d5154;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + var(--bs-border-width));padding-top:calc(.375rem + var(--bs-border-width))}.form-text{color:var(--bs-secondary-color);font-size:.875em;margin-top:.25rem}.form-control{appearance:none;background-clip:padding-box;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);color:var(--bs-body-color);display:block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{background-color:var(--bs-body-bg);border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);color:var(--bs-body-color);outline:0}.form-control::-webkit-date-and-time-value{height:1.5em;margin:0;min-width:85px}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::file-selector-button{background-color:var(--bs-tertiary-bg);border:0 solid;border-color:inherit;border-inline-end-width:var(--bs-border-width);border-radius:0;color:var(--bs-body-color);margin:-.375rem -.75rem;margin-inline-end:.75rem;padding:.375rem .75rem;pointer-events:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-sm{border-radius:var(--bs-border-radius-sm);font-size:.875rem;min-height:calc(1.5em + .5rem + var(--bs-border-width)*2);padding:.25rem .5rem}.form-control-sm::file-selector-button{margin:-.25rem -.5rem;margin-inline-end:.5rem;padding:.25rem .5rem}.form-check{display:block;margin-bottom:.125rem;min-height:1.5rem;padding-left:1.5em}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-position:50%;background-repeat:no-repeat;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);flex-shrink:0;height:1em;margin-top:.25em;print-color-adjust:exact;vertical-align:top;width:1em}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3E%3C/svg%3E")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2' fill='%23fff'/%3E%3C/svg%3E")}.form-check-input[type=checkbox]:indeterminate{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3E%3C/svg%3E");background-color:#0d6efd;border-color:#0d6efd}.form-check-input:disabled{filter:none;opacity:.5;pointer-events:none}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-check-inline{display:inline-block;margin-right:1rem}.form-control.is-valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem)}.form-control.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid,.form-control.is-valid:focus{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label{color:var(--bs-form-valid-color)}.invalid-feedback{color:var(--bs-form-invalid-color);display:none;font-size:.875em;margin-top:.25rem;width:100%}.is-invalid~.invalid-feedback{display:block}.form-control.is-invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem)}.form-control.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid,.form-control.is-invalid:focus{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.btn{--bs-btn-padding-x:.75rem;--bs-btn-padding-y:.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.15),0 1px 1px rgba(0,0,0,.075);--bs-btn-disabled-opacity:.65;--bs-btn-focus-box-shadow:0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb),.5);background-color:var(--bs-btn-bg);border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);color:var(--bs-btn-color);cursor:pointer;display:inline-block;font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;user-select:none;vertical-align:middle}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);color:var(--bs-btn-hover-color)}.btn:focus-visible{background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);box-shadow:var(--bs-btn-focus-box-shadow);color:var(--bs-btn-hover-color);outline:0}.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color);color:var(--bs-btn-active-color)}.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);color:var(--bs-btn-disabled-color);opacity:var(--bs-btn-disabled-opacity);pointer-events:none}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-sm{--bs-btn-padding-y:.25rem;--bs-btn-padding-x:.5rem;--bs-btn-font-size:.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.dropdown-divider{border-top:1px solid var(--bs-dropdown-divider-bg);height:0;margin:var(--bs-dropdown-divider-margin-y) 0;opacity:1;overflow:hidden}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{background:none;border:0;color:var(--bs-nav-link-color);display:block;font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);cursor:default;pointer-events:none}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb),0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb),0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb),0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-brand-padding-y:.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-nav-link-padding-x:.5rem;--bs-navbar-toggler-padding-y:.25rem;--bs-navbar-toggler-padding-x:.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(33,37,41,0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb),0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x);position:relative}.navbar-brand{color:var(--bs-navbar-brand-color);font-size:var(--bs-navbar-brand-font-size);margin-right:var(--bs-navbar-brand-margin-end);padding-bottom:var(--bs-navbar-brand-padding-y);padding-top:var(--bs-navbar-brand-padding-y);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);color:var(--bs-navbar-color);font-size:var(--bs-navbar-toggler-font-size);line-height:1;padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width);outline:0;text-decoration:none}.navbar-toggler-icon{background-image:var(--bs-navbar-toggler-icon-bg);background-position:50%;background-repeat:no-repeat;background-size:100%;display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .nav-link{padding-left:var(--bs-navbar-nav-link-padding-x);padding-right:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}.navbar-dark{--bs-navbar-color:hsla(0,0%,100%,.55);--bs-navbar-hover-color:hsla(0,0%,100%,.75);--bs-navbar-disabled-color:hsla(0,0%,100%,.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:hsla(0,0%,100%,.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(255,255,255,0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-card-cap-padding-y:.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb),0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:.75rem;word-wrap:break-word;background-clip:border-box;background-color:var(--bs-card-bg);border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius);color:var(--bs-body-color);display:flex;flex-direction:column;height:var(--bs-card-height);min-width:0;position:relative}.card-body{color:var(--bs-card-color);flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x)}.card-header{background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color);color:var(--bs-card-cap-color);margin-bottom:0;padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.badge{--bs-badge-padding-x:.65em;--bs-badge-padding-y:.35em;--bs-badge-font-size:.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);border-radius:var(--bs-badge-border-radius);color:var(--bs-badge-color);display:inline-block;font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);text-align:center;vertical-align:baseline;white-space:nowrap}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius);color:var(--bs-alert-color);margin-bottom:var(--bs-alert-margin-bottom);padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);position:relative}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{--bs-progress-height:1rem;--bs-progress-font-size:.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius);font-size:var(--bs-progress-font-size);height:var(--bs-progress-height)}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:var(--bs-progress-bar-bg);color:var(--bs-progress-bar-color);flex-direction:column;justify-content:center;text-align:center;transition:var(--bs-progress-bar-transition);white-space:nowrap}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3E%3C/svg%3E");--bs-btn-close-opacity:.5;--bs-btn-close-hover-opacity:.75;--bs-btn-close-focus-shadow:0 0 0 .25rem rgba(13,110,253,.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:.25;--bs-btn-close-white-filter:invert(1) grayscale(100%) brightness(200%);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;box-sizing:content-box;height:1em;opacity:var(--bs-btn-close-opacity);padding:.25em;width:1em}.btn-close,.btn-close:hover{color:var(--bs-btn-close-color)}.btn-close:hover{opacity:var(--bs-btn-close-hover-opacity);text-decoration:none}.btn-close:focus{box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity);outline:0}.btn-close.disabled,.btn-close:disabled{opacity:var(--bs-btn-close-disabled-opacity);pointer-events:none;user-select:none}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:.75rem;--bs-toast-padding-y:.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);background-clip:padding-box;background-color:var(--bs-toast-bg);border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);border-radius:var(--bs-toast-border-radius);box-shadow:var(--bs-toast-box-shadow);color:var(--bs-toast-color);font-size:var(--bs-toast-font-size);max-width:100%;pointer-events:auto;width:var(--bs-toast-max-width)}.toast:not(.show){display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:var(--bs-toast-header-bg);border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));color:var(--bs-toast-header-color);display:flex;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x)}.toast-header .btn-close{margin-left:var(--bs-toast-padding-x);margin-right:calc(var(--bs-toast-padding-x)*-.5)}.toast-body{word-wrap:break-word;padding:var(--bs-toast-padding-x)}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:.5rem;--bs-modal-color: ;--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);display:none;height:100%;left:0;outline:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:0;width:100%;z-index:var(--bs-modal-zindex)}.modal-dialog{margin:var(--bs-modal-margin);pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{background-clip:padding-box;background-color:var(--bs-modal-bg);border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);color:var(--bs-modal-color);display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-header{align-items:center;border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--bs-modal-header-padding)}.modal-header .btn-close{margin:calc(var(--bs-modal-header-padding-y)*-.5) calc(var(--bs-modal-header-padding-x)*-.5) calc(var(--bs-modal-header-padding-y)*-.5) auto;padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5)}.modal-title{line-height:var(--bs-modal-title-line-height);margin-bottom:0}.modal-body{flex:1 1 auto;padding:var(--bs-modal-padding);position:relative}.modal-footer{align-items:center;background-color:var(--bs-modal-footer-bg);border-bottom-left-radius:var(--bs-modal-inner-border-radius);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{margin-left:auto;margin-right:auto;max-width:var(--bs-modal-width)}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:.5rem;--bs-tooltip-padding-y:.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:.9;--bs-tooltip-arrow-width:.8rem;--bs-tooltip-arrow-height:.4rem;word-wrap:break-word;display:block;font-family:var(--bs-font-sans-serif);font-size:var(--bs-tooltip-font-size);font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:var(--bs-tooltip-margin);opacity:0;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:var(--bs-tooltip-zindex)}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.spinner-border{animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name);border-radius:50%;display:inline-block;height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);width:var(--bs-spinner-width)}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-.125em;--bs-spinner-border-width:.25em;--bs-spinner-animation-speed:.75s;--bs-spinner-animation-name:spinner-border;border-right-color:currentcolor;border:var(--bs-spinner-border-width) solid;border-right:var(--bs-spinner-border-width) solid transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.spinner-border{--bs-spinner-animation-speed:1.5s}}.placeholder{background-color:currentcolor;cursor:wait;display:inline-block;min-height:1em;opacity:.5;vertical-align:middle}.placeholder.btn:before{content:"";display:inline-block}@keyframes placeholder-glow{50%{opacity:.2}}@keyframes placeholder-wave{to{mask-position:-200% 0}}.fixed-bottom{bottom:0;left:0;position:fixed;right:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.d-flex{display:flex!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.flex-column{flex-direction:column!important}.justify-content-between{justify-content:space-between!important}.mt-1{margin-top:.25rem!important}.mb-3{margin-bottom:1rem!important}.p-3{padding:1rem!important}.pt-0{padding-top:0!important}.pb-0{padding-bottom:0!important}.text-center{text-align:center!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.visible{visibility:visible!important}body{min-height:100vh}.border-bottom,.border-top{border-width:3px!important}.rebooting,tr.hide{display:none}td.value{width:80%} \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/css/index.css.gz b/components/wifi-manager/webapp/dist/css/index.css.gz new file mode 100644 index 0000000000000000000000000000000000000000..2ad26ebadcf5e476181f0a0da5faef0d1565aa32 GIT binary patch literal 8583 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 N@;}!NA7h}P008e8k}LoK literal 0 HcmV?d00001 diff --git a/components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css b/components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css deleted file mode 100644 index 60cf410a..00000000 --- a/components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v5.3.2 (https://getbootstrap.com/) - * Copyright 2011-2023 The Bootstrap Authors - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg,hsla(0,0%,100%,.15),hsla(0,0%,100%,0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33,37,41,.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33,37,41,.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0,0,0,.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0,0,0,.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0,0,0,.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0,0,0,.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0,0,0,.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(13,110,253,.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}*,:after,:before{box-sizing:border-box}@media(prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);background-color:var(--bs-body-bg);color:var(--bs-body-color);font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);margin:0;text-align:var(--bs-body-text-align)}.h1,.h2,.h3,.h4,.h5,h1,h2,h3,h4,h5{color:var(--bs-heading-color);font-weight:500;line-height:1.2;margin-bottom:.5rem;margin-top:0}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media(min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media(min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media(min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media(min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}p{margin-top:0}address,p{margin-bottom:1rem}address{font-style:normal;line-height:inherit}ul{margin-bottom:1rem;margin-top:0;padding-left:2rem}ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}b,strong{font-weight:bolder}.small,small{font-size:.875em}sub{bottom:-.25em;font-size:.75em;line-height:0;position:relative;vertical-align:baseline}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}svg{vertical-align:middle}table{border-collapse:collapse;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,th,thead,tr{border:0 solid;border-color:inherit}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,select{font-family:inherit;font-size:inherit;line-height:inherit;margin:0}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{border-style:none;padding:0}fieldset{border:0;margin:0;min-width:0;padding:0}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{-webkit-appearance:button;font:inherit}output{display:inline-block}progress{vertical-align:baseline}[hidden]{display:none!important}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-left:calc(var(--bs-gutter-x)*-.5);margin-right:calc(var(--bs-gutter-x)*-.5);margin-top:calc(var(--bs-gutter-y)*-1)}.row>*{flex-shrink:0;margin-top:var(--bs-gutter-y);max-width:100%;padding-left:calc(var(--bs-gutter-x)*.5);padding-right:calc(var(--bs-gutter-x)*.5);width:100%}.col{flex:1 0 0%}.col-auto{flex:0 0 auto;width:auto}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb),0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb),0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb),0.075);border-color:var(--bs-table-border-color);margin-bottom:1rem;vertical-align:top;width:100%}.table>:not(caption)>*>*{background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)));color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));padding:.5rem}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#a6b5cc;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000}.table-primary,.table-secondary{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#b5b6b7;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#a7b9b1;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000}.table-success,.table-warning{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#ccc2a4;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#c6acae;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000}.table-danger,.table-light{border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#4d5154;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;border-color:var(--bs-table-border-color);color:var(--bs-table-color)}.col-form-label{font-size:inherit;line-height:1.5;margin-bottom:0;padding-bottom:calc(.375rem + var(--bs-border-width));padding-top:calc(.375rem + var(--bs-border-width))}.form-text{color:var(--bs-secondary-color);font-size:.875em;margin-top:.25rem}.form-control{appearance:none;background-clip:padding-box;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);color:var(--bs-body-color);display:block;font-size:1rem;font-weight:400;line-height:1.5;padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}@media(prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{background-color:var(--bs-body-bg);border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);color:var(--bs-body-color);outline:0}.form-control::-webkit-date-and-time-value{height:1.5em;margin:0;min-width:85px}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::file-selector-button{background-color:var(--bs-tertiary-bg);border:0 solid;border-color:inherit;border-inline-end-width:var(--bs-border-width);border-radius:0;color:var(--bs-body-color);margin:-.375rem -.75rem;margin-inline-end:.75rem;padding:.375rem .75rem;pointer-events:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-sm{border-radius:var(--bs-border-radius-sm);font-size:.875rem;min-height:calc(1.5em + .5rem + var(--bs-border-width)*2);padding:.25rem .5rem}.form-control-sm::file-selector-button{margin:-.25rem -.5rem;margin-inline-end:.5rem;padding:.25rem .5rem}.form-check{display:block;margin-bottom:.125rem;min-height:1.5rem;padding-left:1.5em}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-position:50%;background-repeat:no-repeat;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);flex-shrink:0;height:1em;margin-top:.25em;print-color-adjust:exact;vertical-align:top;width:1em}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3E%3C/svg%3E")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2' fill='%23fff'/%3E%3C/svg%3E")}.form-check-input[type=checkbox]:indeterminate{--bs-form-check-bg-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3E%3C/svg%3E");background-color:#0d6efd;border-color:#0d6efd}.form-check-input:disabled{filter:none;opacity:.5;pointer-events:none}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-check-inline{display:inline-block;margin-right:1rem}.form-control.is-valid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem)}.form-control.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid,.form-control.is-valid:focus{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label{color:var(--bs-form-valid-color)}.invalid-feedback{color:var(--bs-form-invalid-color);display:none;font-size:.875em;margin-top:.25rem;width:100%}.is-invalid~.invalid-feedback{display:block}.form-control.is-invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-position:right calc(.375em + .1875rem) center;background-repeat:no-repeat;background-size:calc(.75em + .375rem) calc(.75em + .375rem);border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem)}.form-control.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid,.form-control.is-invalid:focus{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.15),0 1px 1px rgba(0,0,0,.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb),.5);background-color:var(--bs-btn-bg);border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);color:var(--bs-btn-color);cursor:pointer;display:inline-block;font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;user-select:none;vertical-align:middle}@media(prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);color:var(--bs-btn-hover-color)}.btn:focus-visible{background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);box-shadow:var(--bs-btn-focus-box-shadow);color:var(--bs-btn-hover-color);outline:0}.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color);color:var(--bs-btn-active-color)}.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);color:var(--bs-btn-disabled-color);opacity:var(--bs-btn-disabled-opacity);pointer-events:none}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0,0,0,.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.dropdown-divider{border-top:1px solid var(--bs-dropdown-divider-bg);height:0;margin:var(--bs-dropdown-divider-margin-y) 0;opacity:1;overflow:hidden}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;list-style:none;margin-bottom:0;padding-left:0}.nav-link{background:none;border:0;color:var(--bs-nav-link-color);display:block;font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{box-shadow:0 0 0 .25rem rgba(13,110,253,.25);outline:0}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);cursor:default;pointer-events:none}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb),0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb),0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb),0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb),1);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(33, 37, 41, 0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb),0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x);position:relative}.navbar-brand{color:var(--bs-navbar-brand-color);font-size:var(--bs-navbar-brand-font-size);margin-right:var(--bs-navbar-brand-margin-end);padding-bottom:var(--bs-navbar-brand-padding-y);padding-top:var(--bs-navbar-brand-padding-y);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;list-style:none;margin-bottom:0;padding-left:0}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-collapse{align-items:center;flex-basis:100%;flex-grow:1}.navbar-toggler{background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);color:var(--bs-navbar-color);font-size:var(--bs-navbar-toggler-font-size);line-height:1;padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);transition:var(--bs-navbar-toggler-transition)}@media(prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width);outline:0;text-decoration:none}.navbar-toggler-icon{background-image:var(--bs-navbar-toggler-icon-bg);background-position:50%;background-repeat:no-repeat;background-size:100%;display:inline-block;height:1.5em;vertical-align:middle;width:1.5em}@media(min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .nav-link{padding-left:var(--bs-navbar-nav-link-padding-x);padding-right:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}.navbar-dark{--bs-navbar-color:hsla(0,0%,100%,.55);--bs-navbar-hover-color:hsla(0,0%,100%,.75);--bs-navbar-disabled-color:hsla(0,0%,100%,.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:hsla(0,0%,100%,.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb),0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;word-wrap:break-word;background-clip:border-box;background-color:var(--bs-card-bg);border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius);color:var(--bs-body-color);display:flex;flex-direction:column;height:var(--bs-card-height);min-width:0;position:relative}.card-body{color:var(--bs-card-color);flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x)}.card-header{background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color);color:var(--bs-card-cap-color);margin-bottom:0;padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);border-radius:var(--bs-badge-border-radius);color:var(--bs-badge-color);display:inline-block;font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);text-align:center;vertical-align:baseline;white-space:nowrap}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius);color:var(--bs-alert-color);margin-bottom:var(--bs-alert-margin-bottom);padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);position:relative}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius);font-size:var(--bs-progress-font-size);height:var(--bs-progress-height)}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{background-color:var(--bs-progress-bar-bg);color:var(--bs-progress-bar-color);flex-direction:column;justify-content:center;text-align:center;transition:var(--bs-progress-bar-transition);white-space:nowrap}@media(prefers-reduced-motion:reduce){.progress-bar{transition:none}}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3E%3C/svg%3E");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(13,110,253,.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;--bs-btn-close-white-filter:invert(1) grayscale(100%) brightness(200%);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;box-sizing:content-box;height:1em;opacity:var(--bs-btn-close-opacity);padding:.25em;width:1em}.btn-close,.btn-close:hover{color:var(--bs-btn-close-color)}.btn-close:hover{opacity:var(--bs-btn-close-hover-opacity);text-decoration:none}.btn-close:focus{box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity);outline:0}.btn-close.disabled,.btn-close:disabled{opacity:var(--bs-btn-close-disabled-opacity);pointer-events:none;user-select:none}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);background-clip:padding-box;background-color:var(--bs-toast-bg);border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);border-radius:var(--bs-toast-border-radius);box-shadow:var(--bs-toast-box-shadow);color:var(--bs-toast-color);font-size:var(--bs-toast-font-size);max-width:100%;pointer-events:auto;width:var(--bs-toast-max-width)}.toast:not(.show){display:none}.toast-header{align-items:center;background-clip:padding-box;background-color:var(--bs-toast-header-bg);border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));color:var(--bs-toast-header-color);display:flex;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x)}.toast-header .btn-close{margin-left:var(--bs-toast-padding-x);margin-right:calc(var(--bs-toast-padding-x)*-.5)}.toast-body{word-wrap:break-word;padding:var(--bs-toast-padding-x)}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);display:none;height:100%;left:0;outline:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:0;width:100%;z-index:var(--bs-modal-zindex)}.modal-dialog{margin:var(--bs-modal-margin);pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media(prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{background-clip:padding-box;background-color:var(--bs-modal-bg);border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);color:var(--bs-modal-color);display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-header{align-items:center;border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--bs-modal-header-padding)}.modal-header .btn-close{margin:calc(var(--bs-modal-header-padding-y)*-.5) calc(var(--bs-modal-header-padding-x)*-.5) calc(var(--bs-modal-header-padding-y)*-.5) auto;padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5)}.modal-title{line-height:var(--bs-modal-title-line-height);margin-bottom:0}.modal-body{flex:1 1 auto;padding:var(--bs-modal-padding);position:relative}.modal-footer{align-items:center;background-color:var(--bs-modal-footer-bg);border-bottom-left-radius:var(--bs-modal-inner-border-radius);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media(min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{margin-left:auto;margin-right:auto;max-width:var(--bs-modal-width)}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;word-wrap:break-word;display:block;font-family:var(--bs-font-sans-serif);font-size:var(--bs-tooltip-font-size);font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;margin:var(--bs-tooltip-margin);opacity:0;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;z-index:var(--bs-tooltip-zindex)}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.spinner-border{animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name);border-radius:50%;display:inline-block;height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);width:var(--bs-spinner-width)}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border-right-color:currentcolor;border:var(--bs-spinner-border-width) solid;border-right:var(--bs-spinner-border-width) solid transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.spinner-border{--bs-spinner-animation-speed:1.5s}}.placeholder{background-color:currentcolor;cursor:wait;display:inline-block;min-height:1em;opacity:.5;vertical-align:middle}.placeholder.btn:before{content:"";display:inline-block}@keyframes placeholder-glow{50%{opacity:.2}}@keyframes placeholder-wave{to{mask-position:-200% 0}}.fixed-bottom{bottom:0;left:0;position:fixed;right:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.d-flex{display:flex!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.flex-column{flex-direction:column!important}.justify-content-between{justify-content:space-between!important}.mt-1{margin-top:.25rem!important}.mb-3{margin-bottom:1rem!important}.p-3{padding:1rem!important}.pt-0{padding-top:0!important}.pb-0{padding-bottom:0!important}.text-center{text-align:center!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.visible{visibility:visible!important}body{min-height:100vh}.border-bottom,.border-top{border-width:3px!important}.rebooting,tr.hide{display:none}td.value{width:80%} \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css.gz b/components/wifi-manager/webapp/dist/css/index.e8b465b654eff617dd1c.css.gz deleted file mode 100644 index 34ca6420827d0a30a4fb96641a9afdd1400edf15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8604 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 i$DP+Tvwc}8H-dD
Software Updates
VersionDate/TimePlatformBranchBit Depth
Local Firmware Upload
KeyValue
Usage Templates

Supported: flac,pcm,mp3,ogg (mad,mpg for specific mp3 codec)
Close output device after timeout seconds, default is to keep it open while player is 'on'
Logs: all|slimproto|stream|decode|output, level: info|debug|sdebug
Supported: flac,pcm,mp3,ogg (mad,mpg for specific mp3 codec)
Format: ab:cd:ef:12:34:56
<maxrate>|<minrate><maxrate><rate1><rate2><rate3>

WiFi Status
Logs
TimestampMessage
Tasks
#Task NameCPUStateMin StackBase PriorityCur Priority
Credits

squeezelite-esp32
© 2020, philippe44, sle118, daduke
This software is released under the MIT License.

This app would not be possible without the following libraries:

  • squeezelite, © 2012-2019, Adrian Smith and Ralph Irving. Licensed under the GPL License.
  • esp32-wifi-manager, © 2017-2019, Tony Pottier. Licensed under the MIT License.
  • SpinKit, © 2015, Tobias Ahlin. Licensed under the MIT License.
  • jQuery, The jQuery Foundation. Licensed under the MIT License.
  • cJSON, © 2009-2017, Dave Gamble and cJSON contributors. Licensed under the MIT License.
  • esp32-rotary-encoder, © 2011-2019, David Antliff and Ben Buxton. Licensed under the GPL License.
  • tarablessd1306, © 2017-2018, Tara Keeling. Licensed under the MIT license.
  • CSpot, © 2020 feelfreelinux & alufers. Licensed under the GPL License
Extras/Overrides
\ No newline at end of file +
Software Updates
VersionDate/TimePlatformBranchBit Depth
Local Firmware Upload
KeyValue
Usage Templates

Supported: flac,pcm,mp3,ogg (mad,mpg for specific mp3 codec)
Close output device after timeout seconds, default is to keep it open while player is 'on'
Logs: all|slimproto|stream|decode|output, level: info|debug|sdebug
Supported: flac,pcm,mp3,ogg (mad,mpg for specific mp3 codec)
Format: ab:cd:ef:12:34:56
<maxrate>|<minrate><maxrate><rate1><rate2><rate3>

WiFi Status
Logs
TimestampMessage
Tasks
#Task NameCPUStateMin StackBase PriorityCur Priority
Credits

squeezelite-esp32
© 2020, philippe44, sle118, daduke
This software is released under the MIT License.

This app would not be possible without the following libraries:

  • squeezelite, © 2012-2019, Adrian Smith and Ralph Irving. Licensed under the GPL License.
  • esp32-wifi-manager, © 2017-2019, Tony Pottier. Licensed under the MIT License.
  • SpinKit, © 2015, Tobias Ahlin. Licensed under the MIT License.
  • jQuery, The jQuery Foundation. Licensed under the MIT License.
  • cJSON, © 2009-2017, Dave Gamble and cJSON contributors. Licensed under the MIT License.
  • esp32-rotary-encoder, © 2011-2019, David Antliff and Ben Buxton. Licensed under the GPL License.
  • tarablessd1306, © 2017-2018, Tara Keeling. Licensed under the MIT license.
  • CSpot, © 2020 feelfreelinux & alufers. Licensed under the GPL License
Extras/Overrides
\ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/index.html.gz b/components/wifi-manager/webapp/dist/index.html.gz index f0a947e97766d819b37d4c681115912433e327a0..eb79f5bd9c35b42e174d34e88f14bbbe0daf6a02 100644 GIT binary patch literal 4949 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 TzMXknO`s(F;!Mc>2*LAasPaFlhHKtby5~Y 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 e,t={125:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3021);r.object.extend(proto,n);var a=o(5465);r.object.extend(proto,a),r.exportSymbol("proto.sys.AirPlay",null,i),proto.sys.AirPlay=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.AirPlay,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.AirPlay.displayName="proto.sys.AirPlay"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.AirPlay.prototype.toObject=function(e){return proto.sys.AirPlay.toObject(e,this)},proto.sys.AirPlay.toObject=function(e,t){var o={enabled:s.Message.getBooleanFieldWithDefault(t,1,!1),port:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.AirPlay.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.AirPlay;return proto.sys.AirPlay.deserializeBinaryFromReader(o,t)},proto.sys.AirPlay.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnabled(o);break;case 2:o=t.readUint32();e.setPort(o);break;default:t.skipField()}}return e},proto.sys.AirPlay.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.AirPlay.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.AirPlay.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnabled())&&t.writeBool(1,o),0!==(o=e.getPort())&&t.writeUint32(2,o)},proto.sys.AirPlay.prototype.getEnabled=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.AirPlay.prototype.setEnabled=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.AirPlay.prototype.getPort=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.AirPlay.prototype.setPort=function(e){return s.Message.setProto3IntField(this,2,e)},r.object.extend(t,proto.sys)},3353:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3021);r.object.extend(proto,n),r.exportSymbol("proto.sys.Artwork",null,i),proto.sys.Artwork=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Artwork,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Artwork.displayName="proto.sys.Artwork"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.Artwork.prototype.toObject=function(e){return proto.sys.Artwork.toObject(e,this)},proto.sys.Artwork.toObject=function(e,t){var o={enabled:s.Message.getBooleanFieldWithDefault(t,1,!1),resize:s.Message.getBooleanFieldWithDefault(t,2,!1)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Artwork.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Artwork;return proto.sys.Artwork.deserializeBinaryFromReader(o,t)},proto.sys.Artwork.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnabled(o);break;case 2:o=t.readBool();e.setResize(o);break;default:t.skipField()}}return e},proto.sys.Artwork.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Artwork.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Artwork.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnabled())&&t.writeBool(1,o),(o=e.getResize())&&t.writeBool(2,o)},proto.sys.Artwork.prototype.getEnabled=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.Artwork.prototype.setEnabled=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.Artwork.prototype.getResize=function(){return s.Message.getBooleanFieldWithDefault(this,2,!1)},proto.sys.Artwork.prototype.setResize=function(e){return s.Message.setProto3BooleanField(this,2,e)},r.object.extend(t,proto.sys)},6746:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3021);r.object.extend(proto,n),r.exportSymbol("proto.sys.Battery",null,i),r.exportSymbol("proto.sys.BatteryAttenEnum",null,i),r.exportSymbol("proto.sys.BatteryChannelEnum",null,i),proto.sys.Battery=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Battery,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Battery.displayName="proto.sys.Battery"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.Battery.prototype.toObject=function(e){return proto.sys.Battery.toObject(e,this)},proto.sys.Battery.toObject=function(e,t){var o={channel:s.Message.getFieldWithDefault(t,1,0),scale:s.Message.getFloatingPointFieldWithDefault(t,2,0),cells:s.Message.getFieldWithDefault(t,3,0),atten:s.Message.getFieldWithDefault(t,4,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Battery.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Battery;return proto.sys.Battery.deserializeBinaryFromReader(o,t)},proto.sys.Battery.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setChannel(o);break;case 2:o=t.readFloat();e.setScale(o);break;case 3:o=t.readInt32();e.setCells(o);break;case 4:o=t.readEnum();e.setAtten(o);break;default:t.skipField()}}return e},proto.sys.Battery.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Battery.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Battery.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getChannel())&&t.writeEnum(1,o),0!==(o=e.getScale())&&t.writeFloat(2,o),0!==(o=e.getCells())&&t.writeInt32(3,o),0!==(o=e.getAtten())&&t.writeEnum(4,o)},proto.sys.Battery.prototype.getChannel=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Battery.prototype.setChannel=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Battery.prototype.getScale=function(){return s.Message.getFloatingPointFieldWithDefault(this,2,0)},proto.sys.Battery.prototype.setScale=function(e){return s.Message.setProto3FloatField(this,2,e)},proto.sys.Battery.prototype.getCells=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.Battery.prototype.setCells=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.Battery.prototype.getAtten=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.Battery.prototype.setAtten=function(e){return s.Message.setProto3EnumField(this,4,e)},proto.sys.BatteryChannelEnum={UNSPECIFIED_CH:0,CH0:1,CH1:2,CH2:3,CH3:4,CH4:5,CH5:6,CH6:7,CH7:8},proto.sys.BatteryAttenEnum={UNSPECIFIED_ATT:0,ATT_0:1,ATT_1:2,ATT_2:3,ATT_3:4},r.object.extend(t,proto.sys)},7794:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.sys.Button",null,i),r.exportSymbol("proto.sys.ButtonAction",null,i),r.exportSymbol("proto.sys.ButtonActionChoice",null,i),r.exportSymbol("proto.sys.ButtonActionChoice.ActiontypeCase",null,i),r.exportSymbol("proto.sys.ButtonActions",null,i),r.exportSymbol("proto.sys.ButtonProfile",null,i),r.exportSymbol("proto.sys.KnobOnly",null,i),r.exportSymbol("proto.sys.Rotary",null,i),proto.sys.ButtonActionChoice=function(e){s.Message.initialize(this,e,0,-1,null,proto.sys.ButtonActionChoice.oneofGroups_)},r.inherits(proto.sys.ButtonActionChoice,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ButtonActionChoice.displayName="proto.sys.ButtonActionChoice"),proto.sys.ButtonActions=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.ButtonActions,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ButtonActions.displayName="proto.sys.ButtonActions"),proto.sys.Button=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Button,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Button.displayName="proto.sys.Button"),proto.sys.ButtonProfile=function(e){s.Message.initialize(this,e,0,-1,proto.sys.ButtonProfile.repeatedFields_,null)},r.inherits(proto.sys.ButtonProfile,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ButtonProfile.displayName="proto.sys.ButtonProfile"),proto.sys.KnobOnly=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.KnobOnly,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.KnobOnly.displayName="proto.sys.KnobOnly"),proto.sys.Rotary=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Rotary,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Rotary.displayName="proto.sys.Rotary"),proto.sys.ButtonActionChoice.oneofGroups_=[[1,2]],proto.sys.ButtonActionChoice.ActiontypeCase={ACTIONTYPE_NOT_SET:0,ACTION:1,PROFILE_NAME:2},proto.sys.ButtonActionChoice.prototype.getActiontypeCase=function(){return s.Message.computeOneofCase(this,proto.sys.ButtonActionChoice.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.ButtonActionChoice.prototype.toObject=function(e){return proto.sys.ButtonActionChoice.toObject(e,this)},proto.sys.ButtonActionChoice.toObject=function(e,t){var o={action:s.Message.getFieldWithDefault(t,1,0),profileName:s.Message.getFieldWithDefault(t,2,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.ButtonActionChoice.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ButtonActionChoice;return proto.sys.ButtonActionChoice.deserializeBinaryFromReader(o,t)},proto.sys.ButtonActionChoice.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setAction(o);break;case 2:o=t.readString();e.setProfileName(o);break;default:t.skipField()}}return e},proto.sys.ButtonActionChoice.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ButtonActionChoice.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ButtonActionChoice.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=s.Message.getField(e,1))&&t.writeEnum(1,o),null!=(o=s.Message.getField(e,2))&&t.writeString(2,o)},proto.sys.ButtonActionChoice.prototype.getAction=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.ButtonActionChoice.prototype.setAction=function(e){return s.Message.setOneofField(this,1,proto.sys.ButtonActionChoice.oneofGroups_[0],e)},proto.sys.ButtonActionChoice.prototype.clearAction=function(){return s.Message.setOneofField(this,1,proto.sys.ButtonActionChoice.oneofGroups_[0],void 0)},proto.sys.ButtonActionChoice.prototype.hasAction=function(){return null!=s.Message.getField(this,1)},proto.sys.ButtonActionChoice.prototype.getProfileName=function(){return s.Message.getFieldWithDefault(this,2,"")},proto.sys.ButtonActionChoice.prototype.setProfileName=function(e){return s.Message.setOneofField(this,2,proto.sys.ButtonActionChoice.oneofGroups_[0],e)},proto.sys.ButtonActionChoice.prototype.clearProfileName=function(){return s.Message.setOneofField(this,2,proto.sys.ButtonActionChoice.oneofGroups_[0],void 0)},proto.sys.ButtonActionChoice.prototype.hasProfileName=function(){return null!=s.Message.getField(this,2)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.ButtonActions.prototype.toObject=function(e){return proto.sys.ButtonActions.toObject(e,this)},proto.sys.ButtonActions.toObject=function(e,t){var o,s={normal:(o=t.getNormal())&&proto.sys.ButtonActionChoice.toObject(e,o),longpress:(o=t.getLongpress())&&proto.sys.ButtonActionChoice.toObject(e,o),shifted:(o=t.getShifted())&&proto.sys.ButtonActionChoice.toObject(e,o),longshifted:(o=t.getLongshifted())&&proto.sys.ButtonActionChoice.toObject(e,o)};return e&&(s.$jspbMessageInstance=t),s}),proto.sys.ButtonActions.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ButtonActions;return proto.sys.ButtonActions.deserializeBinaryFromReader(o,t)},proto.sys.ButtonActions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.ButtonActionChoice;t.readMessage(o,proto.sys.ButtonActionChoice.deserializeBinaryFromReader),e.setNormal(o);break;case 2:o=new proto.sys.ButtonActionChoice;t.readMessage(o,proto.sys.ButtonActionChoice.deserializeBinaryFromReader),e.setLongpress(o);break;case 3:o=new proto.sys.ButtonActionChoice;t.readMessage(o,proto.sys.ButtonActionChoice.deserializeBinaryFromReader),e.setShifted(o);break;case 4:o=new proto.sys.ButtonActionChoice;t.readMessage(o,proto.sys.ButtonActionChoice.deserializeBinaryFromReader),e.setLongshifted(o);break;default:t.skipField()}}return e},proto.sys.ButtonActions.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ButtonActions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ButtonActions.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getNormal())&&t.writeMessage(1,o,proto.sys.ButtonActionChoice.serializeBinaryToWriter),null!=(o=e.getLongpress())&&t.writeMessage(2,o,proto.sys.ButtonActionChoice.serializeBinaryToWriter),null!=(o=e.getShifted())&&t.writeMessage(3,o,proto.sys.ButtonActionChoice.serializeBinaryToWriter),null!=(o=e.getLongshifted())&&t.writeMessage(4,o,proto.sys.ButtonActionChoice.serializeBinaryToWriter)},proto.sys.ButtonActions.prototype.getNormal=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActionChoice,1)},proto.sys.ButtonActions.prototype.setNormal=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.ButtonActions.prototype.clearNormal=function(){return this.setNormal(void 0)},proto.sys.ButtonActions.prototype.hasNormal=function(){return null!=s.Message.getField(this,1)},proto.sys.ButtonActions.prototype.getLongpress=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActionChoice,2)},proto.sys.ButtonActions.prototype.setLongpress=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.ButtonActions.prototype.clearLongpress=function(){return this.setLongpress(void 0)},proto.sys.ButtonActions.prototype.hasLongpress=function(){return null!=s.Message.getField(this,2)},proto.sys.ButtonActions.prototype.getShifted=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActionChoice,3)},proto.sys.ButtonActions.prototype.setShifted=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.ButtonActions.prototype.clearShifted=function(){return this.setShifted(void 0)},proto.sys.ButtonActions.prototype.hasShifted=function(){return null!=s.Message.getField(this,3)},proto.sys.ButtonActions.prototype.getLongshifted=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActionChoice,4)},proto.sys.ButtonActions.prototype.setLongshifted=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.ButtonActions.prototype.clearLongshifted=function(){return this.setLongshifted(void 0)},proto.sys.ButtonActions.prototype.hasLongshifted=function(){return null!=s.Message.getField(this,4)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Button.prototype.toObject=function(e){return proto.sys.Button.toObject(e,this)},proto.sys.Button.toObject=function(e,t){var o,r={gpio:(o=t.getGpio())&&n.GPIO.toObject(e,o),pull:s.Message.getBooleanFieldWithDefault(t,2,!1),debounce:s.Message.getFieldWithDefault(t,3,0),shifter:(o=t.getShifter())&&n.GPIO.toObject(e,o),longduration:s.Message.getFieldWithDefault(t,5,0),pressed:(o=t.getPressed())&&proto.sys.ButtonActions.toObject(e,o),released:(o=t.getReleased())&&proto.sys.ButtonActions.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Button.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Button;return proto.sys.Button.deserializeBinaryFromReader(o,t)},proto.sys.Button.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;case 2:o=t.readBool();e.setPull(o);break;case 3:o=t.readInt32();e.setDebounce(o);break;case 4:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setShifter(o);break;case 5:o=t.readInt32();e.setLongduration(o);break;case 6:o=new proto.sys.ButtonActions;t.readMessage(o,proto.sys.ButtonActions.deserializeBinaryFromReader),e.setPressed(o);break;case 7:o=new proto.sys.ButtonActions;t.readMessage(o,proto.sys.ButtonActions.deserializeBinaryFromReader),e.setReleased(o);break;default:t.skipField()}}return e},proto.sys.Button.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Button.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Button.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpio())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),(o=e.getPull())&&t.writeBool(2,o),0!==(o=e.getDebounce())&&t.writeInt32(3,o),null!=(o=e.getShifter())&&t.writeMessage(4,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getLongduration())&&t.writeInt32(5,o),null!=(o=e.getPressed())&&t.writeMessage(6,o,proto.sys.ButtonActions.serializeBinaryToWriter),null!=(o=e.getReleased())&&t.writeMessage(7,o,proto.sys.ButtonActions.serializeBinaryToWriter)},proto.sys.Button.prototype.getGpio=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.Button.prototype.setGpio=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Button.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.sys.Button.prototype.hasGpio=function(){return null!=s.Message.getField(this,1)},proto.sys.Button.prototype.getPull=function(){return s.Message.getBooleanFieldWithDefault(this,2,!1)},proto.sys.Button.prototype.setPull=function(e){return s.Message.setProto3BooleanField(this,2,e)},proto.sys.Button.prototype.getDebounce=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.Button.prototype.setDebounce=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.Button.prototype.getShifter=function(){return s.Message.getWrapperField(this,n.GPIO,4)},proto.sys.Button.prototype.setShifter=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Button.prototype.clearShifter=function(){return this.setShifter(void 0)},proto.sys.Button.prototype.hasShifter=function(){return null!=s.Message.getField(this,4)},proto.sys.Button.prototype.getLongduration=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.Button.prototype.setLongduration=function(e){return s.Message.setProto3IntField(this,5,e)},proto.sys.Button.prototype.getPressed=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActions,6)},proto.sys.Button.prototype.setPressed=function(e){return s.Message.setWrapperField(this,6,e)},proto.sys.Button.prototype.clearPressed=function(){return this.setPressed(void 0)},proto.sys.Button.prototype.hasPressed=function(){return null!=s.Message.getField(this,6)},proto.sys.Button.prototype.getReleased=function(){return s.Message.getWrapperField(this,proto.sys.ButtonActions,7)},proto.sys.Button.prototype.setReleased=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.Button.prototype.clearReleased=function(){return this.setReleased(void 0)},proto.sys.Button.prototype.hasReleased=function(){return null!=s.Message.getField(this,7)},proto.sys.ButtonProfile.repeatedFields_=[2],s.Message.GENERATE_TO_OBJECT&&(proto.sys.ButtonProfile.prototype.toObject=function(e){return proto.sys.ButtonProfile.toObject(e,this)},proto.sys.ButtonProfile.toObject=function(e,t){var o={profileName:s.Message.getFieldWithDefault(t,1,""),buttonList:s.Message.toObjectList(t.getButtonList(),proto.sys.Button.toObject,e)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.ButtonProfile.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ButtonProfile;return proto.sys.ButtonProfile.deserializeBinaryFromReader(o,t)},proto.sys.ButtonProfile.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setProfileName(o);break;case 2:o=new proto.sys.Button;t.readMessage(o,proto.sys.Button.deserializeBinaryFromReader),e.addButton(o);break;default:t.skipField()}}return e},proto.sys.ButtonProfile.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ButtonProfile.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ButtonProfile.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getProfileName()).length>0&&t.writeString(1,o),(o=e.getButtonList()).length>0&&t.writeRepeatedMessage(2,o,proto.sys.Button.serializeBinaryToWriter)},proto.sys.ButtonProfile.prototype.getProfileName=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.ButtonProfile.prototype.setProfileName=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.ButtonProfile.prototype.getButtonList=function(){return s.Message.getRepeatedWrapperField(this,proto.sys.Button,2)},proto.sys.ButtonProfile.prototype.setButtonList=function(e){return s.Message.setRepeatedWrapperField(this,2,e)},proto.sys.ButtonProfile.prototype.addButton=function(e,t){return s.Message.addToRepeatedWrapperField(this,2,e,proto.sys.Button,t)},proto.sys.ButtonProfile.prototype.clearButtonList=function(){return this.setButtonList([])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.KnobOnly.prototype.toObject=function(e){return proto.sys.KnobOnly.toObject(e,this)},proto.sys.KnobOnly.toObject=function(e,t){var o={enable:s.Message.getBooleanFieldWithDefault(t,1,!1),delayMs:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.KnobOnly.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.KnobOnly;return proto.sys.KnobOnly.deserializeBinaryFromReader(o,t)},proto.sys.KnobOnly.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnable(o);break;case 2:o=t.readInt32();e.setDelayMs(o);break;default:t.skipField()}}return e},proto.sys.KnobOnly.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.KnobOnly.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.KnobOnly.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnable())&&t.writeBool(1,o),0!==(o=e.getDelayMs())&&t.writeInt32(2,o)},proto.sys.KnobOnly.prototype.getEnable=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.KnobOnly.prototype.setEnable=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.KnobOnly.prototype.getDelayMs=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.KnobOnly.prototype.setDelayMs=function(e){return s.Message.setProto3IntField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Rotary.prototype.toObject=function(e){return proto.sys.Rotary.toObject(e,this)},proto.sys.Rotary.toObject=function(e,t){var o,r={a:(o=t.getA())&&n.GPIO.toObject(e,o),b:(o=t.getB())&&n.GPIO.toObject(e,o),sw:(o=t.getSw())&&n.GPIO.toObject(e,o),knobonly:(o=t.getKnobonly())&&proto.sys.KnobOnly.toObject(e,o),volume:s.Message.getBooleanFieldWithDefault(t,5,!1),longpress:s.Message.getBooleanFieldWithDefault(t,6,!1)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Rotary.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Rotary;return proto.sys.Rotary.deserializeBinaryFromReader(o,t)},proto.sys.Rotary.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setA(o);break;case 2:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setB(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setSw(o);break;case 4:o=new proto.sys.KnobOnly;t.readMessage(o,proto.sys.KnobOnly.deserializeBinaryFromReader),e.setKnobonly(o);break;case 5:o=t.readBool();e.setVolume(o);break;case 6:o=t.readBool();e.setLongpress(o);break;default:t.skipField()}}return e},proto.sys.Rotary.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Rotary.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Rotary.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getA())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getB())&&t.writeMessage(2,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getSw())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getKnobonly())&&t.writeMessage(4,o,proto.sys.KnobOnly.serializeBinaryToWriter),(o=e.getVolume())&&t.writeBool(5,o),(o=e.getLongpress())&&t.writeBool(6,o)},proto.sys.Rotary.prototype.getA=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.Rotary.prototype.setA=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Rotary.prototype.clearA=function(){return this.setA(void 0)},proto.sys.Rotary.prototype.hasA=function(){return null!=s.Message.getField(this,1)},proto.sys.Rotary.prototype.getB=function(){return s.Message.getWrapperField(this,n.GPIO,2)},proto.sys.Rotary.prototype.setB=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Rotary.prototype.clearB=function(){return this.setB(void 0)},proto.sys.Rotary.prototype.hasB=function(){return null!=s.Message.getField(this,2)},proto.sys.Rotary.prototype.getSw=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.Rotary.prototype.setSw=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.Rotary.prototype.clearSw=function(){return this.setSw(void 0)},proto.sys.Rotary.prototype.hasSw=function(){return null!=s.Message.getField(this,3)},proto.sys.Rotary.prototype.getKnobonly=function(){return s.Message.getWrapperField(this,proto.sys.KnobOnly,4)},proto.sys.Rotary.prototype.setKnobonly=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Rotary.prototype.clearKnobonly=function(){return this.setKnobonly(void 0)},proto.sys.Rotary.prototype.hasKnobonly=function(){return null!=s.Message.getField(this,4)},proto.sys.Rotary.prototype.getVolume=function(){return s.Message.getBooleanFieldWithDefault(this,5,!1)},proto.sys.Rotary.prototype.setVolume=function(e){return s.Message.setProto3BooleanField(this,5,e)},proto.sys.Rotary.prototype.getLongpress=function(){return s.Message.getBooleanFieldWithDefault(this,6,!1)},proto.sys.Rotary.prototype.setLongpress=function(e){return s.Message.setProto3BooleanField(this,6,e)},proto.sys.ButtonAction={ACTRLS_NONE:0,ACTRLS_POWER:1,ACTRLS_VOLUP:2,ACTRLS_VOLDOWN:3,ACTRLS_TOGGLE:4,ACTRLS_PLAY:5,ACTRLS_PAUSE:6,ACTRLS_STOP:7,ACTRLS_REW:8,ACTRLS_FWD:9,ACTRLS_PREV:10,ACTRLS_NEXT:11,BCTRLS_UP:12,BCTRLS_DOWN:13,BCTRLS_LEFT:14,BCTRLS_RIGHT:15,BCTRLS_PS1:16,BCTRLS_PS2:17,BCTRLS_PS3:18,BCTRLS_PS4:19,BCTRLS_PS5:20,BCTRLS_PS6:21,BCTRLS_PS7:22,BCTRLS_PS8:23,BCTRLS_PS9:24,BCTRLS_PS10:25,KNOB_LEFT:26,KNOB_RIGHT:27,KNOB_PUSH:28,ACTRLS_SLEEP:29},r.object.extend(t,proto.sys)},2038:(e,t,o)=>{var s=o(3019),r="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==r&&r||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),i=o(3021);s.object.extend(proto,i),s.exportSymbol("proto.sys.DeviceTypeEnum",null,r),s.exportSymbol("proto.sys.HostEnum",null,r),s.exportSymbol("proto.sys.PortEnum",null,r),proto.sys.DeviceTypeEnum={UNSPECIFIED_TYPE:0,DEVTYPE_SPI:1,DEVTYPE_I2C:2,DEVTYPE__RMII:3},proto.sys.PortEnum={UNSPECIFIED_SYSTPORT:0,SYSTEM:1,DAC_PORT:2},proto.sys.HostEnum={UNSPECIFIED_HOST:0,HOST0:1,HOST1:2},s.object.extend(t,proto.sys)},7284:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(5184);r.object.extend(proto,a);var p=o(2035);r.object.extend(proto,p);var l=o(5465);r.object.extend(proto,l);var u=o(3021);r.object.extend(proto,u),r.exportSymbol("proto.sys.DAC",null,i),r.exportSymbol("proto.sys.DACModelEnum",null,i),r.exportSymbol("proto.sys.MCKEnum",null,i),proto.sys.DAC=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.DAC,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DAC.displayName="proto.sys.DAC"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.DAC.prototype.toObject=function(e){return proto.sys.DAC.toObject(e,this)},proto.sys.DAC.toObject=function(e,t){var o,r={bck:(o=t.getBck())&&n.GPIO.toObject(e,o),ws:(o=t.getWs())&&n.GPIO.toObject(e,o),dout:(o=t.getDout())&&n.GPIO.toObject(e,o),mck:s.Message.getFieldWithDefault(t,4,0),mute:(o=t.getMute())&&n.GPIO.toObject(e,o),model:s.Message.getFieldWithDefault(t,6,0),i2c:(o=t.getI2c())&&p.I2CBus.toObject(e,o),daccontrolset:(o=t.getDaccontrolset())&&a.DacControlSet.toObject(e,o),jackMutesAmp:s.Message.getBooleanFieldWithDefault(t,9,!1)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.DAC.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DAC;return proto.sys.DAC.deserializeBinaryFromReader(o,t)},proto.sys.DAC.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setBck(o);break;case 2:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setWs(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setDout(o);break;case 4:o=t.readEnum();e.setMck(o);break;case 5:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setMute(o);break;case 6:o=t.readEnum();e.setModel(o);break;case 7:o=new p.I2CBus;t.readMessage(o,p.I2CBus.deserializeBinaryFromReader),e.setI2c(o);break;case 8:o=new a.DacControlSet;t.readMessage(o,a.DacControlSet.deserializeBinaryFromReader),e.setDaccontrolset(o);break;case 9:o=t.readBool();e.setJackMutesAmp(o);break;default:t.skipField()}}return e},proto.sys.DAC.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DAC.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DAC.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getBck())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getWs())&&t.writeMessage(2,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getDout())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getMck())&&t.writeEnum(4,o),null!=(o=e.getMute())&&t.writeMessage(5,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getModel())&&t.writeEnum(6,o),null!=(o=e.getI2c())&&t.writeMessage(7,o,p.I2CBus.serializeBinaryToWriter),null!=(o=e.getDaccontrolset())&&t.writeMessage(8,o,a.DacControlSet.serializeBinaryToWriter),(o=e.getJackMutesAmp())&&t.writeBool(9,o)},proto.sys.DAC.prototype.getBck=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.DAC.prototype.setBck=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.DAC.prototype.clearBck=function(){return this.setBck(void 0)},proto.sys.DAC.prototype.hasBck=function(){return null!=s.Message.getField(this,1)},proto.sys.DAC.prototype.getWs=function(){return s.Message.getWrapperField(this,n.GPIO,2)},proto.sys.DAC.prototype.setWs=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.DAC.prototype.clearWs=function(){return this.setWs(void 0)},proto.sys.DAC.prototype.hasWs=function(){return null!=s.Message.getField(this,2)},proto.sys.DAC.prototype.getDout=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.DAC.prototype.setDout=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.DAC.prototype.clearDout=function(){return this.setDout(void 0)},proto.sys.DAC.prototype.hasDout=function(){return null!=s.Message.getField(this,3)},proto.sys.DAC.prototype.getMck=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.DAC.prototype.setMck=function(e){return s.Message.setProto3EnumField(this,4,e)},proto.sys.DAC.prototype.getMute=function(){return s.Message.getWrapperField(this,n.GPIO,5)},proto.sys.DAC.prototype.setMute=function(e){return s.Message.setWrapperField(this,5,e)},proto.sys.DAC.prototype.clearMute=function(){return this.setMute(void 0)},proto.sys.DAC.prototype.hasMute=function(){return null!=s.Message.getField(this,5)},proto.sys.DAC.prototype.getModel=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.DAC.prototype.setModel=function(e){return s.Message.setProto3EnumField(this,6,e)},proto.sys.DAC.prototype.getI2c=function(){return s.Message.getWrapperField(this,p.I2CBus,7)},proto.sys.DAC.prototype.setI2c=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.DAC.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.sys.DAC.prototype.hasI2c=function(){return null!=s.Message.getField(this,7)},proto.sys.DAC.prototype.getDaccontrolset=function(){return s.Message.getWrapperField(this,a.DacControlSet,8)},proto.sys.DAC.prototype.setDaccontrolset=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.DAC.prototype.clearDaccontrolset=function(){return this.setDaccontrolset(void 0)},proto.sys.DAC.prototype.hasDaccontrolset=function(){return null!=s.Message.getField(this,8)},proto.sys.DAC.prototype.getJackMutesAmp=function(){return s.Message.getBooleanFieldWithDefault(this,9,!1)},proto.sys.DAC.prototype.setJackMutesAmp=function(e){return s.Message.setProto3BooleanField(this,9,e)},proto.sys.DACModelEnum={UNSPECIFIED_MODEL:0,TAS57XX:1,TAS5713:2,AC101:3,WM8978:4,ES8388:5,I2S:6,CS4265:7},proto.sys.MCKEnum={UNSPECIFIED_MCK:0,MCK0:1,MCK1:2,MCK2:3},r.object.extend(t,proto.sys)},5184:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3021);r.object.extend(proto,n),r.exportSymbol("proto.sys.ControlCommand",null,i),r.exportSymbol("proto.sys.ControlCommandType",null,i),r.exportSymbol("proto.sys.ControlItem",null,i),r.exportSymbol("proto.sys.ControlItem.ItemTypeCase",null,i),r.exportSymbol("proto.sys.DacControlSet",null,i),r.exportSymbol("proto.sys.DelayAction",null,i),r.exportSymbol("proto.sys.GpioAction",null,i),r.exportSymbol("proto.sys.GpioActionLevel",null,i),r.exportSymbol("proto.sys.Mode",null,i),r.exportSymbol("proto.sys.RegisterAction",null,i),proto.sys.DacControlSet=function(e){s.Message.initialize(this,e,0,-1,proto.sys.DacControlSet.repeatedFields_,null)},r.inherits(proto.sys.DacControlSet,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DacControlSet.displayName="proto.sys.DacControlSet"),proto.sys.ControlCommand=function(e){s.Message.initialize(this,e,0,-1,proto.sys.ControlCommand.repeatedFields_,null)},r.inherits(proto.sys.ControlCommand,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ControlCommand.displayName="proto.sys.ControlCommand"),proto.sys.ControlItem=function(e){s.Message.initialize(this,e,0,-1,null,proto.sys.ControlItem.oneofGroups_)},r.inherits(proto.sys.ControlItem,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ControlItem.displayName="proto.sys.ControlItem"),proto.sys.RegisterAction=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.RegisterAction,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.RegisterAction.displayName="proto.sys.RegisterAction"),proto.sys.GpioAction=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.GpioAction,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.GpioAction.displayName="proto.sys.GpioAction"),proto.sys.DelayAction=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.DelayAction,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DelayAction.displayName="proto.sys.DelayAction"),proto.sys.DacControlSet.repeatedFields_=[1],s.Message.GENERATE_TO_OBJECT&&(proto.sys.DacControlSet.prototype.toObject=function(e){return proto.sys.DacControlSet.toObject(e,this)},proto.sys.DacControlSet.toObject=function(e,t){var o={commandsList:s.Message.toObjectList(t.getCommandsList(),proto.sys.ControlCommand.toObject,e)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.DacControlSet.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DacControlSet;return proto.sys.DacControlSet.deserializeBinaryFromReader(o,t)},proto.sys.DacControlSet.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(1===t.getFieldNumber()){var o=new proto.sys.ControlCommand;t.readMessage(o,proto.sys.ControlCommand.deserializeBinaryFromReader),e.addCommands(o)}else t.skipField()}return e},proto.sys.DacControlSet.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DacControlSet.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DacControlSet.serializeBinaryToWriter=function(e,t){var o;(o=e.getCommandsList()).length>0&&t.writeRepeatedMessage(1,o,proto.sys.ControlCommand.serializeBinaryToWriter)},proto.sys.DacControlSet.prototype.getCommandsList=function(){return s.Message.getRepeatedWrapperField(this,proto.sys.ControlCommand,1)},proto.sys.DacControlSet.prototype.setCommandsList=function(e){return s.Message.setRepeatedWrapperField(this,1,e)},proto.sys.DacControlSet.prototype.addCommands=function(e,t){return s.Message.addToRepeatedWrapperField(this,1,e,proto.sys.ControlCommand,t)},proto.sys.DacControlSet.prototype.clearCommandsList=function(){return this.setCommandsList([])},proto.sys.ControlCommand.repeatedFields_=[2],s.Message.GENERATE_TO_OBJECT&&(proto.sys.ControlCommand.prototype.toObject=function(e){return proto.sys.ControlCommand.toObject(e,this)},proto.sys.ControlCommand.toObject=function(e,t){var o={type:s.Message.getFieldWithDefault(t,1,0),itemsList:s.Message.toObjectList(t.getItemsList(),proto.sys.ControlItem.toObject,e)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.ControlCommand.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ControlCommand;return proto.sys.ControlCommand.deserializeBinaryFromReader(o,t)},proto.sys.ControlCommand.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new proto.sys.ControlItem;t.readMessage(o,proto.sys.ControlItem.deserializeBinaryFromReader),e.addItems(o);break;default:t.skipField()}}return e},proto.sys.ControlCommand.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ControlCommand.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ControlCommand.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),(o=e.getItemsList()).length>0&&t.writeRepeatedMessage(2,o,proto.sys.ControlItem.serializeBinaryToWriter)},proto.sys.ControlCommand.prototype.getType=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.ControlCommand.prototype.setType=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.ControlCommand.prototype.getItemsList=function(){return s.Message.getRepeatedWrapperField(this,proto.sys.ControlItem,2)},proto.sys.ControlCommand.prototype.setItemsList=function(e){return s.Message.setRepeatedWrapperField(this,2,e)},proto.sys.ControlCommand.prototype.addItems=function(e,t){return s.Message.addToRepeatedWrapperField(this,2,e,proto.sys.ControlItem,t)},proto.sys.ControlCommand.prototype.clearItemsList=function(){return this.setItemsList([])},proto.sys.ControlItem.oneofGroups_=[[1,2,3]],proto.sys.ControlItem.ItemTypeCase={ITEM_TYPE_NOT_SET:0,REG_ACTION:1,GPIO_ACTION:2,DELAY_ACTION:3},proto.sys.ControlItem.prototype.getItemTypeCase=function(){return s.Message.computeOneofCase(this,proto.sys.ControlItem.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.ControlItem.prototype.toObject=function(e){return proto.sys.ControlItem.toObject(e,this)},proto.sys.ControlItem.toObject=function(e,t){var o,s={regAction:(o=t.getRegAction())&&proto.sys.RegisterAction.toObject(e,o),gpioAction:(o=t.getGpioAction())&&proto.sys.GpioAction.toObject(e,o),delayAction:(o=t.getDelayAction())&&proto.sys.DelayAction.toObject(e,o)};return e&&(s.$jspbMessageInstance=t),s}),proto.sys.ControlItem.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ControlItem;return proto.sys.ControlItem.deserializeBinaryFromReader(o,t)},proto.sys.ControlItem.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.RegisterAction;t.readMessage(o,proto.sys.RegisterAction.deserializeBinaryFromReader),e.setRegAction(o);break;case 2:o=new proto.sys.GpioAction;t.readMessage(o,proto.sys.GpioAction.deserializeBinaryFromReader),e.setGpioAction(o);break;case 3:o=new proto.sys.DelayAction;t.readMessage(o,proto.sys.DelayAction.deserializeBinaryFromReader),e.setDelayAction(o);break;default:t.skipField()}}return e},proto.sys.ControlItem.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ControlItem.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ControlItem.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getRegAction())&&t.writeMessage(1,o,proto.sys.RegisterAction.serializeBinaryToWriter),null!=(o=e.getGpioAction())&&t.writeMessage(2,o,proto.sys.GpioAction.serializeBinaryToWriter),null!=(o=e.getDelayAction())&&t.writeMessage(3,o,proto.sys.DelayAction.serializeBinaryToWriter)},proto.sys.ControlItem.prototype.getRegAction=function(){return s.Message.getWrapperField(this,proto.sys.RegisterAction,1)},proto.sys.ControlItem.prototype.setRegAction=function(e){return s.Message.setOneofWrapperField(this,1,proto.sys.ControlItem.oneofGroups_[0],e)},proto.sys.ControlItem.prototype.clearRegAction=function(){return this.setRegAction(void 0)},proto.sys.ControlItem.prototype.hasRegAction=function(){return null!=s.Message.getField(this,1)},proto.sys.ControlItem.prototype.getGpioAction=function(){return s.Message.getWrapperField(this,proto.sys.GpioAction,2)},proto.sys.ControlItem.prototype.setGpioAction=function(e){return s.Message.setOneofWrapperField(this,2,proto.sys.ControlItem.oneofGroups_[0],e)},proto.sys.ControlItem.prototype.clearGpioAction=function(){return this.setGpioAction(void 0)},proto.sys.ControlItem.prototype.hasGpioAction=function(){return null!=s.Message.getField(this,2)},proto.sys.ControlItem.prototype.getDelayAction=function(){return s.Message.getWrapperField(this,proto.sys.DelayAction,3)},proto.sys.ControlItem.prototype.setDelayAction=function(e){return s.Message.setOneofWrapperField(this,3,proto.sys.ControlItem.oneofGroups_[0],e)},proto.sys.ControlItem.prototype.clearDelayAction=function(){return this.setDelayAction(void 0)},proto.sys.ControlItem.prototype.hasDelayAction=function(){return null!=s.Message.getField(this,3)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.RegisterAction.prototype.toObject=function(e){return proto.sys.RegisterAction.toObject(e,this)},proto.sys.RegisterAction.toObject=function(e,t){var o={reg:s.Message.getFieldWithDefault(t,1,0),val:s.Message.getFieldWithDefault(t,2,0),mode:s.Message.getFieldWithDefault(t,3,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.RegisterAction.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.RegisterAction;return proto.sys.RegisterAction.deserializeBinaryFromReader(o,t)},proto.sys.RegisterAction.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setReg(o);break;case 2:o=t.readInt32();e.setVal(o);break;case 3:o=t.readEnum();e.setMode(o);break;default:t.skipField()}}return e},proto.sys.RegisterAction.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.RegisterAction.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.RegisterAction.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getReg())&&t.writeInt32(1,o),0!==(o=e.getVal())&&t.writeInt32(2,o),0!==(o=e.getMode())&&t.writeEnum(3,o)},proto.sys.RegisterAction.prototype.getReg=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.RegisterAction.prototype.setReg=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.RegisterAction.prototype.getVal=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.RegisterAction.prototype.setVal=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.RegisterAction.prototype.getMode=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.RegisterAction.prototype.setMode=function(e){return s.Message.setProto3EnumField(this,3,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.GpioAction.prototype.toObject=function(e){return proto.sys.GpioAction.toObject(e,this)},proto.sys.GpioAction.toObject=function(e,t){var o={gpio:s.Message.getFieldWithDefault(t,1,0),level:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.GpioAction.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.GpioAction;return proto.sys.GpioAction.deserializeBinaryFromReader(o,t)},proto.sys.GpioAction.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setGpio(o);break;case 2:o=t.readEnum();e.setLevel(o);break;default:t.skipField()}}return e},proto.sys.GpioAction.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.GpioAction.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.GpioAction.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getGpio())&&t.writeInt32(1,o),0!==(o=e.getLevel())&&t.writeEnum(2,o)},proto.sys.GpioAction.prototype.getGpio=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.GpioAction.prototype.setGpio=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.GpioAction.prototype.getLevel=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.GpioAction.prototype.setLevel=function(e){return s.Message.setProto3EnumField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.DelayAction.prototype.toObject=function(e){return proto.sys.DelayAction.toObject(e,this)},proto.sys.DelayAction.toObject=function(e,t){var o={delay:s.Message.getFieldWithDefault(t,1,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.DelayAction.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DelayAction;return proto.sys.DelayAction.deserializeBinaryFromReader(o,t)},proto.sys.DelayAction.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(1===t.getFieldNumber()){var o=t.readInt32();e.setDelay(o)}else t.skipField()}return e},proto.sys.DelayAction.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DelayAction.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DelayAction.serializeBinaryToWriter=function(e,t){var o;0!==(o=e.getDelay())&&t.writeInt32(1,o)},proto.sys.DelayAction.prototype.getDelay=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.DelayAction.prototype.setDelay=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.ControlCommandType={INIT:0,POWER_ON:1,POWER_OFF:2,SPEAKER_ON:3,SPEAKER_OFF:4,HEADSET_ON:5,HEADSET_OFF:6},proto.sys.GpioActionLevel={ACTION_LEVEL_UNDEFINED:0,ACTION_LEVEL_1:1,ACTION_LEVEL_0:2},proto.sys.Mode={REG_MODE_NOTHING:0,REG_MODE_OR:1,REG_MODE_AND:2},r.object.extend(t,proto.sys)},5437:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(2038);r.object.extend(proto,a);var p=o(2035);r.object.extend(proto,p);var l=o(7284);r.object.extend(proto,l);var u=o(874);r.object.extend(proto,u);var y=o(7794);r.object.extend(proto,y);var d=o(6746);r.object.extend(proto,d);var c=o(9716);r.object.extend(proto,c);var g=o(3021);r.object.extend(proto,g),r.exportSymbol("proto.sys.Dev",null,i),r.exportSymbol("proto.sys.Infrared",null,i),r.exportSymbol("proto.sys.InfraredType",null,i),r.exportSymbol("proto.sys.LEDStrip",null,i),r.exportSymbol("proto.sys.LEDStripType",null,i),r.exportSymbol("proto.sys.SPDIF",null,i),r.exportSymbol("proto.sys.SPIBus",null,i),proto.sys.SPDIF=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.SPDIF,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.SPDIF.displayName="proto.sys.SPDIF"),proto.sys.SPIBus=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.SPIBus,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.SPIBus.displayName="proto.sys.SPIBus"),proto.sys.LEDStrip=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.LEDStrip,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.LEDStrip.displayName="proto.sys.LEDStrip"),proto.sys.Infrared=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Infrared,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Infrared.displayName="proto.sys.Infrared"),proto.sys.Dev=function(e){s.Message.initialize(this,e,0,-1,proto.sys.Dev.repeatedFields_,null)},r.inherits(proto.sys.Dev,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Dev.displayName="proto.sys.Dev"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.SPDIF.prototype.toObject=function(e){return proto.sys.SPDIF.toObject(e,this)},proto.sys.SPDIF.toObject=function(e,t){var o,s={ws:(o=t.getWs())&&n.GPIO.toObject(e,o),data:(o=t.getData())&&n.GPIO.toObject(e,o),clk:(o=t.getClk())&&n.GPIO.toObject(e,o)};return e&&(s.$jspbMessageInstance=t),s}),proto.sys.SPDIF.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.SPDIF;return proto.sys.SPDIF.deserializeBinaryFromReader(o,t)},proto.sys.SPDIF.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setWs(o);break;case 2:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setData(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setClk(o);break;default:t.skipField()}}return e},proto.sys.SPDIF.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.SPDIF.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.SPDIF.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getWs())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getData())&&t.writeMessage(2,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getClk())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter)},proto.sys.SPDIF.prototype.getWs=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.SPDIF.prototype.setWs=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.SPDIF.prototype.clearWs=function(){return this.setWs(void 0)},proto.sys.SPDIF.prototype.hasWs=function(){return null!=s.Message.getField(this,1)},proto.sys.SPDIF.prototype.getData=function(){return s.Message.getWrapperField(this,n.GPIO,2)},proto.sys.SPDIF.prototype.setData=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.SPDIF.prototype.clearData=function(){return this.setData(void 0)},proto.sys.SPDIF.prototype.hasData=function(){return null!=s.Message.getField(this,2)},proto.sys.SPDIF.prototype.getClk=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.SPDIF.prototype.setClk=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.SPDIF.prototype.clearClk=function(){return this.setClk(void 0)},proto.sys.SPDIF.prototype.hasClk=function(){return null!=s.Message.getField(this,3)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.SPIBus.prototype.toObject=function(e){return proto.sys.SPIBus.toObject(e,this)},proto.sys.SPIBus.toObject=function(e,t){var o,r={mosi:(o=t.getMosi())&&n.GPIO.toObject(e,o),miso:(o=t.getMiso())&&n.GPIO.toObject(e,o),clk:(o=t.getClk())&&n.GPIO.toObject(e,o),dc:(o=t.getDc())&&n.GPIO.toObject(e,o),host:s.Message.getFieldWithDefault(t,5,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.SPIBus.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.SPIBus;return proto.sys.SPIBus.deserializeBinaryFromReader(o,t)},proto.sys.SPIBus.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setMosi(o);break;case 2:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setMiso(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setClk(o);break;case 4:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setDc(o);break;case 5:o=t.readEnum();e.setHost(o);break;default:t.skipField()}}return e},proto.sys.SPIBus.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.SPIBus.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.SPIBus.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMosi())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getMiso())&&t.writeMessage(2,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getClk())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getDc())&&t.writeMessage(4,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getHost())&&t.writeEnum(5,o)},proto.sys.SPIBus.prototype.getMosi=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.SPIBus.prototype.setMosi=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.SPIBus.prototype.clearMosi=function(){return this.setMosi(void 0)},proto.sys.SPIBus.prototype.hasMosi=function(){return null!=s.Message.getField(this,1)},proto.sys.SPIBus.prototype.getMiso=function(){return s.Message.getWrapperField(this,n.GPIO,2)},proto.sys.SPIBus.prototype.setMiso=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.SPIBus.prototype.clearMiso=function(){return this.setMiso(void 0)},proto.sys.SPIBus.prototype.hasMiso=function(){return null!=s.Message.getField(this,2)},proto.sys.SPIBus.prototype.getClk=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.SPIBus.prototype.setClk=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.SPIBus.prototype.clearClk=function(){return this.setClk(void 0)},proto.sys.SPIBus.prototype.hasClk=function(){return null!=s.Message.getField(this,3)},proto.sys.SPIBus.prototype.getDc=function(){return s.Message.getWrapperField(this,n.GPIO,4)},proto.sys.SPIBus.prototype.setDc=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.SPIBus.prototype.clearDc=function(){return this.setDc(void 0)},proto.sys.SPIBus.prototype.hasDc=function(){return null!=s.Message.getField(this,4)},proto.sys.SPIBus.prototype.getHost=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.SPIBus.prototype.setHost=function(e){return s.Message.setProto3EnumField(this,5,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.LEDStrip.prototype.toObject=function(e){return proto.sys.LEDStrip.toObject(e,this)},proto.sys.LEDStrip.toObject=function(e,t){var o,r={gpio:(o=t.getGpio())&&n.GPIO.toObject(e,o),length:s.Message.getFieldWithDefault(t,2,0),stripType:s.Message.getFieldWithDefault(t,3,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.LEDStrip.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.LEDStrip;return proto.sys.LEDStrip.deserializeBinaryFromReader(o,t)},proto.sys.LEDStrip.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;case 2:o=t.readInt32();e.setLength(o);break;case 3:o=t.readEnum();e.setStripType(o);break;default:t.skipField()}}return e},proto.sys.LEDStrip.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.LEDStrip.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.LEDStrip.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpio())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getLength())&&t.writeInt32(2,o),0!==(o=e.getStripType())&&t.writeEnum(3,o)},proto.sys.LEDStrip.prototype.getGpio=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.LEDStrip.prototype.setGpio=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.LEDStrip.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.sys.LEDStrip.prototype.hasGpio=function(){return null!=s.Message.getField(this,1)},proto.sys.LEDStrip.prototype.getLength=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.LEDStrip.prototype.setLength=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.LEDStrip.prototype.getStripType=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.LEDStrip.prototype.setStripType=function(e){return s.Message.setProto3EnumField(this,3,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Infrared.prototype.toObject=function(e){return proto.sys.Infrared.toObject(e,this)},proto.sys.Infrared.toObject=function(e,t){var o,r={type:s.Message.getFieldWithDefault(t,1,0),gpio:(o=t.getGpio())&&n.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Infrared.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Infrared;return proto.sys.Infrared.deserializeBinaryFromReader(o,t)},proto.sys.Infrared.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;default:t.skipField()}}return e},proto.sys.Infrared.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Infrared.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Infrared.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),null!=(o=e.getGpio())&&t.writeMessage(2,o,n.GPIO.serializeBinaryToWriter)},proto.sys.Infrared.prototype.getType=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Infrared.prototype.setType=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Infrared.prototype.getGpio=function(){return s.Message.getWrapperField(this,n.GPIO,2)},proto.sys.Infrared.prototype.setGpio=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Infrared.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.sys.Infrared.prototype.hasGpio=function(){return null!=s.Message.getField(this,2)},proto.sys.Dev.repeatedFields_=[6,9],s.Message.GENERATE_TO_OBJECT&&(proto.sys.Dev.prototype.toObject=function(e){return proto.sys.Dev.toObject(e,this)},proto.sys.Dev.toObject=function(e,t){var o,r={spi:(o=t.getSpi())&&proto.sys.SPIBus.toObject(e,o),i2c:(o=t.getI2c())&&p.I2CBus.toObject(e,o),dac:(o=t.getDac())&&l.DAC.toObject(e,o),spdif:(o=t.getSpdif())&&proto.sys.SPDIF.toObject(e,o),display:(o=t.getDisplay())&&u.Display.toObject(e,o),gpioExpList:s.Message.toObjectList(t.getGpioExpList(),n.GPIOExp.toObject,e),ledStrip:(o=t.getLedStrip())&&proto.sys.LEDStrip.toObject(e,o),rotary:(o=t.getRotary())&&y.Rotary.toObject(e,o),buttonsList:s.Message.toObjectList(t.getButtonsList(),y.ButtonProfile.toObject,e),eth:(o=t.getEth())&&c.Eth.toObject(e,o),battery:(o=t.getBattery())&&d.Battery.toObject(e,o),ir:(o=t.getIr())&&proto.sys.Infrared.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Dev.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Dev;return proto.sys.Dev.deserializeBinaryFromReader(o,t)},proto.sys.Dev.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.SPIBus;t.readMessage(o,proto.sys.SPIBus.deserializeBinaryFromReader),e.setSpi(o);break;case 2:o=new p.I2CBus;t.readMessage(o,p.I2CBus.deserializeBinaryFromReader),e.setI2c(o);break;case 3:o=new l.DAC;t.readMessage(o,l.DAC.deserializeBinaryFromReader),e.setDac(o);break;case 4:o=new proto.sys.SPDIF;t.readMessage(o,proto.sys.SPDIF.deserializeBinaryFromReader),e.setSpdif(o);break;case 5:o=new u.Display;t.readMessage(o,u.Display.deserializeBinaryFromReader),e.setDisplay(o);break;case 6:o=new n.GPIOExp;t.readMessage(o,n.GPIOExp.deserializeBinaryFromReader),e.addGpioExp(o);break;case 7:o=new proto.sys.LEDStrip;t.readMessage(o,proto.sys.LEDStrip.deserializeBinaryFromReader),e.setLedStrip(o);break;case 8:o=new y.Rotary;t.readMessage(o,y.Rotary.deserializeBinaryFromReader),e.setRotary(o);break;case 9:o=new y.ButtonProfile;t.readMessage(o,y.ButtonProfile.deserializeBinaryFromReader),e.addButtons(o);break;case 10:o=new c.Eth;t.readMessage(o,c.Eth.deserializeBinaryFromReader),e.setEth(o);break;case 11:o=new d.Battery;t.readMessage(o,d.Battery.deserializeBinaryFromReader),e.setBattery(o);break;case 12:o=new proto.sys.Infrared;t.readMessage(o,proto.sys.Infrared.deserializeBinaryFromReader),e.setIr(o);break;default:t.skipField()}}return e},proto.sys.Dev.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Dev.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Dev.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getSpi())&&t.writeMessage(1,o,proto.sys.SPIBus.serializeBinaryToWriter),null!=(o=e.getI2c())&&t.writeMessage(2,o,p.I2CBus.serializeBinaryToWriter),null!=(o=e.getDac())&&t.writeMessage(3,o,l.DAC.serializeBinaryToWriter),null!=(o=e.getSpdif())&&t.writeMessage(4,o,proto.sys.SPDIF.serializeBinaryToWriter),null!=(o=e.getDisplay())&&t.writeMessage(5,o,u.Display.serializeBinaryToWriter),(o=e.getGpioExpList()).length>0&&t.writeRepeatedMessage(6,o,n.GPIOExp.serializeBinaryToWriter),null!=(o=e.getLedStrip())&&t.writeMessage(7,o,proto.sys.LEDStrip.serializeBinaryToWriter),null!=(o=e.getRotary())&&t.writeMessage(8,o,y.Rotary.serializeBinaryToWriter),(o=e.getButtonsList()).length>0&&t.writeRepeatedMessage(9,o,y.ButtonProfile.serializeBinaryToWriter),null!=(o=e.getEth())&&t.writeMessage(10,o,c.Eth.serializeBinaryToWriter),null!=(o=e.getBattery())&&t.writeMessage(11,o,d.Battery.serializeBinaryToWriter),null!=(o=e.getIr())&&t.writeMessage(12,o,proto.sys.Infrared.serializeBinaryToWriter)},proto.sys.Dev.prototype.getSpi=function(){return s.Message.getWrapperField(this,proto.sys.SPIBus,1)},proto.sys.Dev.prototype.setSpi=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Dev.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.sys.Dev.prototype.hasSpi=function(){return null!=s.Message.getField(this,1)},proto.sys.Dev.prototype.getI2c=function(){return s.Message.getWrapperField(this,p.I2CBus,2)},proto.sys.Dev.prototype.setI2c=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Dev.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.sys.Dev.prototype.hasI2c=function(){return null!=s.Message.getField(this,2)},proto.sys.Dev.prototype.getDac=function(){return s.Message.getWrapperField(this,l.DAC,3)},proto.sys.Dev.prototype.setDac=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.Dev.prototype.clearDac=function(){return this.setDac(void 0)},proto.sys.Dev.prototype.hasDac=function(){return null!=s.Message.getField(this,3)},proto.sys.Dev.prototype.getSpdif=function(){return s.Message.getWrapperField(this,proto.sys.SPDIF,4)},proto.sys.Dev.prototype.setSpdif=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Dev.prototype.clearSpdif=function(){return this.setSpdif(void 0)},proto.sys.Dev.prototype.hasSpdif=function(){return null!=s.Message.getField(this,4)},proto.sys.Dev.prototype.getDisplay=function(){return s.Message.getWrapperField(this,u.Display,5)},proto.sys.Dev.prototype.setDisplay=function(e){return s.Message.setWrapperField(this,5,e)},proto.sys.Dev.prototype.clearDisplay=function(){return this.setDisplay(void 0)},proto.sys.Dev.prototype.hasDisplay=function(){return null!=s.Message.getField(this,5)},proto.sys.Dev.prototype.getGpioExpList=function(){return s.Message.getRepeatedWrapperField(this,n.GPIOExp,6)},proto.sys.Dev.prototype.setGpioExpList=function(e){return s.Message.setRepeatedWrapperField(this,6,e)},proto.sys.Dev.prototype.addGpioExp=function(e,t){return s.Message.addToRepeatedWrapperField(this,6,e,proto.sys.GPIOExp,t)},proto.sys.Dev.prototype.clearGpioExpList=function(){return this.setGpioExpList([])},proto.sys.Dev.prototype.getLedStrip=function(){return s.Message.getWrapperField(this,proto.sys.LEDStrip,7)},proto.sys.Dev.prototype.setLedStrip=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.Dev.prototype.clearLedStrip=function(){return this.setLedStrip(void 0)},proto.sys.Dev.prototype.hasLedStrip=function(){return null!=s.Message.getField(this,7)},proto.sys.Dev.prototype.getRotary=function(){return s.Message.getWrapperField(this,y.Rotary,8)},proto.sys.Dev.prototype.setRotary=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.Dev.prototype.clearRotary=function(){return this.setRotary(void 0)},proto.sys.Dev.prototype.hasRotary=function(){return null!=s.Message.getField(this,8)},proto.sys.Dev.prototype.getButtonsList=function(){return s.Message.getRepeatedWrapperField(this,y.ButtonProfile,9)},proto.sys.Dev.prototype.setButtonsList=function(e){return s.Message.setRepeatedWrapperField(this,9,e)},proto.sys.Dev.prototype.addButtons=function(e,t){return s.Message.addToRepeatedWrapperField(this,9,e,proto.sys.ButtonProfile,t)},proto.sys.Dev.prototype.clearButtonsList=function(){return this.setButtonsList([])},proto.sys.Dev.prototype.getEth=function(){return s.Message.getWrapperField(this,c.Eth,10)},proto.sys.Dev.prototype.setEth=function(e){return s.Message.setWrapperField(this,10,e)},proto.sys.Dev.prototype.clearEth=function(){return this.setEth(void 0)},proto.sys.Dev.prototype.hasEth=function(){return null!=s.Message.getField(this,10)},proto.sys.Dev.prototype.getBattery=function(){return s.Message.getWrapperField(this,d.Battery,11)},proto.sys.Dev.prototype.setBattery=function(e){return s.Message.setWrapperField(this,11,e)},proto.sys.Dev.prototype.clearBattery=function(){return this.setBattery(void 0)},proto.sys.Dev.prototype.hasBattery=function(){return null!=s.Message.getField(this,11)},proto.sys.Dev.prototype.getIr=function(){return s.Message.getWrapperField(this,proto.sys.Infrared,12)},proto.sys.Dev.prototype.setIr=function(e){return s.Message.setWrapperField(this,12,e)},proto.sys.Dev.prototype.clearIr=function(){return this.setIr(void 0)},proto.sys.Dev.prototype.hasIr=function(){return null!=s.Message.getField(this,12)},proto.sys.LEDStripType={LS_UNKNOWN:0,LS_WS2812:1,LS_SK6812:2,LS_APA106:3},proto.sys.InfraredType={IR_UNKNOWN:0,IR_RC5:1,IR_NEC:2},r.object.extend(t,proto.sys)},874:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(2038);r.object.extend(proto,a);var p=o(3021);r.object.extend(proto,p),r.exportSymbol("proto.sys.DispCommon",null,i),r.exportSymbol("proto.sys.DispOffsets",null,i),r.exportSymbol("proto.sys.Display",null,i),r.exportSymbol("proto.sys.Display.DisptypeCase",null,i),r.exportSymbol("proto.sys.DisplayDriverEnum",null,i),r.exportSymbol("proto.sys.I2CDisplay",null,i),r.exportSymbol("proto.sys.SPIDisplay",null,i),proto.sys.DispOffsets=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.DispOffsets,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DispOffsets.displayName="proto.sys.DispOffsets"),proto.sys.I2CDisplay=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.I2CDisplay,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.I2CDisplay.displayName="proto.sys.I2CDisplay"),proto.sys.SPIDisplay=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.SPIDisplay,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.SPIDisplay.displayName="proto.sys.SPIDisplay"),proto.sys.DispCommon=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.DispCommon,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DispCommon.displayName="proto.sys.DispCommon"),proto.sys.Display=function(e){s.Message.initialize(this,e,0,-1,null,proto.sys.Display.oneofGroups_)},r.inherits(proto.sys.Display,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Display.displayName="proto.sys.Display"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.DispOffsets.prototype.toObject=function(e){return proto.sys.DispOffsets.toObject(e,this)},proto.sys.DispOffsets.toObject=function(e,t){var o={height:s.Message.getFieldWithDefault(t,1,0),width:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.DispOffsets.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DispOffsets;return proto.sys.DispOffsets.deserializeBinaryFromReader(o,t)},proto.sys.DispOffsets.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setHeight(o);break;case 2:o=t.readInt32();e.setWidth(o);break;default:t.skipField()}}return e},proto.sys.DispOffsets.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DispOffsets.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DispOffsets.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getHeight())&&t.writeInt32(1,o),0!==(o=e.getWidth())&&t.writeInt32(2,o)},proto.sys.DispOffsets.prototype.getHeight=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.DispOffsets.prototype.setHeight=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.DispOffsets.prototype.getWidth=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.DispOffsets.prototype.setWidth=function(e){return s.Message.setProto3IntField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.I2CDisplay.prototype.toObject=function(e){return proto.sys.I2CDisplay.toObject(e,this)},proto.sys.I2CDisplay.toObject=function(e,t){var o={address:s.Message.getFieldWithDefault(t,1,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.I2CDisplay.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.I2CDisplay;return proto.sys.I2CDisplay.deserializeBinaryFromReader(o,t)},proto.sys.I2CDisplay.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(1===t.getFieldNumber()){var o=t.readInt32();e.setAddress(o)}else t.skipField()}return e},proto.sys.I2CDisplay.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.I2CDisplay.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.I2CDisplay.serializeBinaryToWriter=function(e,t){var o;0!==(o=e.getAddress())&&t.writeInt32(1,o)},proto.sys.I2CDisplay.prototype.getAddress=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.I2CDisplay.prototype.setAddress=function(e){return s.Message.setProto3IntField(this,1,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.SPIDisplay.prototype.toObject=function(e){return proto.sys.SPIDisplay.toObject(e,this)},proto.sys.SPIDisplay.toObject=function(e,t){var o,r={cs:(o=t.getCs())&&n.GPIO.toObject(e,o),speed:s.Message.getFieldWithDefault(t,4,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.SPIDisplay.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.SPIDisplay;return proto.sys.SPIDisplay.deserializeBinaryFromReader(o,t)},proto.sys.SPIDisplay.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setCs(o);break;case 4:o=t.readInt32();e.setSpeed(o);break;default:t.skipField()}}return e},proto.sys.SPIDisplay.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.SPIDisplay.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.SPIDisplay.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getCs())&&t.writeMessage(1,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getSpeed())&&t.writeInt32(4,o)},proto.sys.SPIDisplay.prototype.getCs=function(){return s.Message.getWrapperField(this,n.GPIO,1)},proto.sys.SPIDisplay.prototype.setCs=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.SPIDisplay.prototype.clearCs=function(){return this.setCs(void 0)},proto.sys.SPIDisplay.prototype.hasCs=function(){return null!=s.Message.getField(this,1)},proto.sys.SPIDisplay.prototype.getSpeed=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.SPIDisplay.prototype.setSpeed=function(e){return s.Message.setProto3IntField(this,4,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.DispCommon.prototype.toObject=function(e){return proto.sys.DispCommon.toObject(e,this)},proto.sys.DispCommon.toObject=function(e,t){var o,r={width:s.Message.getFieldWithDefault(t,1,0),height:s.Message.getFieldWithDefault(t,2,0),hflip:s.Message.getBooleanFieldWithDefault(t,3,!1),vflip:s.Message.getBooleanFieldWithDefault(t,4,!1),driver:s.Message.getFieldWithDefault(t,5,0),bitdepth:s.Message.getFieldWithDefault(t,6,0),back:(o=t.getBack())&&n.GPIO.toObject(e,o),reset:(o=t.getReset())&&n.GPIO.toObject(e,o),ready:(o=t.getReady())&&n.GPIO.toObject(e,o),offsets:(o=t.getOffsets())&&proto.sys.DispOffsets.toObject(e,o),rotate:s.Message.getBooleanFieldWithDefault(t,11,!1),invert:s.Message.getBooleanFieldWithDefault(t,12,!1),colowSwap:s.Message.getBooleanFieldWithDefault(t,13,!1)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.DispCommon.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DispCommon;return proto.sys.DispCommon.deserializeBinaryFromReader(o,t)},proto.sys.DispCommon.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setWidth(o);break;case 2:o=t.readInt32();e.setHeight(o);break;case 3:o=t.readBool();e.setHflip(o);break;case 4:o=t.readBool();e.setVflip(o);break;case 5:o=t.readEnum();e.setDriver(o);break;case 6:o=t.readInt32();e.setBitdepth(o);break;case 7:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setBack(o);break;case 8:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setReset(o);break;case 9:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setReady(o);break;case 10:o=new proto.sys.DispOffsets;t.readMessage(o,proto.sys.DispOffsets.deserializeBinaryFromReader),e.setOffsets(o);break;case 11:o=t.readBool();e.setRotate(o);break;case 12:o=t.readBool();e.setInvert(o);break;case 13:o=t.readBool();e.setColowSwap(o);break;default:t.skipField()}}return e},proto.sys.DispCommon.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DispCommon.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DispCommon.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getWidth())&&t.writeInt32(1,o),0!==(o=e.getHeight())&&t.writeInt32(2,o),(o=e.getHflip())&&t.writeBool(3,o),(o=e.getVflip())&&t.writeBool(4,o),0!==(o=e.getDriver())&&t.writeEnum(5,o),0!==(o=e.getBitdepth())&&t.writeInt32(6,o),null!=(o=e.getBack())&&t.writeMessage(7,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getReset())&&t.writeMessage(8,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getReady())&&t.writeMessage(9,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getOffsets())&&t.writeMessage(10,o,proto.sys.DispOffsets.serializeBinaryToWriter),(o=e.getRotate())&&t.writeBool(11,o),(o=e.getInvert())&&t.writeBool(12,o),(o=e.getColowSwap())&&t.writeBool(13,o)},proto.sys.DispCommon.prototype.getWidth=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.DispCommon.prototype.setWidth=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.DispCommon.prototype.getHeight=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.DispCommon.prototype.setHeight=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.DispCommon.prototype.getHflip=function(){return s.Message.getBooleanFieldWithDefault(this,3,!1)},proto.sys.DispCommon.prototype.setHflip=function(e){return s.Message.setProto3BooleanField(this,3,e)},proto.sys.DispCommon.prototype.getVflip=function(){return s.Message.getBooleanFieldWithDefault(this,4,!1)},proto.sys.DispCommon.prototype.setVflip=function(e){return s.Message.setProto3BooleanField(this,4,e)},proto.sys.DispCommon.prototype.getDriver=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.DispCommon.prototype.setDriver=function(e){return s.Message.setProto3EnumField(this,5,e)},proto.sys.DispCommon.prototype.getBitdepth=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.DispCommon.prototype.setBitdepth=function(e){return s.Message.setProto3IntField(this,6,e)},proto.sys.DispCommon.prototype.getBack=function(){return s.Message.getWrapperField(this,n.GPIO,7)},proto.sys.DispCommon.prototype.setBack=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.DispCommon.prototype.clearBack=function(){return this.setBack(void 0)},proto.sys.DispCommon.prototype.hasBack=function(){return null!=s.Message.getField(this,7)},proto.sys.DispCommon.prototype.getReset=function(){return s.Message.getWrapperField(this,n.GPIO,8)},proto.sys.DispCommon.prototype.setReset=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.DispCommon.prototype.clearReset=function(){return this.setReset(void 0)},proto.sys.DispCommon.prototype.hasReset=function(){return null!=s.Message.getField(this,8)},proto.sys.DispCommon.prototype.getReady=function(){return s.Message.getWrapperField(this,n.GPIO,9)},proto.sys.DispCommon.prototype.setReady=function(e){return s.Message.setWrapperField(this,9,e)},proto.sys.DispCommon.prototype.clearReady=function(){return this.setReady(void 0)},proto.sys.DispCommon.prototype.hasReady=function(){return null!=s.Message.getField(this,9)},proto.sys.DispCommon.prototype.getOffsets=function(){return s.Message.getWrapperField(this,proto.sys.DispOffsets,10)},proto.sys.DispCommon.prototype.setOffsets=function(e){return s.Message.setWrapperField(this,10,e)},proto.sys.DispCommon.prototype.clearOffsets=function(){return this.setOffsets(void 0)},proto.sys.DispCommon.prototype.hasOffsets=function(){return null!=s.Message.getField(this,10)},proto.sys.DispCommon.prototype.getRotate=function(){return s.Message.getBooleanFieldWithDefault(this,11,!1)},proto.sys.DispCommon.prototype.setRotate=function(e){return s.Message.setProto3BooleanField(this,11,e)},proto.sys.DispCommon.prototype.getInvert=function(){return s.Message.getBooleanFieldWithDefault(this,12,!1)},proto.sys.DispCommon.prototype.setInvert=function(e){return s.Message.setProto3BooleanField(this,12,e)},proto.sys.DispCommon.prototype.getColowSwap=function(){return s.Message.getBooleanFieldWithDefault(this,13,!1)},proto.sys.DispCommon.prototype.setColowSwap=function(e){return s.Message.setProto3BooleanField(this,13,e)},proto.sys.Display.oneofGroups_=[[3,4]],proto.sys.Display.DisptypeCase={DISPTYPE_NOT_SET:0,I2C:3,SPI:4},proto.sys.Display.prototype.getDisptypeCase=function(){return s.Message.computeOneofCase(this,proto.sys.Display.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Display.prototype.toObject=function(e){return proto.sys.Display.toObject(e,this)},proto.sys.Display.toObject=function(e,t){var o,r={type:s.Message.getFieldWithDefault(t,1,0),common:(o=t.getCommon())&&proto.sys.DispCommon.toObject(e,o),i2c:(o=t.getI2c())&&proto.sys.I2CDisplay.toObject(e,o),spi:(o=t.getSpi())&&proto.sys.SPIDisplay.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Display.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Display;return proto.sys.Display.deserializeBinaryFromReader(o,t)},proto.sys.Display.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new proto.sys.DispCommon;t.readMessage(o,proto.sys.DispCommon.deserializeBinaryFromReader),e.setCommon(o);break;case 3:o=new proto.sys.I2CDisplay;t.readMessage(o,proto.sys.I2CDisplay.deserializeBinaryFromReader),e.setI2c(o);break;case 4:o=new proto.sys.SPIDisplay;t.readMessage(o,proto.sys.SPIDisplay.deserializeBinaryFromReader),e.setSpi(o);break;default:t.skipField()}}return e},proto.sys.Display.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Display.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Display.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),null!=(o=e.getCommon())&&t.writeMessage(2,o,proto.sys.DispCommon.serializeBinaryToWriter),null!=(o=e.getI2c())&&t.writeMessage(3,o,proto.sys.I2CDisplay.serializeBinaryToWriter),null!=(o=e.getSpi())&&t.writeMessage(4,o,proto.sys.SPIDisplay.serializeBinaryToWriter)},proto.sys.Display.prototype.getType=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Display.prototype.setType=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Display.prototype.getCommon=function(){return s.Message.getWrapperField(this,proto.sys.DispCommon,2)},proto.sys.Display.prototype.setCommon=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Display.prototype.clearCommon=function(){return this.setCommon(void 0)},proto.sys.Display.prototype.hasCommon=function(){return null!=s.Message.getField(this,2)},proto.sys.Display.prototype.getI2c=function(){return s.Message.getWrapperField(this,proto.sys.I2CDisplay,3)},proto.sys.Display.prototype.setI2c=function(e){return s.Message.setOneofWrapperField(this,3,proto.sys.Display.oneofGroups_[0],e)},proto.sys.Display.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.sys.Display.prototype.hasI2c=function(){return null!=s.Message.getField(this,3)},proto.sys.Display.prototype.getSpi=function(){return s.Message.getWrapperField(this,proto.sys.SPIDisplay,4)},proto.sys.Display.prototype.setSpi=function(e){return s.Message.setOneofWrapperField(this,4,proto.sys.Display.oneofGroups_[0],e)},proto.sys.Display.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.sys.Display.prototype.hasSpi=function(){return null!=s.Message.getField(this,4)},proto.sys.DisplayDriverEnum={UNSPECIFIED_DRIVER:0,SSD1306:1,SSD1322:2,SSD1326:3,SSD1327:4,SH1106:5,SSD1675:6,ST7735:7,ST7789:8,ILI9341:9,ILI9341_24:10,SSD1351:11},r.object.extend(t,proto.sys)},190:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3021);r.object.extend(proto,n),r.exportSymbol("proto.sys.Equalizer",null,i),proto.sys.Equalizer=function(e){s.Message.initialize(this,e,0,-1,proto.sys.Equalizer.repeatedFields_,null)},r.inherits(proto.sys.Equalizer,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Equalizer.displayName="proto.sys.Equalizer"),proto.sys.Equalizer.repeatedFields_=[1],s.Message.GENERATE_TO_OBJECT&&(proto.sys.Equalizer.prototype.toObject=function(e){return proto.sys.Equalizer.toObject(e,this)},proto.sys.Equalizer.toObject=function(e,t){var o,r={gainsList:null==(o=s.Message.getRepeatedFloatingPointField(t,1))?void 0:o,loudness:s.Message.getFloatingPointFieldWithDefault(t,2,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Equalizer.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Equalizer;return proto.sys.Equalizer.deserializeBinaryFromReader(o,t)},proto.sys.Equalizer.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:for(var o=t.isDelimited()?t.readPackedFloat():[t.readFloat()],s=0;s0&&t.writePackedFloat(1,o),0!==(o=e.getLoudness())&&t.writeFloat(2,o)},proto.sys.Equalizer.prototype.getGainsList=function(){return s.Message.getRepeatedFloatingPointField(this,1)},proto.sys.Equalizer.prototype.setGainsList=function(e){return s.Message.setField(this,1,e||[])},proto.sys.Equalizer.prototype.addGains=function(e,t){return s.Message.addToRepeatedField(this,1,e,t)},proto.sys.Equalizer.prototype.clearGainsList=function(){return this.setGainsList([])},proto.sys.Equalizer.prototype.getLoudness=function(){return s.Message.getFloatingPointFieldWithDefault(this,2,0)},proto.sys.Equalizer.prototype.setLoudness=function(e){return s.Message.setProto3FloatField(this,2,e)},r.object.extend(t,proto.sys)},9716:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(2038);r.object.extend(proto,n);var a=o(7567);r.object.extend(proto,a);var p=o(3021);r.object.extend(proto,p);var l=o(5465);r.object.extend(proto,l),r.exportSymbol("proto.sys.Eth",null,i),r.exportSymbol("proto.sys.Eth.EthtypeCase",null,i),r.exportSymbol("proto.sys.EthCommon",null,i),r.exportSymbol("proto.sys.EthModelEnum",null,i),r.exportSymbol("proto.sys.EthRMII",null,i),r.exportSymbol("proto.sys.EthSPI",null,i),r.exportSymbol("proto.sys.EthType",null,i),proto.sys.EthCommon=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.EthCommon,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.EthCommon.displayName="proto.sys.EthCommon"),proto.sys.EthSPI=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.EthSPI,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.EthSPI.displayName="proto.sys.EthSPI"),proto.sys.EthRMII=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.EthRMII,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.EthRMII.displayName="proto.sys.EthRMII"),proto.sys.Eth=function(e){s.Message.initialize(this,e,0,-1,null,proto.sys.Eth.oneofGroups_)},r.inherits(proto.sys.Eth,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Eth.displayName="proto.sys.Eth"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.EthCommon.prototype.toObject=function(e){return proto.sys.EthCommon.toObject(e,this)},proto.sys.EthCommon.toObject=function(e,t){var o,r={model:s.Message.getFieldWithDefault(t,1,0),rst:(o=t.getRst())&&a.GPIO.toObject(e,o),ethtmoutS:s.Message.getFieldWithDefault(t,3,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.EthCommon.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.EthCommon;return proto.sys.EthCommon.deserializeBinaryFromReader(o,t)},proto.sys.EthCommon.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setModel(o);break;case 2:o=new a.GPIO;t.readMessage(o,a.GPIO.deserializeBinaryFromReader),e.setRst(o);break;case 3:o=t.readUint32();e.setEthtmoutS(o);break;default:t.skipField()}}return e},proto.sys.EthCommon.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.EthCommon.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.EthCommon.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getModel())&&t.writeEnum(1,o),null!=(o=e.getRst())&&t.writeMessage(2,o,a.GPIO.serializeBinaryToWriter),0!==(o=e.getEthtmoutS())&&t.writeUint32(3,o)},proto.sys.EthCommon.prototype.getModel=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.EthCommon.prototype.setModel=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.EthCommon.prototype.getRst=function(){return s.Message.getWrapperField(this,a.GPIO,2)},proto.sys.EthCommon.prototype.setRst=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.EthCommon.prototype.clearRst=function(){return this.setRst(void 0)},proto.sys.EthCommon.prototype.hasRst=function(){return null!=s.Message.getField(this,2)},proto.sys.EthCommon.prototype.getEthtmoutS=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.EthCommon.prototype.setEthtmoutS=function(e){return s.Message.setProto3IntField(this,3,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.EthSPI.prototype.toObject=function(e){return proto.sys.EthSPI.toObject(e,this)},proto.sys.EthSPI.toObject=function(e,t){var o,r={cs:(o=t.getCs())&&a.GPIO.toObject(e,o),speed:s.Message.getFieldWithDefault(t,2,0),intr:(o=t.getIntr())&&a.GPIO.toObject(e,o),host:s.Message.getFieldWithDefault(t,4,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.EthSPI.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.EthSPI;return proto.sys.EthSPI.deserializeBinaryFromReader(o,t)},proto.sys.EthSPI.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new a.GPIO;t.readMessage(o,a.GPIO.deserializeBinaryFromReader),e.setCs(o);break;case 2:o=t.readInt32();e.setSpeed(o);break;case 3:o=new a.GPIO;t.readMessage(o,a.GPIO.deserializeBinaryFromReader),e.setIntr(o);break;case 4:o=t.readInt32();e.setHost(o);break;default:t.skipField()}}return e},proto.sys.EthSPI.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.EthSPI.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.EthSPI.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getCs())&&t.writeMessage(1,o,a.GPIO.serializeBinaryToWriter),0!==(o=e.getSpeed())&&t.writeInt32(2,o),null!=(o=e.getIntr())&&t.writeMessage(3,o,a.GPIO.serializeBinaryToWriter),0!==(o=e.getHost())&&t.writeInt32(4,o)},proto.sys.EthSPI.prototype.getCs=function(){return s.Message.getWrapperField(this,a.GPIO,1)},proto.sys.EthSPI.prototype.setCs=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.EthSPI.prototype.clearCs=function(){return this.setCs(void 0)},proto.sys.EthSPI.prototype.hasCs=function(){return null!=s.Message.getField(this,1)},proto.sys.EthSPI.prototype.getSpeed=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.EthSPI.prototype.setSpeed=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.EthSPI.prototype.getIntr=function(){return s.Message.getWrapperField(this,a.GPIO,3)},proto.sys.EthSPI.prototype.setIntr=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.EthSPI.prototype.clearIntr=function(){return this.setIntr(void 0)},proto.sys.EthSPI.prototype.hasIntr=function(){return null!=s.Message.getField(this,3)},proto.sys.EthSPI.prototype.getHost=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.EthSPI.prototype.setHost=function(e){return s.Message.setProto3IntField(this,4,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.EthRMII.prototype.toObject=function(e){return proto.sys.EthRMII.toObject(e,this)},proto.sys.EthRMII.toObject=function(e,t){var o,s={mdc:(o=t.getMdc())&&a.GPIO.toObject(e,o),mdio:(o=t.getMdio())&&a.GPIO.toObject(e,o)};return e&&(s.$jspbMessageInstance=t),s}),proto.sys.EthRMII.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.EthRMII;return proto.sys.EthRMII.deserializeBinaryFromReader(o,t)},proto.sys.EthRMII.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new a.GPIO;t.readMessage(o,a.GPIO.deserializeBinaryFromReader),e.setMdc(o);break;case 2:o=new a.GPIO;t.readMessage(o,a.GPIO.deserializeBinaryFromReader),e.setMdio(o);break;default:t.skipField()}}return e},proto.sys.EthRMII.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.EthRMII.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.EthRMII.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMdc())&&t.writeMessage(1,o,a.GPIO.serializeBinaryToWriter),null!=(o=e.getMdio())&&t.writeMessage(2,o,a.GPIO.serializeBinaryToWriter)},proto.sys.EthRMII.prototype.getMdc=function(){return s.Message.getWrapperField(this,a.GPIO,1)},proto.sys.EthRMII.prototype.setMdc=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.EthRMII.prototype.clearMdc=function(){return this.setMdc(void 0)},proto.sys.EthRMII.prototype.hasMdc=function(){return null!=s.Message.getField(this,1)},proto.sys.EthRMII.prototype.getMdio=function(){return s.Message.getWrapperField(this,a.GPIO,2)},proto.sys.EthRMII.prototype.setMdio=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.EthRMII.prototype.clearMdio=function(){return this.setMdio(void 0)},proto.sys.EthRMII.prototype.hasMdio=function(){return null!=s.Message.getField(this,2)},proto.sys.Eth.oneofGroups_=[[3,4]],proto.sys.Eth.EthtypeCase={ETHTYPE_NOT_SET:0,SPI:3,RMII:4},proto.sys.Eth.prototype.getEthtypeCase=function(){return s.Message.computeOneofCase(this,proto.sys.Eth.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Eth.prototype.toObject=function(e){return proto.sys.Eth.toObject(e,this)},proto.sys.Eth.toObject=function(e,t){var o,r={type:s.Message.getFieldWithDefault(t,1,0),common:(o=t.getCommon())&&proto.sys.EthCommon.toObject(e,o),spi:(o=t.getSpi())&&proto.sys.EthSPI.toObject(e,o),rmii:(o=t.getRmii())&&proto.sys.EthRMII.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Eth.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Eth;return proto.sys.Eth.deserializeBinaryFromReader(o,t)},proto.sys.Eth.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new proto.sys.EthCommon;t.readMessage(o,proto.sys.EthCommon.deserializeBinaryFromReader),e.setCommon(o);break;case 3:o=new proto.sys.EthSPI;t.readMessage(o,proto.sys.EthSPI.deserializeBinaryFromReader),e.setSpi(o);break;case 4:o=new proto.sys.EthRMII;t.readMessage(o,proto.sys.EthRMII.deserializeBinaryFromReader),e.setRmii(o);break;default:t.skipField()}}return e},proto.sys.Eth.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Eth.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Eth.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),null!=(o=e.getCommon())&&t.writeMessage(2,o,proto.sys.EthCommon.serializeBinaryToWriter),null!=(o=e.getSpi())&&t.writeMessage(3,o,proto.sys.EthSPI.serializeBinaryToWriter),null!=(o=e.getRmii())&&t.writeMessage(4,o,proto.sys.EthRMII.serializeBinaryToWriter)},proto.sys.Eth.prototype.getType=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Eth.prototype.setType=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Eth.prototype.getCommon=function(){return s.Message.getWrapperField(this,proto.sys.EthCommon,2)},proto.sys.Eth.prototype.setCommon=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Eth.prototype.clearCommon=function(){return this.setCommon(void 0)},proto.sys.Eth.prototype.hasCommon=function(){return null!=s.Message.getField(this,2)},proto.sys.Eth.prototype.getSpi=function(){return s.Message.getWrapperField(this,proto.sys.EthSPI,3)},proto.sys.Eth.prototype.setSpi=function(e){return s.Message.setOneofWrapperField(this,3,proto.sys.Eth.oneofGroups_[0],e)},proto.sys.Eth.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.sys.Eth.prototype.hasSpi=function(){return null!=s.Message.getField(this,3)},proto.sys.Eth.prototype.getRmii=function(){return s.Message.getWrapperField(this,proto.sys.EthRMII,4)},proto.sys.Eth.prototype.setRmii=function(e){return s.Message.setOneofWrapperField(this,4,proto.sys.Eth.oneofGroups_[0],e)},proto.sys.Eth.prototype.clearRmii=function(){return this.setRmii(void 0)},proto.sys.Eth.prototype.hasRmii=function(){return null!=s.Message.getField(this,4)},proto.sys.EthModelEnum={UNSPECIFIED_ETHMODEL:0,LAN8720:1,DM9051:2,W5500:3},proto.sys.EthType={UNSPECIFIED_ETH:0,SPI:1,RMII:2},r.object.extend(t,proto.sys)},7567:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(2038);r.object.extend(proto,n);var a=o(5465);r.object.extend(proto,a);var p=o(3021);r.object.extend(proto,p),r.exportSymbol("proto.sys.GPIO",null,i),r.exportSymbol("proto.sys.GPIOExp",null,i),r.exportSymbol("proto.sys.GPIOExp.ExptypeCase",null,i),r.exportSymbol("proto.sys.GPIOExpI2C",null,i),r.exportSymbol("proto.sys.GPIOExpModelEnum",null,i),r.exportSymbol("proto.sys.GPIOExpSPI",null,i),r.exportSymbol("proto.sys.Gpios",null,i),r.exportSymbol("proto.sys.LED",null,i),r.exportSymbol("proto.sys.LedTypesEnum",null,i),r.exportSymbol("proto.sys.LevelsEnum",null,i),proto.sys.GPIO=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.GPIO,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.GPIO.displayName="proto.sys.GPIO"),proto.sys.LED=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.LED,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.LED.displayName="proto.sys.LED"),proto.sys.Gpios=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Gpios,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Gpios.displayName="proto.sys.Gpios"),proto.sys.GPIOExpI2C=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.GPIOExpI2C,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.GPIOExpI2C.displayName="proto.sys.GPIOExpI2C"),proto.sys.GPIOExpSPI=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.GPIOExpSPI,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.GPIOExpSPI.displayName="proto.sys.GPIOExpSPI"),proto.sys.GPIOExp=function(e){s.Message.initialize(this,e,0,-1,null,proto.sys.GPIOExp.oneofGroups_)},r.inherits(proto.sys.GPIOExp,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.GPIOExp.displayName="proto.sys.GPIOExp"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.GPIO.prototype.toObject=function(e){return proto.sys.GPIO.toObject(e,this)},proto.sys.GPIO.toObject=function(e,t){var o={pin:s.Message.getFieldWithDefault(t,1,0),level:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.GPIO.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.GPIO;return proto.sys.GPIO.deserializeBinaryFromReader(o,t)},proto.sys.GPIO.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setPin(o);break;case 2:o=t.readEnum();e.setLevel(o);break;default:t.skipField()}}return e},proto.sys.GPIO.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.GPIO.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.GPIO.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getPin())&&t.writeInt32(1,o),0!==(o=e.getLevel())&&t.writeEnum(2,o)},proto.sys.GPIO.prototype.getPin=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.GPIO.prototype.setPin=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.GPIO.prototype.getLevel=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.GPIO.prototype.setLevel=function(e){return s.Message.setProto3EnumField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.LED.prototype.toObject=function(e){return proto.sys.LED.toObject(e,this)},proto.sys.LED.toObject=function(e,t){var o,r={gpio:(o=t.getGpio())&&proto.sys.GPIO.toObject(e,o),brightness:s.Message.getFieldWithDefault(t,2,0),ledType:s.Message.getFieldWithDefault(t,3,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.LED.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.LED;return proto.sys.LED.deserializeBinaryFromReader(o,t)},proto.sys.LED.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;case 2:o=t.readInt32();e.setBrightness(o);break;case 3:o=t.readEnum();e.setLedType(o);break;default:t.skipField()}}return e},proto.sys.LED.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.LED.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.LED.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpio())&&t.writeMessage(1,o,proto.sys.GPIO.serializeBinaryToWriter),0!==(o=e.getBrightness())&&t.writeInt32(2,o),0!==(o=e.getLedType())&&t.writeEnum(3,o)},proto.sys.LED.prototype.getGpio=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,1)},proto.sys.LED.prototype.setGpio=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.LED.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.sys.LED.prototype.hasGpio=function(){return null!=s.Message.getField(this,1)},proto.sys.LED.prototype.getBrightness=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.LED.prototype.setBrightness=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.LED.prototype.getLedType=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.LED.prototype.setLedType=function(e){return s.Message.setProto3EnumField(this,3,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Gpios.prototype.toObject=function(e){return proto.sys.Gpios.toObject(e,this)},proto.sys.Gpios.toObject=function(e,t){var o,s={greenled:(o=t.getGreenled())&&proto.sys.LED.toObject(e,o),redled:(o=t.getRedled())&&proto.sys.LED.toObject(e,o),audiojack:(o=t.getAudiojack())&&proto.sys.GPIO.toObject(e,o),amp:(o=t.getAmp())&&proto.sys.GPIO.toObject(e,o),power:(o=t.getPower())&&proto.sys.GPIO.toObject(e,o),jack:(o=t.getJack())&&proto.sys.GPIO.toObject(e,o),spkfault:(o=t.getSpkfault())&&proto.sys.GPIO.toObject(e,o),vcc:(o=t.getVcc())&&proto.sys.GPIO.toObject(e,o),gnd:(o=t.getGnd())&&proto.sys.GPIO.toObject(e,o)};return e&&(s.$jspbMessageInstance=t),s}),proto.sys.Gpios.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Gpios;return proto.sys.Gpios.deserializeBinaryFromReader(o,t)},proto.sys.Gpios.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.LED;t.readMessage(o,proto.sys.LED.deserializeBinaryFromReader),e.setGreenled(o);break;case 2:o=new proto.sys.LED;t.readMessage(o,proto.sys.LED.deserializeBinaryFromReader),e.setRedled(o);break;case 3:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setAudiojack(o);break;case 4:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setAmp(o);break;case 5:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setPower(o);break;case 6:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setJack(o);break;case 7:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setSpkfault(o);break;case 8:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setVcc(o);break;case 9:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setGnd(o);break;default:t.skipField()}}return e},proto.sys.Gpios.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Gpios.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Gpios.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGreenled())&&t.writeMessage(1,o,proto.sys.LED.serializeBinaryToWriter),null!=(o=e.getRedled())&&t.writeMessage(2,o,proto.sys.LED.serializeBinaryToWriter),null!=(o=e.getAudiojack())&&t.writeMessage(3,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getAmp())&&t.writeMessage(4,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getPower())&&t.writeMessage(5,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getJack())&&t.writeMessage(6,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getSpkfault())&&t.writeMessage(7,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getVcc())&&t.writeMessage(8,o,proto.sys.GPIO.serializeBinaryToWriter),null!=(o=e.getGnd())&&t.writeMessage(9,o,proto.sys.GPIO.serializeBinaryToWriter)},proto.sys.Gpios.prototype.getGreenled=function(){return s.Message.getWrapperField(this,proto.sys.LED,1)},proto.sys.Gpios.prototype.setGreenled=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Gpios.prototype.clearGreenled=function(){return this.setGreenled(void 0)},proto.sys.Gpios.prototype.hasGreenled=function(){return null!=s.Message.getField(this,1)},proto.sys.Gpios.prototype.getRedled=function(){return s.Message.getWrapperField(this,proto.sys.LED,2)},proto.sys.Gpios.prototype.setRedled=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Gpios.prototype.clearRedled=function(){return this.setRedled(void 0)},proto.sys.Gpios.prototype.hasRedled=function(){return null!=s.Message.getField(this,2)},proto.sys.Gpios.prototype.getAudiojack=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,3)},proto.sys.Gpios.prototype.setAudiojack=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.Gpios.prototype.clearAudiojack=function(){return this.setAudiojack(void 0)},proto.sys.Gpios.prototype.hasAudiojack=function(){return null!=s.Message.getField(this,3)},proto.sys.Gpios.prototype.getAmp=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,4)},proto.sys.Gpios.prototype.setAmp=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Gpios.prototype.clearAmp=function(){return this.setAmp(void 0)},proto.sys.Gpios.prototype.hasAmp=function(){return null!=s.Message.getField(this,4)},proto.sys.Gpios.prototype.getPower=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,5)},proto.sys.Gpios.prototype.setPower=function(e){return s.Message.setWrapperField(this,5,e)},proto.sys.Gpios.prototype.clearPower=function(){return this.setPower(void 0)},proto.sys.Gpios.prototype.hasPower=function(){return null!=s.Message.getField(this,5)},proto.sys.Gpios.prototype.getJack=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,6)},proto.sys.Gpios.prototype.setJack=function(e){return s.Message.setWrapperField(this,6,e)},proto.sys.Gpios.prototype.clearJack=function(){return this.setJack(void 0)},proto.sys.Gpios.prototype.hasJack=function(){return null!=s.Message.getField(this,6)},proto.sys.Gpios.prototype.getSpkfault=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,7)},proto.sys.Gpios.prototype.setSpkfault=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.Gpios.prototype.clearSpkfault=function(){return this.setSpkfault(void 0)},proto.sys.Gpios.prototype.hasSpkfault=function(){return null!=s.Message.getField(this,7)},proto.sys.Gpios.prototype.getVcc=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,8)},proto.sys.Gpios.prototype.setVcc=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.Gpios.prototype.clearVcc=function(){return this.setVcc(void 0)},proto.sys.Gpios.prototype.hasVcc=function(){return null!=s.Message.getField(this,8)},proto.sys.Gpios.prototype.getGnd=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,9)},proto.sys.Gpios.prototype.setGnd=function(e){return s.Message.setWrapperField(this,9,e)},proto.sys.Gpios.prototype.clearGnd=function(){return this.setGnd(void 0)},proto.sys.Gpios.prototype.hasGnd=function(){return null!=s.Message.getField(this,9)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.GPIOExpI2C.prototype.toObject=function(e){return proto.sys.GPIOExpI2C.toObject(e,this)},proto.sys.GPIOExpI2C.toObject=function(e,t){var o={port:s.Message.getFieldWithDefault(t,5,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.GPIOExpI2C.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.GPIOExpI2C;return proto.sys.GPIOExpI2C.deserializeBinaryFromReader(o,t)},proto.sys.GPIOExpI2C.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(5===t.getFieldNumber()){var o=t.readEnum();e.setPort(o)}else t.skipField()}return e},proto.sys.GPIOExpI2C.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.GPIOExpI2C.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.GPIOExpI2C.serializeBinaryToWriter=function(e,t){var o;0!==(o=e.getPort())&&t.writeEnum(5,o)},proto.sys.GPIOExpI2C.prototype.getPort=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.GPIOExpI2C.prototype.setPort=function(e){return s.Message.setProto3EnumField(this,5,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.GPIOExpSPI.prototype.toObject=function(e){return proto.sys.GPIOExpSPI.toObject(e,this)},proto.sys.GPIOExpSPI.toObject=function(e,t){var o,r={speed:s.Message.getFieldWithDefault(t,1,0),host:s.Message.getFieldWithDefault(t,2,0),cs:(o=t.getCs())&&proto.sys.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.GPIOExpSPI.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.GPIOExpSPI;return proto.sys.GPIOExpSPI.deserializeBinaryFromReader(o,t)},proto.sys.GPIOExpSPI.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setSpeed(o);break;case 2:o=t.readEnum();e.setHost(o);break;case 3:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setCs(o);break;default:t.skipField()}}return e},proto.sys.GPIOExpSPI.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.GPIOExpSPI.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.GPIOExpSPI.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getSpeed())&&t.writeInt32(1,o),0!==(o=e.getHost())&&t.writeEnum(2,o),null!=(o=e.getCs())&&t.writeMessage(3,o,proto.sys.GPIO.serializeBinaryToWriter)},proto.sys.GPIOExpSPI.prototype.getSpeed=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.GPIOExpSPI.prototype.setSpeed=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.GPIOExpSPI.prototype.getHost=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.GPIOExpSPI.prototype.setHost=function(e){return s.Message.setProto3EnumField(this,2,e)},proto.sys.GPIOExpSPI.prototype.getCs=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,3)},proto.sys.GPIOExpSPI.prototype.setCs=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.GPIOExpSPI.prototype.clearCs=function(){return this.setCs(void 0)},proto.sys.GPIOExpSPI.prototype.hasCs=function(){return null!=s.Message.getField(this,3)},proto.sys.GPIOExp.oneofGroups_=[[3,4]],proto.sys.GPIOExp.ExptypeCase={EXPTYPE_NOT_SET:0,I2C:3,SPI:4},proto.sys.GPIOExp.prototype.getExptypeCase=function(){return s.Message.computeOneofCase(this,proto.sys.GPIOExp.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.GPIOExp.prototype.toObject=function(e){return proto.sys.GPIOExp.toObject(e,this)},proto.sys.GPIOExp.toObject=function(e,t){var o,r={model:s.Message.getFieldWithDefault(t,1,0),addr:s.Message.getFieldWithDefault(t,2,0),i2c:(o=t.getI2c())&&proto.sys.GPIOExpI2C.toObject(e,o),spi:(o=t.getSpi())&&proto.sys.GPIOExpSPI.toObject(e,o),base:s.Message.getFieldWithDefault(t,5,0),count:s.Message.getFieldWithDefault(t,6,0),intr:(o=t.getIntr())&&proto.sys.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.GPIOExp.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.GPIOExp;return proto.sys.GPIOExp.deserializeBinaryFromReader(o,t)},proto.sys.GPIOExp.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setModel(o);break;case 2:o=t.readInt32();e.setAddr(o);break;case 3:o=new proto.sys.GPIOExpI2C;t.readMessage(o,proto.sys.GPIOExpI2C.deserializeBinaryFromReader),e.setI2c(o);break;case 4:o=new proto.sys.GPIOExpSPI;t.readMessage(o,proto.sys.GPIOExpSPI.deserializeBinaryFromReader),e.setSpi(o);break;case 5:o=t.readInt32();e.setBase(o);break;case 6:o=t.readInt32();e.setCount(o);break;case 7:o=new proto.sys.GPIO;t.readMessage(o,proto.sys.GPIO.deserializeBinaryFromReader),e.setIntr(o);break;default:t.skipField()}}return e},proto.sys.GPIOExp.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.GPIOExp.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.GPIOExp.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getModel())&&t.writeEnum(1,o),0!==(o=e.getAddr())&&t.writeInt32(2,o),null!=(o=e.getI2c())&&t.writeMessage(3,o,proto.sys.GPIOExpI2C.serializeBinaryToWriter),null!=(o=e.getSpi())&&t.writeMessage(4,o,proto.sys.GPIOExpSPI.serializeBinaryToWriter),0!==(o=e.getBase())&&t.writeInt32(5,o),0!==(o=e.getCount())&&t.writeInt32(6,o),null!=(o=e.getIntr())&&t.writeMessage(7,o,proto.sys.GPIO.serializeBinaryToWriter)},proto.sys.GPIOExp.prototype.getModel=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.GPIOExp.prototype.setModel=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.GPIOExp.prototype.getAddr=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.GPIOExp.prototype.setAddr=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.GPIOExp.prototype.getI2c=function(){return s.Message.getWrapperField(this,proto.sys.GPIOExpI2C,3)},proto.sys.GPIOExp.prototype.setI2c=function(e){return s.Message.setOneofWrapperField(this,3,proto.sys.GPIOExp.oneofGroups_[0],e)},proto.sys.GPIOExp.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.sys.GPIOExp.prototype.hasI2c=function(){return null!=s.Message.getField(this,3)},proto.sys.GPIOExp.prototype.getSpi=function(){return s.Message.getWrapperField(this,proto.sys.GPIOExpSPI,4)},proto.sys.GPIOExp.prototype.setSpi=function(e){return s.Message.setOneofWrapperField(this,4,proto.sys.GPIOExp.oneofGroups_[0],e)},proto.sys.GPIOExp.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.sys.GPIOExp.prototype.hasSpi=function(){return null!=s.Message.getField(this,4)},proto.sys.GPIOExp.prototype.getBase=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.GPIOExp.prototype.setBase=function(e){return s.Message.setProto3IntField(this,5,e)},proto.sys.GPIOExp.prototype.getCount=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.GPIOExp.prototype.setCount=function(e){return s.Message.setProto3IntField(this,6,e)},proto.sys.GPIOExp.prototype.getIntr=function(){return s.Message.getWrapperField(this,proto.sys.GPIO,7)},proto.sys.GPIOExp.prototype.setIntr=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.GPIOExp.prototype.clearIntr=function(){return this.setIntr(void 0)},proto.sys.GPIOExp.prototype.hasIntr=function(){return null!=s.Message.getField(this,7)},proto.sys.LevelsEnum={L_LOW:0,L_HIGH:1},proto.sys.LedTypesEnum={UNKNOWN:0,LED_TYPE_GPIO:1,LED_TYPE_WS2812:2},proto.sys.GPIOExpModelEnum={UNSPECIFIED_EXP:0,PCA9535:1,PCA85XX:2,MCP23017:3,MCP23S17:4},r.object.extend(t,proto.sys)},2035:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.sys.I2CBus",null,i),r.exportSymbol("proto.sys.I2CPortEnum",null,i),proto.sys.I2CBus=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.I2CBus,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.I2CBus.displayName="proto.sys.I2CBus"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.I2CBus.prototype.toObject=function(e){return proto.sys.I2CBus.toObject(e,this)},proto.sys.I2CBus.toObject=function(e,t){var o,r={port:s.Message.getFieldWithDefault(t,1,0),speed:s.Message.getFieldWithDefault(t,2,0),sda:(o=t.getSda())&&n.GPIO.toObject(e,o),scl:(o=t.getScl())&&n.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.I2CBus.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.I2CBus;return proto.sys.I2CBus.deserializeBinaryFromReader(o,t)},proto.sys.I2CBus.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setPort(o);break;case 2:o=t.readInt32();e.setSpeed(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setSda(o);break;case 4:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setScl(o);break;default:t.skipField()}}return e},proto.sys.I2CBus.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.I2CBus.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.I2CBus.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getPort())&&t.writeEnum(1,o),0!==(o=e.getSpeed())&&t.writeInt32(2,o),null!=(o=e.getSda())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter),null!=(o=e.getScl())&&t.writeMessage(4,o,n.GPIO.serializeBinaryToWriter)},proto.sys.I2CBus.prototype.getPort=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.I2CBus.prototype.setPort=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.I2CBus.prototype.getSpeed=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.I2CBus.prototype.setSpeed=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.I2CBus.prototype.getSda=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.I2CBus.prototype.setSda=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.I2CBus.prototype.clearSda=function(){return this.setSda(void 0)},proto.sys.I2CBus.prototype.hasSda=function(){return null!=s.Message.getField(this,3)},proto.sys.I2CBus.prototype.getScl=function(){return s.Message.getWrapperField(this,n.GPIO,4)},proto.sys.I2CBus.prototype.setScl=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.I2CBus.prototype.clearScl=function(){return this.setScl(void 0)},proto.sys.I2CBus.prototype.hasScl=function(){return null!=s.Message.getField(this,4)},proto.sys.I2CPortEnum={UNSPECIFIED_PORT:0,I2CPORT0:1,I2CPORT1:2},r.object.extend(t,proto.sys)},8395:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(5465);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.sys.Names",null,i),proto.sys.Names=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Names,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Names.displayName="proto.sys.Names"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.Names.prototype.toObject=function(e){return proto.sys.Names.toObject(e,this)},proto.sys.Names.toObject=function(e,t){var o={device:s.Message.getFieldWithDefault(t,1,""),airplay:s.Message.getFieldWithDefault(t,2,""),spotify:s.Message.getFieldWithDefault(t,3,""),bluetooth:s.Message.getFieldWithDefault(t,4,""),squeezelite:s.Message.getFieldWithDefault(t,5,""),wifiApName:s.Message.getFieldWithDefault(t,6,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Names.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Names;return proto.sys.Names.deserializeBinaryFromReader(o,t)},proto.sys.Names.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setDevice(o);break;case 2:o=t.readString();e.setAirplay(o);break;case 3:o=t.readString();e.setSpotify(o);break;case 4:o=t.readString();e.setBluetooth(o);break;case 5:o=t.readString();e.setSqueezelite(o);break;case 6:o=t.readString();e.setWifiApName(o);break;default:t.skipField()}}return e},proto.sys.Names.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Names.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Names.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getDevice()).length>0&&t.writeString(1,o),(o=e.getAirplay()).length>0&&t.writeString(2,o),(o=e.getSpotify()).length>0&&t.writeString(3,o),(o=e.getBluetooth()).length>0&&t.writeString(4,o),(o=e.getSqueezelite()).length>0&&t.writeString(5,o),(o=e.getWifiApName()).length>0&&t.writeString(6,o)},proto.sys.Names.prototype.getDevice=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.Names.prototype.setDevice=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.Names.prototype.getAirplay=function(){return s.Message.getFieldWithDefault(this,2,"")},proto.sys.Names.prototype.setAirplay=function(e){return s.Message.setProto3StringField(this,2,e)},proto.sys.Names.prototype.getSpotify=function(){return s.Message.getFieldWithDefault(this,3,"")},proto.sys.Names.prototype.setSpotify=function(e){return s.Message.setProto3StringField(this,3,e)},proto.sys.Names.prototype.getBluetooth=function(){return s.Message.getFieldWithDefault(this,4,"")},proto.sys.Names.prototype.setBluetooth=function(e){return s.Message.setProto3StringField(this,4,e)},proto.sys.Names.prototype.getSqueezelite=function(){return s.Message.getFieldWithDefault(this,5,"")},proto.sys.Names.prototype.setSqueezelite=function(e){return s.Message.setProto3StringField(this,5,e)},proto.sys.Names.prototype.getWifiApName=function(){return s.Message.getFieldWithDefault(this,6,"")},proto.sys.Names.prototype.setWifiApName=function(e){return s.Message.setProto3StringField(this,6,e)},r.object.extend(t,proto.sys)},5397:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(1134);r.object.extend(proto,n);var a=o(5465);r.object.extend(proto,a);var p=o(3021);r.object.extend(proto,p),r.exportSymbol("proto.sys.IP",null,i),r.exportSymbol("proto.sys.NetworkConfig",null,i),r.exportSymbol("proto.sys.NetworkConfig.PowerSaveTypeEnum",null,i),r.exportSymbol("proto.sys.Server",null,i),r.exportSymbol("proto.sys.WifiAP",null,i),r.exportSymbol("proto.sys.WifiAuthTypeEnum",null,i),r.exportSymbol("proto.sys.WifiRadioTypesEnum",null,i),r.exportSymbol("proto.sys.WifiSTAEntry",null,i),proto.sys.IP=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.IP,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.IP.displayName="proto.sys.IP"),proto.sys.WifiSTAEntry=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.WifiSTAEntry,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.WifiSTAEntry.displayName="proto.sys.WifiSTAEntry"),proto.sys.WifiAP=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.WifiAP,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.WifiAP.displayName="proto.sys.WifiAP"),proto.sys.Server=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Server,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Server.displayName="proto.sys.Server"),proto.sys.NetworkConfig=function(e){s.Message.initialize(this,e,0,-1,proto.sys.NetworkConfig.repeatedFields_,null)},r.inherits(proto.sys.NetworkConfig,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.NetworkConfig.displayName="proto.sys.NetworkConfig"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.IP.prototype.toObject=function(e){return proto.sys.IP.toObject(e,this)},proto.sys.IP.toObject=function(e,t){var o={ip:s.Message.getFieldWithDefault(t,14,""),netmask:s.Message.getFieldWithDefault(t,15,""),gw:s.Message.getFieldWithDefault(t,16,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.IP.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.IP;return proto.sys.IP.deserializeBinaryFromReader(o,t)},proto.sys.IP.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 14:var o=t.readString();e.setIp(o);break;case 15:o=t.readString();e.setNetmask(o);break;case 16:o=t.readString();e.setGw(o);break;default:t.skipField()}}return e},proto.sys.IP.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.IP.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.IP.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getIp()).length>0&&t.writeString(14,o),(o=e.getNetmask()).length>0&&t.writeString(15,o),(o=e.getGw()).length>0&&t.writeString(16,o)},proto.sys.IP.prototype.getIp=function(){return s.Message.getFieldWithDefault(this,14,"")},proto.sys.IP.prototype.setIp=function(e){return s.Message.setProto3StringField(this,14,e)},proto.sys.IP.prototype.getNetmask=function(){return s.Message.getFieldWithDefault(this,15,"")},proto.sys.IP.prototype.setNetmask=function(e){return s.Message.setProto3StringField(this,15,e)},proto.sys.IP.prototype.getGw=function(){return s.Message.getFieldWithDefault(this,16,"")},proto.sys.IP.prototype.setGw=function(e){return s.Message.setProto3StringField(this,16,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.WifiSTAEntry.prototype.toObject=function(e){return proto.sys.WifiSTAEntry.toObject(e,this)},proto.sys.WifiSTAEntry.toObject=function(e,t){var o,r={ssid:s.Message.getFieldWithDefault(t,1,""),bssid:s.Message.getFieldWithDefault(t,2,""),channel:s.Message.getFieldWithDefault(t,3,0),authType:s.Message.getFieldWithDefault(t,4,0),radioType:s.Message.getFieldWithDefault(t,5,0),lastTry:(o=t.getLastTry())&&n.Timestamp.toObject(e,o),lastSeen:(o=t.getLastSeen())&&n.Timestamp.toObject(e,o),connected:s.Message.getBooleanFieldWithDefault(t,8,!1),password:s.Message.getFieldWithDefault(t,9,""),rssi:s.Message.getFieldWithDefault(t,10,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.WifiSTAEntry.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.WifiSTAEntry;return proto.sys.WifiSTAEntry.deserializeBinaryFromReader(o,t)},proto.sys.WifiSTAEntry.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setSsid(o);break;case 2:o=t.readString();e.setBssid(o);break;case 3:o=t.readUint32();e.setChannel(o);break;case 4:o=t.readEnum();e.setAuthType(o);break;case 5:o=t.readEnum();e.setRadioType(o);break;case 6:o=new n.Timestamp;t.readMessage(o,n.Timestamp.deserializeBinaryFromReader),e.setLastTry(o);break;case 7:o=new n.Timestamp;t.readMessage(o,n.Timestamp.deserializeBinaryFromReader),e.setLastSeen(o);break;case 8:o=t.readBool();e.setConnected(o);break;case 9:o=t.readString();e.setPassword(o);break;case 10:o=t.readUint32();e.setRssi(o);break;default:t.skipField()}}return e},proto.sys.WifiSTAEntry.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.WifiSTAEntry.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.WifiSTAEntry.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getSsid()).length>0&&t.writeString(1,o),(o=e.getBssid()).length>0&&t.writeString(2,o),0!==(o=e.getChannel())&&t.writeUint32(3,o),0!==(o=e.getAuthType())&&t.writeEnum(4,o),0!==(o=e.getRadioType())&&t.writeEnum(5,o),null!=(o=e.getLastTry())&&t.writeMessage(6,o,n.Timestamp.serializeBinaryToWriter),null!=(o=e.getLastSeen())&&t.writeMessage(7,o,n.Timestamp.serializeBinaryToWriter),(o=e.getConnected())&&t.writeBool(8,o),(o=e.getPassword()).length>0&&t.writeString(9,o),0!==(o=e.getRssi())&&t.writeUint32(10,o)},proto.sys.WifiSTAEntry.prototype.getSsid=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.WifiSTAEntry.prototype.setSsid=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.WifiSTAEntry.prototype.getBssid=function(){return s.Message.getFieldWithDefault(this,2,"")},proto.sys.WifiSTAEntry.prototype.setBssid=function(e){return s.Message.setProto3StringField(this,2,e)},proto.sys.WifiSTAEntry.prototype.getChannel=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.WifiSTAEntry.prototype.setChannel=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.WifiSTAEntry.prototype.getAuthType=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.WifiSTAEntry.prototype.setAuthType=function(e){return s.Message.setProto3EnumField(this,4,e)},proto.sys.WifiSTAEntry.prototype.getRadioType=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.WifiSTAEntry.prototype.setRadioType=function(e){return s.Message.setProto3EnumField(this,5,e)},proto.sys.WifiSTAEntry.prototype.getLastTry=function(){return s.Message.getWrapperField(this,n.Timestamp,6)},proto.sys.WifiSTAEntry.prototype.setLastTry=function(e){return s.Message.setWrapperField(this,6,e)},proto.sys.WifiSTAEntry.prototype.clearLastTry=function(){return this.setLastTry(void 0)},proto.sys.WifiSTAEntry.prototype.hasLastTry=function(){return null!=s.Message.getField(this,6)},proto.sys.WifiSTAEntry.prototype.getLastSeen=function(){return s.Message.getWrapperField(this,n.Timestamp,7)},proto.sys.WifiSTAEntry.prototype.setLastSeen=function(e){return s.Message.setWrapperField(this,7,e)},proto.sys.WifiSTAEntry.prototype.clearLastSeen=function(){return this.setLastSeen(void 0)},proto.sys.WifiSTAEntry.prototype.hasLastSeen=function(){return null!=s.Message.getField(this,7)},proto.sys.WifiSTAEntry.prototype.getConnected=function(){return s.Message.getBooleanFieldWithDefault(this,8,!1)},proto.sys.WifiSTAEntry.prototype.setConnected=function(e){return s.Message.setProto3BooleanField(this,8,e)},proto.sys.WifiSTAEntry.prototype.getPassword=function(){return s.Message.getFieldWithDefault(this,9,"")},proto.sys.WifiSTAEntry.prototype.setPassword=function(e){return s.Message.setProto3StringField(this,9,e)},proto.sys.WifiSTAEntry.prototype.getRssi=function(){return s.Message.getFieldWithDefault(this,10,0)},proto.sys.WifiSTAEntry.prototype.setRssi=function(e){return s.Message.setProto3IntField(this,10,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.WifiAP.prototype.toObject=function(e){return proto.sys.WifiAP.toObject(e,this)},proto.sys.WifiAP.toObject=function(e,t){var o,r={ip:(o=t.getIp())&&proto.sys.IP.toObject(e,o),password:s.Message.getFieldWithDefault(t,2,""),channel:s.Message.getFieldWithDefault(t,3,0),authMode:s.Message.getFieldWithDefault(t,4,0),hidden:s.Message.getBooleanFieldWithDefault(t,5,!1),maxConnection:s.Message.getFieldWithDefault(t,6,0),beaconInterval:s.Message.getFieldWithDefault(t,7,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.WifiAP.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.WifiAP;return proto.sys.WifiAP.deserializeBinaryFromReader(o,t)},proto.sys.WifiAP.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.IP;t.readMessage(o,proto.sys.IP.deserializeBinaryFromReader),e.setIp(o);break;case 2:o=t.readString();e.setPassword(o);break;case 3:o=t.readUint32();e.setChannel(o);break;case 4:o=t.readEnum();e.setAuthMode(o);break;case 5:o=t.readBool();e.setHidden(o);break;case 6:o=t.readUint32();e.setMaxConnection(o);break;case 7:o=t.readUint32();e.setBeaconInterval(o);break;default:t.skipField()}}return e},proto.sys.WifiAP.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.WifiAP.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.WifiAP.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getIp())&&t.writeMessage(1,o,proto.sys.IP.serializeBinaryToWriter),(o=e.getPassword()).length>0&&t.writeString(2,o),0!==(o=e.getChannel())&&t.writeUint32(3,o),0!==(o=e.getAuthMode())&&t.writeEnum(4,o),(o=e.getHidden())&&t.writeBool(5,o),0!==(o=e.getMaxConnection())&&t.writeUint32(6,o),0!==(o=e.getBeaconInterval())&&t.writeUint32(7,o)},proto.sys.WifiAP.prototype.getIp=function(){return s.Message.getWrapperField(this,proto.sys.IP,1)},proto.sys.WifiAP.prototype.setIp=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.WifiAP.prototype.clearIp=function(){return this.setIp(void 0)},proto.sys.WifiAP.prototype.hasIp=function(){return null!=s.Message.getField(this,1)},proto.sys.WifiAP.prototype.getPassword=function(){return s.Message.getFieldWithDefault(this,2,"")},proto.sys.WifiAP.prototype.setPassword=function(e){return s.Message.setProto3StringField(this,2,e)},proto.sys.WifiAP.prototype.getChannel=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.WifiAP.prototype.setChannel=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.WifiAP.prototype.getAuthMode=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.WifiAP.prototype.setAuthMode=function(e){return s.Message.setProto3EnumField(this,4,e)},proto.sys.WifiAP.prototype.getHidden=function(){return s.Message.getBooleanFieldWithDefault(this,5,!1)},proto.sys.WifiAP.prototype.setHidden=function(e){return s.Message.setProto3BooleanField(this,5,e)},proto.sys.WifiAP.prototype.getMaxConnection=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.WifiAP.prototype.setMaxConnection=function(e){return s.Message.setProto3IntField(this,6,e)},proto.sys.WifiAP.prototype.getBeaconInterval=function(){return s.Message.getFieldWithDefault(this,7,0)},proto.sys.WifiAP.prototype.setBeaconInterval=function(e){return s.Message.setProto3IntField(this,7,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Server.prototype.toObject=function(e){return proto.sys.Server.toObject(e,this)},proto.sys.Server.toObject=function(e,t){var o={cport:s.Message.getFieldWithDefault(t,1,0),port:s.Message.getFieldWithDefault(t,2,0),ip:s.Message.getFieldWithDefault(t,3,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Server.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Server;return proto.sys.Server.deserializeBinaryFromReader(o,t)},proto.sys.Server.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setCport(o);break;case 2:o=t.readInt32();e.setPort(o);break;case 3:o=t.readString();e.setIp(o);break;default:t.skipField()}}return e},proto.sys.Server.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Server.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Server.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getCport())&&t.writeInt32(1,o),0!==(o=e.getPort())&&t.writeInt32(2,o),(o=e.getIp()).length>0&&t.writeString(3,o)},proto.sys.Server.prototype.getCport=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Server.prototype.setCport=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.Server.prototype.getPort=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.Server.prototype.setPort=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.Server.prototype.getIp=function(){return s.Message.getFieldWithDefault(this,3,"")},proto.sys.Server.prototype.setIp=function(e){return s.Message.setProto3StringField(this,3,e)},proto.sys.NetworkConfig.repeatedFields_=[3],s.Message.GENERATE_TO_OBJECT&&(proto.sys.NetworkConfig.prototype.toObject=function(e){return proto.sys.NetworkConfig.toObject(e,this)},proto.sys.NetworkConfig.toObject=function(e,t){var o,r={disableDhcp:s.Message.getBooleanFieldWithDefault(t,1,!1),manualIp:(o=t.getManualIp())&&proto.sys.IP.toObject(e,o),credentialsList:s.Message.toObjectList(t.getCredentialsList(),proto.sys.WifiSTAEntry.toObject,e),ap:(o=t.getAp())&&proto.sys.WifiAP.toObject(e,o),staPollingMaxS:s.Message.getFieldWithDefault(t,5,0),apDurationS:s.Message.getFieldWithDefault(t,6,0),staPollingMinS:s.Message.getFieldWithDefault(t,7,0),dhcpTmoutS:s.Message.getFieldWithDefault(t,8,0),ethBoot:s.Message.getBooleanFieldWithDefault(t,9,!1),maxWifiRetry:s.Message.getFieldWithDefault(t,10,0),maxApNum:s.Message.getFieldWithDefault(t,11,0),maxSsidSize:s.Message.getFieldWithDefault(t,12,0),maxPasswordSize:s.Message.getFieldWithDefault(t,13,0),taskPriority:s.Message.getFieldWithDefault(t,14,0),powerSaveMode:s.Message.getFieldWithDefault(t,15,0),maxInitialWifiAttempt:s.Message.getFieldWithDefault(t,16,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.NetworkConfig.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.NetworkConfig;return proto.sys.NetworkConfig.deserializeBinaryFromReader(o,t)},proto.sys.NetworkConfig.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setDisableDhcp(o);break;case 2:o=new proto.sys.IP;t.readMessage(o,proto.sys.IP.deserializeBinaryFromReader),e.setManualIp(o);break;case 3:o=new proto.sys.WifiSTAEntry;t.readMessage(o,proto.sys.WifiSTAEntry.deserializeBinaryFromReader),e.addCredentials(o);break;case 4:o=new proto.sys.WifiAP;t.readMessage(o,proto.sys.WifiAP.deserializeBinaryFromReader),e.setAp(o);break;case 5:o=t.readUint32();e.setStaPollingMaxS(o);break;case 6:o=t.readUint32();e.setApDurationS(o);break;case 7:o=t.readUint32();e.setStaPollingMinS(o);break;case 8:o=t.readUint32();e.setDhcpTmoutS(o);break;case 9:o=t.readBool();e.setEthBoot(o);break;case 10:o=t.readUint32();e.setMaxWifiRetry(o);break;case 11:o=t.readUint32();e.setMaxApNum(o);break;case 12:o=t.readUint32();e.setMaxSsidSize(o);break;case 13:o=t.readUint32();e.setMaxPasswordSize(o);break;case 14:o=t.readUint32();e.setTaskPriority(o);break;case 15:o=t.readEnum();e.setPowerSaveMode(o);break;case 16:o=t.readUint32();e.setMaxInitialWifiAttempt(o);break;default:t.skipField()}}return e},proto.sys.NetworkConfig.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.NetworkConfig.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.NetworkConfig.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getDisableDhcp())&&t.writeBool(1,o),null!=(o=e.getManualIp())&&t.writeMessage(2,o,proto.sys.IP.serializeBinaryToWriter),(o=e.getCredentialsList()).length>0&&t.writeRepeatedMessage(3,o,proto.sys.WifiSTAEntry.serializeBinaryToWriter),null!=(o=e.getAp())&&t.writeMessage(4,o,proto.sys.WifiAP.serializeBinaryToWriter),0!==(o=e.getStaPollingMaxS())&&t.writeUint32(5,o),0!==(o=e.getApDurationS())&&t.writeUint32(6,o),0!==(o=e.getStaPollingMinS())&&t.writeUint32(7,o),0!==(o=e.getDhcpTmoutS())&&t.writeUint32(8,o),(o=e.getEthBoot())&&t.writeBool(9,o),0!==(o=e.getMaxWifiRetry())&&t.writeUint32(10,o),0!==(o=e.getMaxApNum())&&t.writeUint32(11,o),0!==(o=e.getMaxSsidSize())&&t.writeUint32(12,o),0!==(o=e.getMaxPasswordSize())&&t.writeUint32(13,o),0!==(o=e.getTaskPriority())&&t.writeUint32(14,o),0!==(o=e.getPowerSaveMode())&&t.writeEnum(15,o),0!==(o=e.getMaxInitialWifiAttempt())&&t.writeUint32(16,o)},proto.sys.NetworkConfig.PowerSaveTypeEnum={WIFI_PS_NONE:0,WIFI_PS_MIN_MODEM:1,WIFI_PS_MAX_MODEM:2},proto.sys.NetworkConfig.prototype.getDisableDhcp=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.NetworkConfig.prototype.setDisableDhcp=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.NetworkConfig.prototype.getManualIp=function(){return s.Message.getWrapperField(this,proto.sys.IP,2)},proto.sys.NetworkConfig.prototype.setManualIp=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.NetworkConfig.prototype.clearManualIp=function(){return this.setManualIp(void 0)},proto.sys.NetworkConfig.prototype.hasManualIp=function(){return null!=s.Message.getField(this,2)},proto.sys.NetworkConfig.prototype.getCredentialsList=function(){return s.Message.getRepeatedWrapperField(this,proto.sys.WifiSTAEntry,3)},proto.sys.NetworkConfig.prototype.setCredentialsList=function(e){return s.Message.setRepeatedWrapperField(this,3,e)},proto.sys.NetworkConfig.prototype.addCredentials=function(e,t){return s.Message.addToRepeatedWrapperField(this,3,e,proto.sys.WifiSTAEntry,t)},proto.sys.NetworkConfig.prototype.clearCredentialsList=function(){return this.setCredentialsList([])},proto.sys.NetworkConfig.prototype.getAp=function(){return s.Message.getWrapperField(this,proto.sys.WifiAP,4)},proto.sys.NetworkConfig.prototype.setAp=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.NetworkConfig.prototype.clearAp=function(){return this.setAp(void 0)},proto.sys.NetworkConfig.prototype.hasAp=function(){return null!=s.Message.getField(this,4)},proto.sys.NetworkConfig.prototype.getStaPollingMaxS=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.NetworkConfig.prototype.setStaPollingMaxS=function(e){return s.Message.setProto3IntField(this,5,e)},proto.sys.NetworkConfig.prototype.getApDurationS=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.NetworkConfig.prototype.setApDurationS=function(e){return s.Message.setProto3IntField(this,6,e)},proto.sys.NetworkConfig.prototype.getStaPollingMinS=function(){return s.Message.getFieldWithDefault(this,7,0)},proto.sys.NetworkConfig.prototype.setStaPollingMinS=function(e){return s.Message.setProto3IntField(this,7,e)},proto.sys.NetworkConfig.prototype.getDhcpTmoutS=function(){return s.Message.getFieldWithDefault(this,8,0)},proto.sys.NetworkConfig.prototype.setDhcpTmoutS=function(e){return s.Message.setProto3IntField(this,8,e)},proto.sys.NetworkConfig.prototype.getEthBoot=function(){return s.Message.getBooleanFieldWithDefault(this,9,!1)},proto.sys.NetworkConfig.prototype.setEthBoot=function(e){return s.Message.setProto3BooleanField(this,9,e)},proto.sys.NetworkConfig.prototype.getMaxWifiRetry=function(){return s.Message.getFieldWithDefault(this,10,0)},proto.sys.NetworkConfig.prototype.setMaxWifiRetry=function(e){return s.Message.setProto3IntField(this,10,e)},proto.sys.NetworkConfig.prototype.getMaxApNum=function(){return s.Message.getFieldWithDefault(this,11,0)},proto.sys.NetworkConfig.prototype.setMaxApNum=function(e){return s.Message.setProto3IntField(this,11,e)},proto.sys.NetworkConfig.prototype.getMaxSsidSize=function(){return s.Message.getFieldWithDefault(this,12,0)},proto.sys.NetworkConfig.prototype.setMaxSsidSize=function(e){return s.Message.setProto3IntField(this,12,e)},proto.sys.NetworkConfig.prototype.getMaxPasswordSize=function(){return s.Message.getFieldWithDefault(this,13,0)},proto.sys.NetworkConfig.prototype.setMaxPasswordSize=function(e){return s.Message.setProto3IntField(this,13,e)},proto.sys.NetworkConfig.prototype.getTaskPriority=function(){return s.Message.getFieldWithDefault(this,14,0)},proto.sys.NetworkConfig.prototype.setTaskPriority=function(e){return s.Message.setProto3IntField(this,14,e)},proto.sys.NetworkConfig.prototype.getPowerSaveMode=function(){return s.Message.getFieldWithDefault(this,15,0)},proto.sys.NetworkConfig.prototype.setPowerSaveMode=function(e){return s.Message.setProto3EnumField(this,15,e)},proto.sys.NetworkConfig.prototype.getMaxInitialWifiAttempt=function(){return s.Message.getFieldWithDefault(this,16,0)},proto.sys.NetworkConfig.prototype.setMaxInitialWifiAttempt=function(e){return s.Message.setProto3IntField(this,16,e)},proto.sys.WifiAuthTypeEnum={AUTH_UNKNOWN:0,AUTH_OPEN:1,AUTH_WEP:2,AUTH_WPA_PSK:3,AUTH_WPA2_PSK:4,AUTH_WPA_WPA2_PSK:5,AUTH_WPA2_ENTERPRISE:6,AUTH_WPA3_PSK:7,AUTH_WPA2_WPA3_PSK:8,AUTH_WAPI_PSK:9},proto.sys.WifiRadioTypesEnum={PHY_UNKNOWN:0,PHY_11B:1,PHY_11G:2,PHY_11N:3,PHY_LR:4,PHY_WPS:5,PHY_FTM_RESPONDER:6,PHY_FTM_INITIATOR:7},r.object.extend(t,proto.sys)},3359:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(7567);r.object.extend(proto,n);var a=o(3353);r.object.extend(proto,a);var p=o(3043);r.object.extend(proto,p);var l=o(125);r.object.extend(proto,l);var u=o(1480);r.object.extend(proto,u);var y=o(190);r.object.extend(proto,y);var d=o(3021);r.object.extend(proto,d);var c=o(5465);r.object.extend(proto,c),r.exportSymbol("proto.sys.BluetoothSink",null,i),r.exportSymbol("proto.sys.Metadata",null,i),r.exportSymbol("proto.sys.Services",null,i),r.exportSymbol("proto.sys.SleepService",null,i),r.exportSymbol("proto.sys.Telnet",null,i),r.exportSymbol("proto.sys.TelnetEnableEnum",null,i),proto.sys.SleepService=function(e){s.Message.initialize(this,e,0,-1,proto.sys.SleepService.repeatedFields_,null)},r.inherits(proto.sys.SleepService,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.SleepService.displayName="proto.sys.SleepService"),proto.sys.Telnet=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Telnet,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Telnet.displayName="proto.sys.Telnet"),proto.sys.Metadata=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Metadata,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Metadata.displayName="proto.sys.Metadata"),proto.sys.BluetoothSink=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.BluetoothSink,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.BluetoothSink.displayName="proto.sys.BluetoothSink"),proto.sys.Services=function(e){s.Message.initialize(this,e,0,-1,proto.sys.Services.repeatedFields_,null)},r.inherits(proto.sys.Services,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Services.displayName="proto.sys.Services"),proto.sys.SleepService.repeatedFields_=[4,5],s.Message.GENERATE_TO_OBJECT&&(proto.sys.SleepService.prototype.toObject=function(e){return proto.sys.SleepService.toObject(e,this)},proto.sys.SleepService.toObject=function(e,t){var o,r={delay:s.Message.getFieldWithDefault(t,1,0),spurious:s.Message.getFieldWithDefault(t,2,0),sleep:(o=t.getSleep())&&n.GPIO.toObject(e,o),wakeList:s.Message.toObjectList(t.getWakeList(),n.GPIO.toObject,e),rtcList:s.Message.toObjectList(t.getRtcList(),n.GPIO.toObject,e),batt:s.Message.getFloatingPointFieldWithDefault(t,6,0)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.SleepService.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.SleepService;return proto.sys.SleepService.deserializeBinaryFromReader(o,t)},proto.sys.SleepService.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readUint32();e.setDelay(o);break;case 2:o=t.readInt32();e.setSpurious(o);break;case 3:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.setSleep(o);break;case 4:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.addWake(o);break;case 5:o=new n.GPIO;t.readMessage(o,n.GPIO.deserializeBinaryFromReader),e.addRtc(o);break;case 6:o=t.readFloat();e.setBatt(o);break;default:t.skipField()}}return e},proto.sys.SleepService.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.SleepService.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.SleepService.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getDelay())&&t.writeUint32(1,o),0!==(o=e.getSpurious())&&t.writeInt32(2,o),null!=(o=e.getSleep())&&t.writeMessage(3,o,n.GPIO.serializeBinaryToWriter),(o=e.getWakeList()).length>0&&t.writeRepeatedMessage(4,o,n.GPIO.serializeBinaryToWriter),(o=e.getRtcList()).length>0&&t.writeRepeatedMessage(5,o,n.GPIO.serializeBinaryToWriter),0!==(o=e.getBatt())&&t.writeFloat(6,o)},proto.sys.SleepService.prototype.getDelay=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.SleepService.prototype.setDelay=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.SleepService.prototype.getSpurious=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.SleepService.prototype.setSpurious=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.SleepService.prototype.getSleep=function(){return s.Message.getWrapperField(this,n.GPIO,3)},proto.sys.SleepService.prototype.setSleep=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.SleepService.prototype.clearSleep=function(){return this.setSleep(void 0)},proto.sys.SleepService.prototype.hasSleep=function(){return null!=s.Message.getField(this,3)},proto.sys.SleepService.prototype.getWakeList=function(){return s.Message.getRepeatedWrapperField(this,n.GPIO,4)},proto.sys.SleepService.prototype.setWakeList=function(e){return s.Message.setRepeatedWrapperField(this,4,e)},proto.sys.SleepService.prototype.addWake=function(e,t){return s.Message.addToRepeatedWrapperField(this,4,e,proto.sys.GPIO,t)},proto.sys.SleepService.prototype.clearWakeList=function(){return this.setWakeList([])},proto.sys.SleepService.prototype.getRtcList=function(){return s.Message.getRepeatedWrapperField(this,n.GPIO,5)},proto.sys.SleepService.prototype.setRtcList=function(e){return s.Message.setRepeatedWrapperField(this,5,e)},proto.sys.SleepService.prototype.addRtc=function(e,t){return s.Message.addToRepeatedWrapperField(this,5,e,proto.sys.GPIO,t)},proto.sys.SleepService.prototype.clearRtcList=function(){return this.setRtcList([])},proto.sys.SleepService.prototype.getBatt=function(){return s.Message.getFloatingPointFieldWithDefault(this,6,0)},proto.sys.SleepService.prototype.setBatt=function(e){return s.Message.setProto3FloatField(this,6,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Telnet.prototype.toObject=function(e){return proto.sys.Telnet.toObject(e,this)},proto.sys.Telnet.toObject=function(e,t){var o={enable:s.Message.getFieldWithDefault(t,1,0),block:s.Message.getFieldWithDefault(t,2,0),buffer:s.Message.getFieldWithDefault(t,3,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Telnet.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Telnet;return proto.sys.Telnet.deserializeBinaryFromReader(o,t)},proto.sys.Telnet.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setEnable(o);break;case 2:o=t.readUint32();e.setBlock(o);break;case 3:o=t.readUint32();e.setBuffer(o);break;default:t.skipField()}}return e},proto.sys.Telnet.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Telnet.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Telnet.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getEnable())&&t.writeEnum(1,o),0!==(o=e.getBlock())&&t.writeUint32(2,o),0!==(o=e.getBuffer())&&t.writeUint32(3,o)},proto.sys.Telnet.prototype.getEnable=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Telnet.prototype.setEnable=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Telnet.prototype.getBlock=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.Telnet.prototype.setBlock=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.Telnet.prototype.getBuffer=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.Telnet.prototype.setBuffer=function(e){return s.Message.setProto3IntField(this,3,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.Metadata.prototype.toObject=function(e){return proto.sys.Metadata.toObject(e,this)},proto.sys.Metadata.toObject=function(e,t){var o,r={format:s.Message.getFieldWithDefault(t,1,""),speed:s.Message.getFieldWithDefault(t,2,0),pause:s.Message.getFieldWithDefault(t,3,0),artwork:(o=t.getArtwork())&&a.Artwork.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Metadata.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Metadata;return proto.sys.Metadata.deserializeBinaryFromReader(o,t)},proto.sys.Metadata.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setFormat(o);break;case 2:o=t.readUint32();e.setSpeed(o);break;case 3:o=t.readUint32();e.setPause(o);break;case 4:o=new a.Artwork;t.readMessage(o,a.Artwork.deserializeBinaryFromReader),e.setArtwork(o);break;default:t.skipField()}}return e},proto.sys.Metadata.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Metadata.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Metadata.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getFormat()).length>0&&t.writeString(1,o),0!==(o=e.getSpeed())&&t.writeUint32(2,o),0!==(o=e.getPause())&&t.writeUint32(3,o),null!=(o=e.getArtwork())&&t.writeMessage(4,o,a.Artwork.serializeBinaryToWriter)},proto.sys.Metadata.prototype.getFormat=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.Metadata.prototype.setFormat=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.Metadata.prototype.getSpeed=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.Metadata.prototype.setSpeed=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.Metadata.prototype.getPause=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.Metadata.prototype.setPause=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.Metadata.prototype.getArtwork=function(){return s.Message.getWrapperField(this,a.Artwork,4)},proto.sys.Metadata.prototype.setArtwork=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Metadata.prototype.clearArtwork=function(){return this.setArtwork(void 0)},proto.sys.Metadata.prototype.hasArtwork=function(){return null!=s.Message.getField(this,4)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.BluetoothSink.prototype.toObject=function(e){return proto.sys.BluetoothSink.toObject(e,this)},proto.sys.BluetoothSink.toObject=function(e,t){var o={enabled:s.Message.getBooleanFieldWithDefault(t,1,!1),volume:s.Message.getFieldWithDefault(t,2,0),pin:s.Message.getFieldWithDefault(t,3,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.BluetoothSink.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.BluetoothSink;return proto.sys.BluetoothSink.deserializeBinaryFromReader(o,t)},proto.sys.BluetoothSink.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnabled(o);break;case 2:o=t.readUint32();e.setVolume(o);break;case 3:o=t.readString();e.setPin(o);break;default:t.skipField()}}return e},proto.sys.BluetoothSink.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.BluetoothSink.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.BluetoothSink.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnabled())&&t.writeBool(1,o),0!==(o=e.getVolume())&&t.writeUint32(2,o),(o=e.getPin()).length>0&&t.writeString(3,o)},proto.sys.BluetoothSink.prototype.getEnabled=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.BluetoothSink.prototype.setEnabled=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.BluetoothSink.prototype.getVolume=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.BluetoothSink.prototype.setVolume=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.BluetoothSink.prototype.getPin=function(){return s.Message.getFieldWithDefault(this,3,"")},proto.sys.BluetoothSink.prototype.setPin=function(e){return s.Message.setProto3StringField(this,3,e)},proto.sys.Services.repeatedFields_=[6],s.Message.GENERATE_TO_OBJECT&&(proto.sys.Services.prototype.toObject=function(e){return proto.sys.Services.toObject(e,this)},proto.sys.Services.toObject=function(e,t){var o,r={metadata:(o=t.getMetadata())&&proto.sys.Metadata.toObject(e,o),sleep:(o=t.getSleep())&&proto.sys.SleepService.toObject(e,o),cspot:(o=t.getCspot())&&p.Spotify.toObject(e,o),airplay:(o=t.getAirplay())&&l.AirPlay.toObject(e,o),squeezeliteProfilesList:s.Message.toObjectList(t.getSqueezeliteProfilesList(),u.SqueezeliteProfile.toObject,e),releaseUrl:s.Message.getFieldWithDefault(t,7,""),btSink:(o=t.getBtSink())&&proto.sys.BluetoothSink.toObject(e,o),statistics:s.Message.getBooleanFieldWithDefault(t,9,!1),telnet:(o=t.getTelnet())&&proto.sys.Telnet.toObject(e,o),equalizer:(o=t.getEqualizer())&&y.Equalizer.toObject(e,o),currentProfile:s.Message.getFieldWithDefault(t,12,"")};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Services.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Services;return proto.sys.Services.deserializeBinaryFromReader(o,t)},proto.sys.Services.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.sys.Metadata;t.readMessage(o,proto.sys.Metadata.deserializeBinaryFromReader),e.setMetadata(o);break;case 2:o=new proto.sys.SleepService;t.readMessage(o,proto.sys.SleepService.deserializeBinaryFromReader),e.setSleep(o);break;case 4:o=new p.Spotify;t.readMessage(o,p.Spotify.deserializeBinaryFromReader),e.setCspot(o);break;case 5:o=new l.AirPlay;t.readMessage(o,l.AirPlay.deserializeBinaryFromReader),e.setAirplay(o);break;case 6:o=new u.SqueezeliteProfile;t.readMessage(o,u.SqueezeliteProfile.deserializeBinaryFromReader),e.addSqueezeliteProfiles(o);break;case 7:o=t.readString();e.setReleaseUrl(o);break;case 8:o=new proto.sys.BluetoothSink;t.readMessage(o,proto.sys.BluetoothSink.deserializeBinaryFromReader),e.setBtSink(o);break;case 9:o=t.readBool();e.setStatistics(o);break;case 10:o=new proto.sys.Telnet;t.readMessage(o,proto.sys.Telnet.deserializeBinaryFromReader),e.setTelnet(o);break;case 11:o=new y.Equalizer;t.readMessage(o,y.Equalizer.deserializeBinaryFromReader),e.setEqualizer(o);break;case 12:o=t.readString();e.setCurrentProfile(o);break;default:t.skipField()}}return e},proto.sys.Services.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Services.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Services.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMetadata())&&t.writeMessage(1,o,proto.sys.Metadata.serializeBinaryToWriter),null!=(o=e.getSleep())&&t.writeMessage(2,o,proto.sys.SleepService.serializeBinaryToWriter),null!=(o=e.getCspot())&&t.writeMessage(4,o,p.Spotify.serializeBinaryToWriter),null!=(o=e.getAirplay())&&t.writeMessage(5,o,l.AirPlay.serializeBinaryToWriter),(o=e.getSqueezeliteProfilesList()).length>0&&t.writeRepeatedMessage(6,o,u.SqueezeliteProfile.serializeBinaryToWriter),(o=e.getReleaseUrl()).length>0&&t.writeString(7,o),null!=(o=e.getBtSink())&&t.writeMessage(8,o,proto.sys.BluetoothSink.serializeBinaryToWriter),(o=e.getStatistics())&&t.writeBool(9,o),null!=(o=e.getTelnet())&&t.writeMessage(10,o,proto.sys.Telnet.serializeBinaryToWriter),null!=(o=e.getEqualizer())&&t.writeMessage(11,o,y.Equalizer.serializeBinaryToWriter),(o=e.getCurrentProfile()).length>0&&t.writeString(12,o)},proto.sys.Services.prototype.getMetadata=function(){return s.Message.getWrapperField(this,proto.sys.Metadata,1)},proto.sys.Services.prototype.setMetadata=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Services.prototype.clearMetadata=function(){return this.setMetadata(void 0)},proto.sys.Services.prototype.hasMetadata=function(){return null!=s.Message.getField(this,1)},proto.sys.Services.prototype.getSleep=function(){return s.Message.getWrapperField(this,proto.sys.SleepService,2)},proto.sys.Services.prototype.setSleep=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Services.prototype.clearSleep=function(){return this.setSleep(void 0)},proto.sys.Services.prototype.hasSleep=function(){return null!=s.Message.getField(this,2)},proto.sys.Services.prototype.getCspot=function(){return s.Message.getWrapperField(this,p.Spotify,4)},proto.sys.Services.prototype.setCspot=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Services.prototype.clearCspot=function(){return this.setCspot(void 0)},proto.sys.Services.prototype.hasCspot=function(){return null!=s.Message.getField(this,4)},proto.sys.Services.prototype.getAirplay=function(){return s.Message.getWrapperField(this,l.AirPlay,5)},proto.sys.Services.prototype.setAirplay=function(e){return s.Message.setWrapperField(this,5,e)},proto.sys.Services.prototype.clearAirplay=function(){return this.setAirplay(void 0)},proto.sys.Services.prototype.hasAirplay=function(){return null!=s.Message.getField(this,5)},proto.sys.Services.prototype.getSqueezeliteProfilesList=function(){return s.Message.getRepeatedWrapperField(this,u.SqueezeliteProfile,6)},proto.sys.Services.prototype.setSqueezeliteProfilesList=function(e){return s.Message.setRepeatedWrapperField(this,6,e)},proto.sys.Services.prototype.addSqueezeliteProfiles=function(e,t){return s.Message.addToRepeatedWrapperField(this,6,e,proto.sys.SqueezeliteProfile,t)},proto.sys.Services.prototype.clearSqueezeliteProfilesList=function(){return this.setSqueezeliteProfilesList([])},proto.sys.Services.prototype.getReleaseUrl=function(){return s.Message.getFieldWithDefault(this,7,"")},proto.sys.Services.prototype.setReleaseUrl=function(e){return s.Message.setProto3StringField(this,7,e)},proto.sys.Services.prototype.getBtSink=function(){return s.Message.getWrapperField(this,proto.sys.BluetoothSink,8)},proto.sys.Services.prototype.setBtSink=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.Services.prototype.clearBtSink=function(){return this.setBtSink(void 0)},proto.sys.Services.prototype.hasBtSink=function(){return null!=s.Message.getField(this,8)},proto.sys.Services.prototype.getStatistics=function(){return s.Message.getBooleanFieldWithDefault(this,9,!1)},proto.sys.Services.prototype.setStatistics=function(e){return s.Message.setProto3BooleanField(this,9,e)},proto.sys.Services.prototype.getTelnet=function(){return s.Message.getWrapperField(this,proto.sys.Telnet,10)},proto.sys.Services.prototype.setTelnet=function(e){return s.Message.setWrapperField(this,10,e)},proto.sys.Services.prototype.clearTelnet=function(){return this.setTelnet(void 0)},proto.sys.Services.prototype.hasTelnet=function(){return null!=s.Message.getField(this,10)},proto.sys.Services.prototype.getEqualizer=function(){return s.Message.getWrapperField(this,y.Equalizer,11)},proto.sys.Services.prototype.setEqualizer=function(e){return s.Message.setWrapperField(this,11,e)},proto.sys.Services.prototype.clearEqualizer=function(){return this.setEqualizer(void 0)},proto.sys.Services.prototype.hasEqualizer=function(){return null!=s.Message.getField(this,11)},proto.sys.Services.prototype.getCurrentProfile=function(){return s.Message.getFieldWithDefault(this,12,"")},proto.sys.Services.prototype.setCurrentProfile=function(e){return s.Message.setProto3StringField(this,12,e)},proto.sys.TelnetEnableEnum={SERIAL_ONLY:0,TELNET:1,TELNET_SERIAL:2},r.object.extend(t,proto.sys)},3043:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(5465);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.sys.Spotify",null,i),proto.sys.Spotify=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Spotify,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Spotify.displayName="proto.sys.Spotify"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.Spotify.prototype.toObject=function(e){return proto.sys.Spotify.toObject(e,this)},proto.sys.Spotify.toObject=function(e,t){var o={enabled:s.Message.getBooleanFieldWithDefault(t,1,!1),bitrate:s.Message.getFieldWithDefault(t,2,0),zeroconf:s.Message.getBooleanFieldWithDefault(t,3,!1),volume:s.Message.getFieldWithDefault(t,4,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.Spotify.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Spotify;return proto.sys.Spotify.deserializeBinaryFromReader(o,t)},proto.sys.Spotify.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnabled(o);break;case 2:o=t.readUint32();e.setBitrate(o);break;case 3:o=t.readBool();e.setZeroconf(o);break;case 4:o=t.readUint32();e.setVolume(o);break;default:t.skipField()}}return e},proto.sys.Spotify.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Spotify.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Spotify.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnabled())&&t.writeBool(1,o),0!==(o=e.getBitrate())&&t.writeUint32(2,o),(o=e.getZeroconf())&&t.writeBool(3,o),0!==(o=e.getVolume())&&t.writeUint32(4,o)},proto.sys.Spotify.prototype.getEnabled=function(){return s.Message.getBooleanFieldWithDefault(this,1,!1)},proto.sys.Spotify.prototype.setEnabled=function(e){return s.Message.setProto3BooleanField(this,1,e)},proto.sys.Spotify.prototype.getBitrate=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.Spotify.prototype.setBitrate=function(e){return s.Message.setProto3IntField(this,2,e)},proto.sys.Spotify.prototype.getZeroconf=function(){return s.Message.getBooleanFieldWithDefault(this,3,!1)},proto.sys.Spotify.prototype.setZeroconf=function(e){return s.Message.setProto3BooleanField(this,3,e)},proto.sys.Spotify.prototype.getVolume=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.Spotify.prototype.setVolume=function(e){return s.Message.setProto3IntField(this,4,e)},r.object.extend(t,proto.sys)},1480:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(5465);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.sys.BufferOption",null,i),r.exportSymbol("proto.sys.CodexEnum",null,i),r.exportSymbol("proto.sys.DebugLevelEnum",null,i),r.exportSymbol("proto.sys.DebugOptions",null,i),r.exportSymbol("proto.sys.OutputBT",null,i),r.exportSymbol("proto.sys.OutputTypeEnum",null,i),r.exportSymbol("proto.sys.RatesOption",null,i),r.exportSymbol("proto.sys.ResampleAlgorithm",null,i),r.exportSymbol("proto.sys.ResampleOptions",null,i),r.exportSymbol("proto.sys.SampleRate",null,i),r.exportSymbol("proto.sys.Squeezelite",null,i),r.exportSymbol("proto.sys.SqueezeliteProfile",null,i),proto.sys.OutputBT=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.OutputBT,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.OutputBT.displayName="proto.sys.OutputBT"),proto.sys.ResampleOptions=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.ResampleOptions,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.ResampleOptions.displayName="proto.sys.ResampleOptions"),proto.sys.RatesOption=function(e){s.Message.initialize(this,e,0,-1,proto.sys.RatesOption.repeatedFields_,null)},r.inherits(proto.sys.RatesOption,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.RatesOption.displayName="proto.sys.RatesOption"),proto.sys.BufferOption=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.BufferOption,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.BufferOption.displayName="proto.sys.BufferOption"),proto.sys.DebugOptions=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.DebugOptions,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.DebugOptions.displayName="proto.sys.DebugOptions"),proto.sys.Squeezelite=function(e){s.Message.initialize(this,e,0,-1,proto.sys.Squeezelite.repeatedFields_,null)},r.inherits(proto.sys.Squeezelite,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Squeezelite.displayName="proto.sys.Squeezelite"),proto.sys.SqueezeliteProfile=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.SqueezeliteProfile,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.SqueezeliteProfile.displayName="proto.sys.SqueezeliteProfile"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.OutputBT.prototype.toObject=function(e){return proto.sys.OutputBT.toObject(e,this)},proto.sys.OutputBT.toObject=function(e,t){var o={sinkName:s.Message.getFieldWithDefault(t,1,""),pin:s.Message.getFieldWithDefault(t,2,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.OutputBT.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.OutputBT;return proto.sys.OutputBT.deserializeBinaryFromReader(o,t)},proto.sys.OutputBT.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setSinkName(o);break;case 2:o=t.readString();e.setPin(o);break;default:t.skipField()}}return e},proto.sys.OutputBT.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.OutputBT.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.OutputBT.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getSinkName()).length>0&&t.writeString(1,o),(o=e.getPin()).length>0&&t.writeString(2,o)},proto.sys.OutputBT.prototype.getSinkName=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.OutputBT.prototype.setSinkName=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.OutputBT.prototype.getPin=function(){return s.Message.getFieldWithDefault(this,2,"")},proto.sys.OutputBT.prototype.setPin=function(e){return s.Message.setProto3StringField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.ResampleOptions.prototype.toObject=function(e){return proto.sys.ResampleOptions.toObject(e,this)},proto.sys.ResampleOptions.toObject=function(e,t){var o={algorithm:s.Message.getFieldWithDefault(t,1,0),interpolateFilterCoefficients:s.Message.getBooleanFieldWithDefault(t,2,!1)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.ResampleOptions.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.ResampleOptions;return proto.sys.ResampleOptions.deserializeBinaryFromReader(o,t)},proto.sys.ResampleOptions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setAlgorithm(o);break;case 2:o=t.readBool();e.setInterpolateFilterCoefficients(o);break;default:t.skipField()}}return e},proto.sys.ResampleOptions.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.ResampleOptions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.ResampleOptions.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getAlgorithm())&&t.writeEnum(1,o),(o=e.getInterpolateFilterCoefficients())&&t.writeBool(2,o)},proto.sys.ResampleOptions.prototype.getAlgorithm=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.ResampleOptions.prototype.setAlgorithm=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.ResampleOptions.prototype.getInterpolateFilterCoefficients=function(){return s.Message.getBooleanFieldWithDefault(this,2,!1)},proto.sys.ResampleOptions.prototype.setInterpolateFilterCoefficients=function(e){return s.Message.setProto3BooleanField(this,2,e)},proto.sys.RatesOption.repeatedFields_=[3],s.Message.GENERATE_TO_OBJECT&&(proto.sys.RatesOption.prototype.toObject=function(e){return proto.sys.RatesOption.toObject(e,this)},proto.sys.RatesOption.toObject=function(e,t){var o,r={min:s.Message.getFieldWithDefault(t,1,0),max:s.Message.getFieldWithDefault(t,2,0),listList:null==(o=s.Message.getRepeatedField(t,3))?void 0:o};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.RatesOption.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.RatesOption;return proto.sys.RatesOption.deserializeBinaryFromReader(o,t)},proto.sys.RatesOption.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setMin(o);break;case 2:o=t.readEnum();e.setMax(o);break;case 3:for(var s=t.isDelimited()?t.readPackedEnum():[t.readEnum()],r=0;r0&&t.writePackedEnum(3,o)},proto.sys.RatesOption.prototype.getMin=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.RatesOption.prototype.setMin=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.RatesOption.prototype.getMax=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.RatesOption.prototype.setMax=function(e){return s.Message.setProto3EnumField(this,2,e)},proto.sys.RatesOption.prototype.getListList=function(){return s.Message.getRepeatedField(this,3)},proto.sys.RatesOption.prototype.setListList=function(e){return s.Message.setField(this,3,e||[])},proto.sys.RatesOption.prototype.addList=function(e,t){return s.Message.addToRepeatedField(this,3,e,t)},proto.sys.RatesOption.prototype.clearListList=function(){return this.setListList([])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.BufferOption.prototype.toObject=function(e){return proto.sys.BufferOption.toObject(e,this)},proto.sys.BufferOption.toObject=function(e,t){var o={stream:s.Message.getFieldWithDefault(t,1,0),output:s.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.BufferOption.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.BufferOption;return proto.sys.BufferOption.deserializeBinaryFromReader(o,t)},proto.sys.BufferOption.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readUint32();e.setStream(o);break;case 2:o=t.readUint32();e.setOutput(o);break;default:t.skipField()}}return e},proto.sys.BufferOption.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.BufferOption.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.BufferOption.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getStream())&&t.writeUint32(1,o),0!==(o=e.getOutput())&&t.writeUint32(2,o)},proto.sys.BufferOption.prototype.getStream=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.BufferOption.prototype.setStream=function(e){return s.Message.setProto3IntField(this,1,e)},proto.sys.BufferOption.prototype.getOutput=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.BufferOption.prototype.setOutput=function(e){return s.Message.setProto3IntField(this,2,e)},s.Message.GENERATE_TO_OBJECT&&(proto.sys.DebugOptions.prototype.toObject=function(e){return proto.sys.DebugOptions.toObject(e,this)},proto.sys.DebugOptions.toObject=function(e,t){var o={output:s.Message.getFieldWithDefault(t,1,0),stream:s.Message.getFieldWithDefault(t,2,0),decode:s.Message.getFieldWithDefault(t,3,0),slimproto:s.Message.getFieldWithDefault(t,4,0),ir:s.Message.getFieldWithDefault(t,5,0),all:s.Message.getFieldWithDefault(t,6,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.sys.DebugOptions.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.DebugOptions;return proto.sys.DebugOptions.deserializeBinaryFromReader(o,t)},proto.sys.DebugOptions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setOutput(o);break;case 2:o=t.readEnum();e.setStream(o);break;case 3:o=t.readEnum();e.setDecode(o);break;case 4:o=t.readEnum();e.setSlimproto(o);break;case 5:o=t.readEnum();e.setIr(o);break;case 6:o=t.readEnum();e.setAll(o);break;default:t.skipField()}}return e},proto.sys.DebugOptions.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.DebugOptions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.DebugOptions.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getOutput())&&t.writeEnum(1,o),0!==(o=e.getStream())&&t.writeEnum(2,o),0!==(o=e.getDecode())&&t.writeEnum(3,o),0!==(o=e.getSlimproto())&&t.writeEnum(4,o),0!==(o=e.getIr())&&t.writeEnum(5,o),0!==(o=e.getAll())&&t.writeEnum(6,o)},proto.sys.DebugOptions.prototype.getOutput=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.DebugOptions.prototype.setOutput=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.DebugOptions.prototype.getStream=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.sys.DebugOptions.prototype.setStream=function(e){return s.Message.setProto3EnumField(this,2,e)},proto.sys.DebugOptions.prototype.getDecode=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.DebugOptions.prototype.setDecode=function(e){return s.Message.setProto3EnumField(this,3,e)},proto.sys.DebugOptions.prototype.getSlimproto=function(){return s.Message.getFieldWithDefault(this,4,0)},proto.sys.DebugOptions.prototype.setSlimproto=function(e){return s.Message.setProto3EnumField(this,4,e)},proto.sys.DebugOptions.prototype.getIr=function(){return s.Message.getFieldWithDefault(this,5,0)},proto.sys.DebugOptions.prototype.setIr=function(e){return s.Message.setProto3EnumField(this,5,e)},proto.sys.DebugOptions.prototype.getAll=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.DebugOptions.prototype.setAll=function(e){return s.Message.setProto3EnumField(this,6,e)},proto.sys.Squeezelite.repeatedFields_=[13,14],s.Message.GENERATE_TO_OBJECT&&(proto.sys.Squeezelite.prototype.toObject=function(e){return proto.sys.Squeezelite.toObject(e,this)},proto.sys.Squeezelite.toObject=function(e,t){var o,r={outputType:s.Message.getFieldWithDefault(t,1,0),rates:(o=t.getRates())&&proto.sys.RatesOption.toObject(e,o),ampGpioTimeout:s.Message.getFieldWithDefault(t,3,0),wavAiffHeaderParsing:s.Message.getBooleanFieldWithDefault(t,4,!1),serverNameIp:s.Message.getFieldWithDefault(t,5,""),serverPort:s.Message.getFieldWithDefault(t,6,0),enabled:s.Message.getBooleanFieldWithDefault(t,7,!1),outputBt:(o=t.getOutputBt())&&proto.sys.OutputBT.toObject(e,o),log:(o=t.getLog())&&proto.sys.DebugOptions.toObject(e,o),maxRate:s.Message.getFieldWithDefault(t,10,0),buffers:(o=t.getBuffers())&&proto.sys.BufferOption.toObject(e,o),resample:s.Message.getFieldWithDefault(t,12,""),includedCodexList:null==(o=s.Message.getRepeatedField(t,13))?void 0:o,excludedCodexList:null==(o=s.Message.getRepeatedField(t,14))?void 0:o};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Squeezelite.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Squeezelite;return proto.sys.Squeezelite.deserializeBinaryFromReader(o,t)},proto.sys.Squeezelite.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setOutputType(o);break;case 2:o=new proto.sys.RatesOption;t.readMessage(o,proto.sys.RatesOption.deserializeBinaryFromReader),e.setRates(o);break;case 3:o=t.readInt32();e.setAmpGpioTimeout(o);break;case 4:o=t.readBool();e.setWavAiffHeaderParsing(o);break;case 5:o=t.readString();e.setServerNameIp(o);break;case 6:o=t.readUint32();e.setServerPort(o);break;case 7:o=t.readBool();e.setEnabled(o);break;case 8:o=new proto.sys.OutputBT;t.readMessage(o,proto.sys.OutputBT.deserializeBinaryFromReader),e.setOutputBt(o);break;case 9:o=new proto.sys.DebugOptions;t.readMessage(o,proto.sys.DebugOptions.deserializeBinaryFromReader),e.setLog(o);break;case 10:o=t.readUint32();e.setMaxRate(o);break;case 11:o=new proto.sys.BufferOption;t.readMessage(o,proto.sys.BufferOption.deserializeBinaryFromReader),e.setBuffers(o);break;case 12:o=t.readString();e.setResample(o);break;case 13:for(var s=t.isDelimited()?t.readPackedEnum():[t.readEnum()],r=0;r0&&t.writeString(5,o),0!==(o=e.getServerPort())&&t.writeUint32(6,o),(o=e.getEnabled())&&t.writeBool(7,o),null!=(o=e.getOutputBt())&&t.writeMessage(8,o,proto.sys.OutputBT.serializeBinaryToWriter),null!=(o=e.getLog())&&t.writeMessage(9,o,proto.sys.DebugOptions.serializeBinaryToWriter),0!==(o=e.getMaxRate())&&t.writeUint32(10,o),null!=(o=e.getBuffers())&&t.writeMessage(11,o,proto.sys.BufferOption.serializeBinaryToWriter),(o=e.getResample()).length>0&&t.writeString(12,o),(o=e.getIncludedCodexList()).length>0&&t.writePackedEnum(13,o),(o=e.getExcludedCodexList()).length>0&&t.writePackedEnum(14,o)},proto.sys.Squeezelite.prototype.getOutputType=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.sys.Squeezelite.prototype.setOutputType=function(e){return s.Message.setProto3EnumField(this,1,e)},proto.sys.Squeezelite.prototype.getRates=function(){return s.Message.getWrapperField(this,proto.sys.RatesOption,2)},proto.sys.Squeezelite.prototype.setRates=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Squeezelite.prototype.clearRates=function(){return this.setRates(void 0)},proto.sys.Squeezelite.prototype.hasRates=function(){return null!=s.Message.getField(this,2)},proto.sys.Squeezelite.prototype.getAmpGpioTimeout=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.sys.Squeezelite.prototype.setAmpGpioTimeout=function(e){return s.Message.setProto3IntField(this,3,e)},proto.sys.Squeezelite.prototype.getWavAiffHeaderParsing=function(){return s.Message.getBooleanFieldWithDefault(this,4,!1)},proto.sys.Squeezelite.prototype.setWavAiffHeaderParsing=function(e){return s.Message.setProto3BooleanField(this,4,e)},proto.sys.Squeezelite.prototype.getServerNameIp=function(){return s.Message.getFieldWithDefault(this,5,"")},proto.sys.Squeezelite.prototype.setServerNameIp=function(e){return s.Message.setProto3StringField(this,5,e)},proto.sys.Squeezelite.prototype.getServerPort=function(){return s.Message.getFieldWithDefault(this,6,0)},proto.sys.Squeezelite.prototype.setServerPort=function(e){return s.Message.setProto3IntField(this,6,e)},proto.sys.Squeezelite.prototype.getEnabled=function(){return s.Message.getBooleanFieldWithDefault(this,7,!1)},proto.sys.Squeezelite.prototype.setEnabled=function(e){return s.Message.setProto3BooleanField(this,7,e)},proto.sys.Squeezelite.prototype.getOutputBt=function(){return s.Message.getWrapperField(this,proto.sys.OutputBT,8)},proto.sys.Squeezelite.prototype.setOutputBt=function(e){return s.Message.setWrapperField(this,8,e)},proto.sys.Squeezelite.prototype.clearOutputBt=function(){return this.setOutputBt(void 0)},proto.sys.Squeezelite.prototype.hasOutputBt=function(){return null!=s.Message.getField(this,8)},proto.sys.Squeezelite.prototype.getLog=function(){return s.Message.getWrapperField(this,proto.sys.DebugOptions,9)},proto.sys.Squeezelite.prototype.setLog=function(e){return s.Message.setWrapperField(this,9,e)},proto.sys.Squeezelite.prototype.clearLog=function(){return this.setLog(void 0)},proto.sys.Squeezelite.prototype.hasLog=function(){return null!=s.Message.getField(this,9)},proto.sys.Squeezelite.prototype.getMaxRate=function(){return s.Message.getFieldWithDefault(this,10,0)},proto.sys.Squeezelite.prototype.setMaxRate=function(e){return s.Message.setProto3IntField(this,10,e)},proto.sys.Squeezelite.prototype.getBuffers=function(){return s.Message.getWrapperField(this,proto.sys.BufferOption,11)},proto.sys.Squeezelite.prototype.setBuffers=function(e){return s.Message.setWrapperField(this,11,e)},proto.sys.Squeezelite.prototype.clearBuffers=function(){return this.setBuffers(void 0)},proto.sys.Squeezelite.prototype.hasBuffers=function(){return null!=s.Message.getField(this,11)},proto.sys.Squeezelite.prototype.getResample=function(){return s.Message.getFieldWithDefault(this,12,"")},proto.sys.Squeezelite.prototype.setResample=function(e){return s.Message.setProto3StringField(this,12,e)},proto.sys.Squeezelite.prototype.getIncludedCodexList=function(){return s.Message.getRepeatedField(this,13)},proto.sys.Squeezelite.prototype.setIncludedCodexList=function(e){return s.Message.setField(this,13,e||[])},proto.sys.Squeezelite.prototype.addIncludedCodex=function(e,t){return s.Message.addToRepeatedField(this,13,e,t)},proto.sys.Squeezelite.prototype.clearIncludedCodexList=function(){return this.setIncludedCodexList([])},proto.sys.Squeezelite.prototype.getExcludedCodexList=function(){return s.Message.getRepeatedField(this,14)},proto.sys.Squeezelite.prototype.setExcludedCodexList=function(e){return s.Message.setField(this,14,e||[])},proto.sys.Squeezelite.prototype.addExcludedCodex=function(e,t){return s.Message.addToRepeatedField(this,14,e,t)},proto.sys.Squeezelite.prototype.clearExcludedCodexList=function(){return this.setExcludedCodexList([])},s.Message.GENERATE_TO_OBJECT&&(proto.sys.SqueezeliteProfile.prototype.toObject=function(e){return proto.sys.SqueezeliteProfile.toObject(e,this)},proto.sys.SqueezeliteProfile.toObject=function(e,t){var o,r={name:s.Message.getFieldWithDefault(t,1,""),profile:(o=t.getProfile())&&proto.sys.Squeezelite.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.SqueezeliteProfile.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.SqueezeliteProfile;return proto.sys.SqueezeliteProfile.deserializeBinaryFromReader(o,t)},proto.sys.SqueezeliteProfile.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setName(o);break;case 2:o=new proto.sys.Squeezelite;t.readMessage(o,proto.sys.Squeezelite.deserializeBinaryFromReader),e.setProfile(o);break;default:t.skipField()}}return e},proto.sys.SqueezeliteProfile.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.SqueezeliteProfile.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.SqueezeliteProfile.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getName()).length>0&&t.writeString(1,o),null!=(o=e.getProfile())&&t.writeMessage(2,o,proto.sys.Squeezelite.serializeBinaryToWriter)},proto.sys.SqueezeliteProfile.prototype.getName=function(){return s.Message.getFieldWithDefault(this,1,"")},proto.sys.SqueezeliteProfile.prototype.setName=function(e){return s.Message.setProto3StringField(this,1,e)},proto.sys.SqueezeliteProfile.prototype.getProfile=function(){return s.Message.getWrapperField(this,proto.sys.Squeezelite,2)},proto.sys.SqueezeliteProfile.prototype.setProfile=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.SqueezeliteProfile.prototype.clearProfile=function(){return this.setProfile(void 0)},proto.sys.SqueezeliteProfile.prototype.hasProfile=function(){return null!=s.Message.getField(this,2)},proto.sys.OutputTypeEnum={OUTPUT_UNKNOWN:0,OUTPUT_I2S:1,OUTPUT_SPDIF:2,OUTPUT_BLUETOOTH:3},proto.sys.ResampleAlgorithm={RA_DISABLED:0,RA_BASIC_LINEAR:1,RA_THIRTEEN_TAPS:2,RA_TWENTY_ONE_TAPS:3},proto.sys.SampleRate={SAMPLE_RATE_UNSPECIFIED:0,SAMPLE_RATE_8000:8e3,SAMPLE_RATE_11025:11025,SAMPLE_RATE_12000:12e3,SAMPLE_RATE_16000:16e3,SAMPLE_RATE_22050:22050,SAMPLE_RATE_24000:24e3,SAMPLE_RATE_32000:32e3,SAMPLE_RATE_44100:44100,SAMPLE_RATE_48000:48e3,SAMPLE_RATE_88200:88200,SAMPLE_RATE_96000:96e3,SAMPLE_RATE_176400:176400,SAMPLE_RATE_192000:192e3,SAMPLE_RATE_352800:352800,SAMPLE_RATE_384000:384e3,SAMPLE_RATE_705600:705600,SAMPLE_RATE_768000:768e3},proto.sys.DebugLevelEnum={DEFAULT:0,ERROR:1,WARN:2,INFO:3,DEBUG:4,SDEBUG:5},proto.sys.CodexEnum={C_UNDEFINED:0,C_ALAC:1,C_OGG:2,C_OPS:3,C_FLAC:4,C_PCM:5,C_MP3:6,C_MAD:7,C_MPG:8},r.object.extend(t,proto.sys)},4874:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(3359);r.object.extend(proto,n);var a=o(7567);r.object.extend(proto,a);var p=o(5437);r.object.extend(proto,p);var l=o(8395);r.object.extend(proto,l);var u=o(5397);r.object.extend(proto,u);var y=o(5465);r.object.extend(proto,y);var d=o(3021);r.object.extend(proto,d),r.exportSymbol("proto.sys.Config",null,i),proto.sys.Config=function(e){s.Message.initialize(this,e,0,-1,null,null)},r.inherits(proto.sys.Config,s.Message),r.DEBUG&&!COMPILED&&(proto.sys.Config.displayName="proto.sys.Config"),s.Message.GENERATE_TO_OBJECT&&(proto.sys.Config.prototype.toObject=function(e){return proto.sys.Config.toObject(e,this)},proto.sys.Config.toObject=function(e,t){var o,r={gpios:(o=t.getGpios())&&a.Gpios.toObject(e,o),dev:(o=t.getDev())&&p.Dev.toObject(e,o),services:(o=t.getServices())&&n.Services.toObject(e,o),names:(o=t.getNames())&&l.Names.toObject(e,o),target:s.Message.getFieldWithDefault(t,5,""),net:(o=t.getNet())&&u.NetworkConfig.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.sys.Config.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.sys.Config;return proto.sys.Config.deserializeBinaryFromReader(o,t)},proto.sys.Config.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new a.Gpios;t.readMessage(o,a.Gpios.deserializeBinaryFromReader),e.setGpios(o);break;case 2:o=new p.Dev;t.readMessage(o,p.Dev.deserializeBinaryFromReader),e.setDev(o);break;case 3:o=new n.Services;t.readMessage(o,n.Services.deserializeBinaryFromReader),e.setServices(o);break;case 4:o=new l.Names;t.readMessage(o,l.Names.deserializeBinaryFromReader),e.setNames(o);break;case 5:o=t.readString();e.setTarget(o);break;case 6:o=new u.NetworkConfig;t.readMessage(o,u.NetworkConfig.deserializeBinaryFromReader),e.setNet(o);break;default:t.skipField()}}return e},proto.sys.Config.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.sys.Config.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.sys.Config.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpios())&&t.writeMessage(1,o,a.Gpios.serializeBinaryToWriter),null!=(o=e.getDev())&&t.writeMessage(2,o,p.Dev.serializeBinaryToWriter),null!=(o=e.getServices())&&t.writeMessage(3,o,n.Services.serializeBinaryToWriter),null!=(o=e.getNames())&&t.writeMessage(4,o,l.Names.serializeBinaryToWriter),(o=e.getTarget()).length>0&&t.writeString(5,o),null!=(o=e.getNet())&&t.writeMessage(6,o,u.NetworkConfig.serializeBinaryToWriter)},proto.sys.Config.prototype.getGpios=function(){return s.Message.getWrapperField(this,a.Gpios,1)},proto.sys.Config.prototype.setGpios=function(e){return s.Message.setWrapperField(this,1,e)},proto.sys.Config.prototype.clearGpios=function(){return this.setGpios(void 0)},proto.sys.Config.prototype.hasGpios=function(){return null!=s.Message.getField(this,1)},proto.sys.Config.prototype.getDev=function(){return s.Message.getWrapperField(this,p.Dev,2)},proto.sys.Config.prototype.setDev=function(e){return s.Message.setWrapperField(this,2,e)},proto.sys.Config.prototype.clearDev=function(){return this.setDev(void 0)},proto.sys.Config.prototype.hasDev=function(){return null!=s.Message.getField(this,2)},proto.sys.Config.prototype.getServices=function(){return s.Message.getWrapperField(this,n.Services,3)},proto.sys.Config.prototype.setServices=function(e){return s.Message.setWrapperField(this,3,e)},proto.sys.Config.prototype.clearServices=function(){return this.setServices(void 0)},proto.sys.Config.prototype.hasServices=function(){return null!=s.Message.getField(this,3)},proto.sys.Config.prototype.getNames=function(){return s.Message.getWrapperField(this,l.Names,4)},proto.sys.Config.prototype.setNames=function(e){return s.Message.setWrapperField(this,4,e)},proto.sys.Config.prototype.clearNames=function(){return this.setNames(void 0)},proto.sys.Config.prototype.hasNames=function(){return null!=s.Message.getField(this,4)},proto.sys.Config.prototype.getTarget=function(){return s.Message.getFieldWithDefault(this,5,"")},proto.sys.Config.prototype.setTarget=function(e){return s.Message.setProto3StringField(this,5,e)},proto.sys.Config.prototype.getNet=function(){return s.Message.getWrapperField(this,u.NetworkConfig,6)},proto.sys.Config.prototype.setNet=function(e){return s.Message.setWrapperField(this,6,e)},proto.sys.Config.prototype.clearNet=function(){return this.setNet(void 0)},proto.sys.Config.prototype.hasNet=function(){return null!=s.Message.getField(this,6)},r.object.extend(t,proto.sys)},5465:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(9392);r.object.extend(proto,n);var a=o(3021);r.object.extend(proto,a),r.exportSymbol("proto.CustomOptions",null,i),r.exportSymbol("proto.CustomOptions.DefaultValueCase",null,i),r.exportSymbol("proto.custEnum",null,i),r.exportSymbol("proto.custField",null,i),r.exportSymbol("proto.custFile",null,i),r.exportSymbol("proto.custMsg",null,i),proto.CustomOptions=function(e){s.Message.initialize(this,e,0,500,null,proto.CustomOptions.oneofGroups_)},r.inherits(proto.CustomOptions,s.Message),r.DEBUG&&!COMPILED&&(proto.CustomOptions.displayName="proto.CustomOptions"),proto.CustomOptions.oneofGroups_=[[50050,50051,50052,50053,50054,50055,50056,50057,50058,50059,50060]],proto.CustomOptions.DefaultValueCase={DEFAULT_VALUE_NOT_SET:0,V_STRING:50050,V_UINT32:50051,V_INT32:50052,V_UINT64:50053,V_INT64:50054,V_DOUBLE:50055,V_FLOAT:50056,V_BOOL:50057,V_ENUM:50058,V_BYTES:50059,V_MSG:50060},proto.CustomOptions.prototype.getDefaultValueCase=function(){return s.Message.computeOneofCase(this,proto.CustomOptions.oneofGroups_[0])},s.Message.GENERATE_TO_OBJECT&&(proto.CustomOptions.prototype.toObject=function(e){return proto.CustomOptions.toObject(e,this)},proto.CustomOptions.toObject=function(e,t){var o={initFromMac:s.Message.getBooleanFieldWithDefault(t,50001,!1),constPrefix:s.Message.getFieldWithDefault(t,50002,""),readOnly:s.Message.getBooleanFieldWithDefault(t,50003,!1),vString:s.Message.getFieldWithDefault(t,50050,""),vUint32:s.Message.getFieldWithDefault(t,50051,0),vInt32:s.Message.getFieldWithDefault(t,50052,0),vUint64:s.Message.getFieldWithDefault(t,50053,0),vInt64:s.Message.getFieldWithDefault(t,50054,0),vDouble:s.Message.getFloatingPointFieldWithDefault(t,50055,0),vFloat:s.Message.getFloatingPointFieldWithDefault(t,50056,0),vBool:s.Message.getBooleanFieldWithDefault(t,50057,!1),vEnum:s.Message.getFieldWithDefault(t,50058,""),vBytes:t.getVBytes_asB64(),vMsg:t.getVMsg_asB64(),globalName:s.Message.getFieldWithDefault(t,50005,"")};return e&&(o.$jspbMessageInstance=t),o}),proto.CustomOptions.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.CustomOptions;return proto.CustomOptions.deserializeBinaryFromReader(o,t)},proto.CustomOptions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 50001:var o=t.readBool();e.setInitFromMac(o);break;case 50002:o=t.readString();e.setConstPrefix(o);break;case 50003:o=t.readBool();e.setReadOnly(o);break;case 50050:o=t.readString();e.setVString(o);break;case 50051:o=t.readUint32();e.setVUint32(o);break;case 50052:o=t.readInt32();e.setVInt32(o);break;case 50053:o=t.readUint64();e.setVUint64(o);break;case 50054:o=t.readInt64();e.setVInt64(o);break;case 50055:o=t.readDouble();e.setVDouble(o);break;case 50056:o=t.readFloat();e.setVFloat(o);break;case 50057:o=t.readBool();e.setVBool(o);break;case 50058:o=t.readString();e.setVEnum(o);break;case 50059:o=t.readBytes();e.setVBytes(o);break;case 50060:o=t.readBytes();e.setVMsg(o);break;case 50005:o=t.readString();e.setGlobalName(o);break;default:t.skipField()}}return e},proto.CustomOptions.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.CustomOptions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.CustomOptions.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getInitFromMac())&&t.writeBool(50001,o),(o=e.getConstPrefix()).length>0&&t.writeString(50002,o),(o=e.getReadOnly())&&t.writeBool(50003,o),null!=(o=s.Message.getField(e,50050))&&t.writeString(50050,o),null!=(o=s.Message.getField(e,50051))&&t.writeUint32(50051,o),null!=(o=s.Message.getField(e,50052))&&t.writeInt32(50052,o),null!=(o=s.Message.getField(e,50053))&&t.writeUint64(50053,o),null!=(o=s.Message.getField(e,50054))&&t.writeInt64(50054,o),null!=(o=s.Message.getField(e,50055))&&t.writeDouble(50055,o),null!=(o=s.Message.getField(e,50056))&&t.writeFloat(50056,o),null!=(o=s.Message.getField(e,50057))&&t.writeBool(50057,o),null!=(o=s.Message.getField(e,50058))&&t.writeString(50058,o),null!=(o=s.Message.getField(e,50059))&&t.writeBytes(50059,o),null!=(o=s.Message.getField(e,50060))&&t.writeBytes(50060,o),(o=e.getGlobalName()).length>0&&t.writeString(50005,o)},proto.CustomOptions.prototype.getInitFromMac=function(){return s.Message.getBooleanFieldWithDefault(this,50001,!1)},proto.CustomOptions.prototype.setInitFromMac=function(e){return s.Message.setProto3BooleanField(this,50001,e)},proto.CustomOptions.prototype.getConstPrefix=function(){return s.Message.getFieldWithDefault(this,50002,"")},proto.CustomOptions.prototype.setConstPrefix=function(e){return s.Message.setProto3StringField(this,50002,e)},proto.CustomOptions.prototype.getReadOnly=function(){return s.Message.getBooleanFieldWithDefault(this,50003,!1)},proto.CustomOptions.prototype.setReadOnly=function(e){return s.Message.setProto3BooleanField(this,50003,e)},proto.CustomOptions.prototype.getVString=function(){return s.Message.getFieldWithDefault(this,50050,"")},proto.CustomOptions.prototype.setVString=function(e){return s.Message.setOneofField(this,50050,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVString=function(){return s.Message.setOneofField(this,50050,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVString=function(){return null!=s.Message.getField(this,50050)},proto.CustomOptions.prototype.getVUint32=function(){return s.Message.getFieldWithDefault(this,50051,0)},proto.CustomOptions.prototype.setVUint32=function(e){return s.Message.setOneofField(this,50051,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVUint32=function(){return s.Message.setOneofField(this,50051,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVUint32=function(){return null!=s.Message.getField(this,50051)},proto.CustomOptions.prototype.getVInt32=function(){return s.Message.getFieldWithDefault(this,50052,0)},proto.CustomOptions.prototype.setVInt32=function(e){return s.Message.setOneofField(this,50052,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVInt32=function(){return s.Message.setOneofField(this,50052,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVInt32=function(){return null!=s.Message.getField(this,50052)},proto.CustomOptions.prototype.getVUint64=function(){return s.Message.getFieldWithDefault(this,50053,0)},proto.CustomOptions.prototype.setVUint64=function(e){return s.Message.setOneofField(this,50053,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVUint64=function(){return s.Message.setOneofField(this,50053,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVUint64=function(){return null!=s.Message.getField(this,50053)},proto.CustomOptions.prototype.getVInt64=function(){return s.Message.getFieldWithDefault(this,50054,0)},proto.CustomOptions.prototype.setVInt64=function(e){return s.Message.setOneofField(this,50054,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVInt64=function(){return s.Message.setOneofField(this,50054,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVInt64=function(){return null!=s.Message.getField(this,50054)},proto.CustomOptions.prototype.getVDouble=function(){return s.Message.getFloatingPointFieldWithDefault(this,50055,0)},proto.CustomOptions.prototype.setVDouble=function(e){return s.Message.setOneofField(this,50055,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVDouble=function(){return s.Message.setOneofField(this,50055,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVDouble=function(){return null!=s.Message.getField(this,50055)},proto.CustomOptions.prototype.getVFloat=function(){return s.Message.getFloatingPointFieldWithDefault(this,50056,0)},proto.CustomOptions.prototype.setVFloat=function(e){return s.Message.setOneofField(this,50056,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVFloat=function(){return s.Message.setOneofField(this,50056,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVFloat=function(){return null!=s.Message.getField(this,50056)},proto.CustomOptions.prototype.getVBool=function(){return s.Message.getBooleanFieldWithDefault(this,50057,!1)},proto.CustomOptions.prototype.setVBool=function(e){return s.Message.setOneofField(this,50057,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVBool=function(){return s.Message.setOneofField(this,50057,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVBool=function(){return null!=s.Message.getField(this,50057)},proto.CustomOptions.prototype.getVEnum=function(){return s.Message.getFieldWithDefault(this,50058,"")},proto.CustomOptions.prototype.setVEnum=function(e){return s.Message.setOneofField(this,50058,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVEnum=function(){return s.Message.setOneofField(this,50058,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVEnum=function(){return null!=s.Message.getField(this,50058)},proto.CustomOptions.prototype.getVBytes=function(){return s.Message.getFieldWithDefault(this,50059,"")},proto.CustomOptions.prototype.getVBytes_asB64=function(){return s.Message.bytesAsB64(this.getVBytes())},proto.CustomOptions.prototype.getVBytes_asU8=function(){return s.Message.bytesAsU8(this.getVBytes())},proto.CustomOptions.prototype.setVBytes=function(e){return s.Message.setOneofField(this,50059,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVBytes=function(){return s.Message.setOneofField(this,50059,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVBytes=function(){return null!=s.Message.getField(this,50059)},proto.CustomOptions.prototype.getVMsg=function(){return s.Message.getFieldWithDefault(this,50060,"")},proto.CustomOptions.prototype.getVMsg_asB64=function(){return s.Message.bytesAsB64(this.getVMsg())},proto.CustomOptions.prototype.getVMsg_asU8=function(){return s.Message.bytesAsU8(this.getVMsg())},proto.CustomOptions.prototype.setVMsg=function(e){return s.Message.setOneofField(this,50060,proto.CustomOptions.oneofGroups_[0],e)},proto.CustomOptions.prototype.clearVMsg=function(){return s.Message.setOneofField(this,50060,proto.CustomOptions.oneofGroups_[0],void 0)},proto.CustomOptions.prototype.hasVMsg=function(){return null!=s.Message.getField(this,50060)},proto.CustomOptions.prototype.getGlobalName=function(){return s.Message.getFieldWithDefault(this,50005,"")},proto.CustomOptions.prototype.setGlobalName=function(e){return s.Message.setProto3StringField(this,50005,e)},proto.custFile=new s.ExtensionFieldInfo(2010,{custFile:0},proto.CustomOptions,proto.CustomOptions.toObject,0),n.FileOptions.extensionsBinary[2010]=new s.ExtensionFieldBinaryInfo(proto.custFile,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.CustomOptions.serializeBinaryToWriter,proto.CustomOptions.deserializeBinaryFromReader,!1),n.FileOptions.extensions[2010]=proto.custFile,proto.custMsg=new s.ExtensionFieldInfo(2010,{custMsg:0},proto.CustomOptions,proto.CustomOptions.toObject,0),n.MessageOptions.extensionsBinary[2010]=new s.ExtensionFieldBinaryInfo(proto.custMsg,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.CustomOptions.serializeBinaryToWriter,proto.CustomOptions.deserializeBinaryFromReader,!1),n.MessageOptions.extensions[2010]=proto.custMsg,proto.custEnum=new s.ExtensionFieldInfo(2010,{custEnum:0},proto.CustomOptions,proto.CustomOptions.toObject,0),n.EnumOptions.extensionsBinary[2010]=new s.ExtensionFieldBinaryInfo(proto.custEnum,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.CustomOptions.serializeBinaryToWriter,proto.CustomOptions.deserializeBinaryFromReader,!1),n.EnumOptions.extensions[2010]=proto.custEnum,proto.custField=new s.ExtensionFieldInfo(2010,{custField:0},proto.CustomOptions,proto.CustomOptions.toObject,0),n.FieldOptions.extensionsBinary[2010]=new s.ExtensionFieldBinaryInfo(proto.custField,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.CustomOptions.serializeBinaryToWriter,proto.CustomOptions.deserializeBinaryFromReader,!1),n.FieldOptions.extensions[2010]=proto.custField,r.object.extend(t,proto)},3021:(e,t,o)=>{var s=o(3019),r=s,i="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof window&&window||void 0!==i&&i||"undefined"!=typeof self&&self||function(){return this}.call(null)||Function("return this")(),n=o(9392);r.object.extend(proto,n),r.exportSymbol("proto.DescriptorSize",null,i),r.exportSymbol("proto.FieldType",null,i),r.exportSymbol("proto.IntSize",null,i),r.exportSymbol("proto.NanoPBOptions",null,i),r.exportSymbol("proto.TypenameMangling",null,i),r.exportSymbol("proto.nanopb",null,i),r.exportSymbol("proto.nanopbEnumopt",null,i),r.exportSymbol("proto.nanopbFileopt",null,i),r.exportSymbol("proto.nanopbMsgopt",null,i),proto.NanoPBOptions=function(e){s.Message.initialize(this,e,0,-1,proto.NanoPBOptions.repeatedFields_,null)},r.inherits(proto.NanoPBOptions,s.Message),r.DEBUG&&!COMPILED&&(proto.NanoPBOptions.displayName="proto.NanoPBOptions"),proto.NanoPBOptions.repeatedFields_=[24,26],s.Message.GENERATE_TO_OBJECT&&(proto.NanoPBOptions.prototype.toObject=function(e){return proto.NanoPBOptions.toObject(e,this)},proto.NanoPBOptions.toObject=function(e,t){var o,r={maxSize:null==(o=s.Message.getField(t,1))?void 0:o,maxLength:null==(o=s.Message.getField(t,14))?void 0:o,maxCount:null==(o=s.Message.getField(t,2))?void 0:o,intSize:s.Message.getFieldWithDefault(t,7,0),type:s.Message.getFieldWithDefault(t,3,0),longNames:s.Message.getBooleanFieldWithDefault(t,4,!0),packedStruct:s.Message.getBooleanFieldWithDefault(t,5,!1),packedEnum:s.Message.getBooleanFieldWithDefault(t,10,!1),skipMessage:s.Message.getBooleanFieldWithDefault(t,6,!1),noUnions:s.Message.getBooleanFieldWithDefault(t,8,!1),msgid:null==(o=s.Message.getField(t,9))?void 0:o,anonymousOneof:s.Message.getBooleanFieldWithDefault(t,11,!1),proto3:s.Message.getBooleanFieldWithDefault(t,12,!1),proto3SingularMsgs:s.Message.getBooleanFieldWithDefault(t,21,!1),enumToString:s.Message.getBooleanFieldWithDefault(t,13,!1),fixedLength:s.Message.getBooleanFieldWithDefault(t,15,!1),fixedCount:s.Message.getBooleanFieldWithDefault(t,16,!1),submsgCallback:s.Message.getBooleanFieldWithDefault(t,22,!1),mangleNames:s.Message.getFieldWithDefault(t,17,0),callbackDatatype:s.Message.getFieldWithDefault(t,18,"pb_callback_t"),callbackFunction:s.Message.getFieldWithDefault(t,19,"pb_default_field_callback"),descriptorsize:s.Message.getFieldWithDefault(t,20,0),defaultHas:s.Message.getBooleanFieldWithDefault(t,23,!1),includeList:null==(o=s.Message.getRepeatedField(t,24))?void 0:o,excludeList:null==(o=s.Message.getRepeatedField(t,26))?void 0:o,pb_package:null==(o=s.Message.getField(t,25))?void 0:o,typeOverride:null==(o=s.Message.getField(t,27))?void 0:o,sortByTag:s.Message.getBooleanFieldWithDefault(t,28,!0)};return e&&(r.$jspbMessageInstance=t),r}),proto.NanoPBOptions.deserializeBinary=function(e){var t=new s.BinaryReader(e),o=new proto.NanoPBOptions;return proto.NanoPBOptions.deserializeBinaryFromReader(o,t)},proto.NanoPBOptions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setMaxSize(o);break;case 14:o=t.readInt32();e.setMaxLength(o);break;case 2:o=t.readInt32();e.setMaxCount(o);break;case 7:o=t.readEnum();e.setIntSize(o);break;case 3:o=t.readEnum();e.setType(o);break;case 4:o=t.readBool();e.setLongNames(o);break;case 5:o=t.readBool();e.setPackedStruct(o);break;case 10:o=t.readBool();e.setPackedEnum(o);break;case 6:o=t.readBool();e.setSkipMessage(o);break;case 8:o=t.readBool();e.setNoUnions(o);break;case 9:o=t.readUint32();e.setMsgid(o);break;case 11:o=t.readBool();e.setAnonymousOneof(o);break;case 12:o=t.readBool();e.setProto3(o);break;case 21:o=t.readBool();e.setProto3SingularMsgs(o);break;case 13:o=t.readBool();e.setEnumToString(o);break;case 15:o=t.readBool();e.setFixedLength(o);break;case 16:o=t.readBool();e.setFixedCount(o);break;case 22:o=t.readBool();e.setSubmsgCallback(o);break;case 17:o=t.readEnum();e.setMangleNames(o);break;case 18:o=t.readString();e.setCallbackDatatype(o);break;case 19:o=t.readString();e.setCallbackFunction(o);break;case 20:o=t.readEnum();e.setDescriptorsize(o);break;case 23:o=t.readBool();e.setDefaultHas(o);break;case 24:o=t.readString();e.addInclude(o);break;case 26:o=t.readString();e.addExclude(o);break;case 25:o=t.readString();e.setPackage(o);break;case 27:o=t.readEnum();e.setTypeOverride(o);break;case 28:o=t.readBool();e.setSortByTag(o);break;default:t.skipField()}}return e},proto.NanoPBOptions.prototype.serializeBinary=function(){var e=new s.BinaryWriter;return proto.NanoPBOptions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.NanoPBOptions.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=s.Message.getField(e,1))&&t.writeInt32(1,o),null!=(o=s.Message.getField(e,14))&&t.writeInt32(14,o),null!=(o=s.Message.getField(e,2))&&t.writeInt32(2,o),null!=(o=s.Message.getField(e,7))&&t.writeEnum(7,o),null!=(o=s.Message.getField(e,3))&&t.writeEnum(3,o),null!=(o=s.Message.getField(e,4))&&t.writeBool(4,o),null!=(o=s.Message.getField(e,5))&&t.writeBool(5,o),null!=(o=s.Message.getField(e,10))&&t.writeBool(10,o),null!=(o=s.Message.getField(e,6))&&t.writeBool(6,o),null!=(o=s.Message.getField(e,8))&&t.writeBool(8,o),null!=(o=s.Message.getField(e,9))&&t.writeUint32(9,o),null!=(o=s.Message.getField(e,11))&&t.writeBool(11,o),null!=(o=s.Message.getField(e,12))&&t.writeBool(12,o),null!=(o=s.Message.getField(e,21))&&t.writeBool(21,o),null!=(o=s.Message.getField(e,13))&&t.writeBool(13,o),null!=(o=s.Message.getField(e,15))&&t.writeBool(15,o),null!=(o=s.Message.getField(e,16))&&t.writeBool(16,o),null!=(o=s.Message.getField(e,22))&&t.writeBool(22,o),null!=(o=s.Message.getField(e,17))&&t.writeEnum(17,o),null!=(o=s.Message.getField(e,18))&&t.writeString(18,o),null!=(o=s.Message.getField(e,19))&&t.writeString(19,o),null!=(o=s.Message.getField(e,20))&&t.writeEnum(20,o),null!=(o=s.Message.getField(e,23))&&t.writeBool(23,o),(o=e.getIncludeList()).length>0&&t.writeRepeatedString(24,o),(o=e.getExcludeList()).length>0&&t.writeRepeatedString(26,o),null!=(o=s.Message.getField(e,25))&&t.writeString(25,o),null!=(o=s.Message.getField(e,27))&&t.writeEnum(27,o),null!=(o=s.Message.getField(e,28))&&t.writeBool(28,o)},proto.NanoPBOptions.prototype.getMaxSize=function(){return s.Message.getFieldWithDefault(this,1,0)},proto.NanoPBOptions.prototype.setMaxSize=function(e){return s.Message.setField(this,1,e)},proto.NanoPBOptions.prototype.clearMaxSize=function(){return s.Message.setField(this,1,void 0)},proto.NanoPBOptions.prototype.hasMaxSize=function(){return null!=s.Message.getField(this,1)},proto.NanoPBOptions.prototype.getMaxLength=function(){return s.Message.getFieldWithDefault(this,14,0)},proto.NanoPBOptions.prototype.setMaxLength=function(e){return s.Message.setField(this,14,e)},proto.NanoPBOptions.prototype.clearMaxLength=function(){return s.Message.setField(this,14,void 0)},proto.NanoPBOptions.prototype.hasMaxLength=function(){return null!=s.Message.getField(this,14)},proto.NanoPBOptions.prototype.getMaxCount=function(){return s.Message.getFieldWithDefault(this,2,0)},proto.NanoPBOptions.prototype.setMaxCount=function(e){return s.Message.setField(this,2,e)},proto.NanoPBOptions.prototype.clearMaxCount=function(){return s.Message.setField(this,2,void 0)},proto.NanoPBOptions.prototype.hasMaxCount=function(){return null!=s.Message.getField(this,2)},proto.NanoPBOptions.prototype.getIntSize=function(){return s.Message.getFieldWithDefault(this,7,0)},proto.NanoPBOptions.prototype.setIntSize=function(e){return s.Message.setField(this,7,e)},proto.NanoPBOptions.prototype.clearIntSize=function(){return s.Message.setField(this,7,void 0)},proto.NanoPBOptions.prototype.hasIntSize=function(){return null!=s.Message.getField(this,7)},proto.NanoPBOptions.prototype.getType=function(){return s.Message.getFieldWithDefault(this,3,0)},proto.NanoPBOptions.prototype.setType=function(e){return s.Message.setField(this,3,e)},proto.NanoPBOptions.prototype.clearType=function(){return s.Message.setField(this,3,void 0)},proto.NanoPBOptions.prototype.hasType=function(){return null!=s.Message.getField(this,3)},proto.NanoPBOptions.prototype.getLongNames=function(){return s.Message.getBooleanFieldWithDefault(this,4,!0)},proto.NanoPBOptions.prototype.setLongNames=function(e){return s.Message.setField(this,4,e)},proto.NanoPBOptions.prototype.clearLongNames=function(){return s.Message.setField(this,4,void 0)},proto.NanoPBOptions.prototype.hasLongNames=function(){return null!=s.Message.getField(this,4)},proto.NanoPBOptions.prototype.getPackedStruct=function(){return s.Message.getBooleanFieldWithDefault(this,5,!1)},proto.NanoPBOptions.prototype.setPackedStruct=function(e){return s.Message.setField(this,5,e)},proto.NanoPBOptions.prototype.clearPackedStruct=function(){return s.Message.setField(this,5,void 0)},proto.NanoPBOptions.prototype.hasPackedStruct=function(){return null!=s.Message.getField(this,5)},proto.NanoPBOptions.prototype.getPackedEnum=function(){return s.Message.getBooleanFieldWithDefault(this,10,!1)},proto.NanoPBOptions.prototype.setPackedEnum=function(e){return s.Message.setField(this,10,e)},proto.NanoPBOptions.prototype.clearPackedEnum=function(){return s.Message.setField(this,10,void 0)},proto.NanoPBOptions.prototype.hasPackedEnum=function(){return null!=s.Message.getField(this,10)},proto.NanoPBOptions.prototype.getSkipMessage=function(){return s.Message.getBooleanFieldWithDefault(this,6,!1)},proto.NanoPBOptions.prototype.setSkipMessage=function(e){return s.Message.setField(this,6,e)},proto.NanoPBOptions.prototype.clearSkipMessage=function(){return s.Message.setField(this,6,void 0)},proto.NanoPBOptions.prototype.hasSkipMessage=function(){return null!=s.Message.getField(this,6)},proto.NanoPBOptions.prototype.getNoUnions=function(){return s.Message.getBooleanFieldWithDefault(this,8,!1)},proto.NanoPBOptions.prototype.setNoUnions=function(e){return s.Message.setField(this,8,e)},proto.NanoPBOptions.prototype.clearNoUnions=function(){return s.Message.setField(this,8,void 0)},proto.NanoPBOptions.prototype.hasNoUnions=function(){return null!=s.Message.getField(this,8)},proto.NanoPBOptions.prototype.getMsgid=function(){return s.Message.getFieldWithDefault(this,9,0)},proto.NanoPBOptions.prototype.setMsgid=function(e){return s.Message.setField(this,9,e)},proto.NanoPBOptions.prototype.clearMsgid=function(){return s.Message.setField(this,9,void 0)},proto.NanoPBOptions.prototype.hasMsgid=function(){return null!=s.Message.getField(this,9)},proto.NanoPBOptions.prototype.getAnonymousOneof=function(){return s.Message.getBooleanFieldWithDefault(this,11,!1)},proto.NanoPBOptions.prototype.setAnonymousOneof=function(e){return s.Message.setField(this,11,e)},proto.NanoPBOptions.prototype.clearAnonymousOneof=function(){return s.Message.setField(this,11,void 0)},proto.NanoPBOptions.prototype.hasAnonymousOneof=function(){return null!=s.Message.getField(this,11)},proto.NanoPBOptions.prototype.getProto3=function(){return s.Message.getBooleanFieldWithDefault(this,12,!1)},proto.NanoPBOptions.prototype.setProto3=function(e){return s.Message.setField(this,12,e)},proto.NanoPBOptions.prototype.clearProto3=function(){return s.Message.setField(this,12,void 0)},proto.NanoPBOptions.prototype.hasProto3=function(){return null!=s.Message.getField(this,12)},proto.NanoPBOptions.prototype.getProto3SingularMsgs=function(){return s.Message.getBooleanFieldWithDefault(this,21,!1)},proto.NanoPBOptions.prototype.setProto3SingularMsgs=function(e){return s.Message.setField(this,21,e)},proto.NanoPBOptions.prototype.clearProto3SingularMsgs=function(){return s.Message.setField(this,21,void 0)},proto.NanoPBOptions.prototype.hasProto3SingularMsgs=function(){return null!=s.Message.getField(this,21)},proto.NanoPBOptions.prototype.getEnumToString=function(){return s.Message.getBooleanFieldWithDefault(this,13,!1)},proto.NanoPBOptions.prototype.setEnumToString=function(e){return s.Message.setField(this,13,e)},proto.NanoPBOptions.prototype.clearEnumToString=function(){return s.Message.setField(this,13,void 0)},proto.NanoPBOptions.prototype.hasEnumToString=function(){return null!=s.Message.getField(this,13)},proto.NanoPBOptions.prototype.getFixedLength=function(){return s.Message.getBooleanFieldWithDefault(this,15,!1)},proto.NanoPBOptions.prototype.setFixedLength=function(e){return s.Message.setField(this,15,e)},proto.NanoPBOptions.prototype.clearFixedLength=function(){return s.Message.setField(this,15,void 0)},proto.NanoPBOptions.prototype.hasFixedLength=function(){return null!=s.Message.getField(this,15)},proto.NanoPBOptions.prototype.getFixedCount=function(){return s.Message.getBooleanFieldWithDefault(this,16,!1)},proto.NanoPBOptions.prototype.setFixedCount=function(e){return s.Message.setField(this,16,e)},proto.NanoPBOptions.prototype.clearFixedCount=function(){return s.Message.setField(this,16,void 0)},proto.NanoPBOptions.prototype.hasFixedCount=function(){return null!=s.Message.getField(this,16)},proto.NanoPBOptions.prototype.getSubmsgCallback=function(){return s.Message.getBooleanFieldWithDefault(this,22,!1)},proto.NanoPBOptions.prototype.setSubmsgCallback=function(e){return s.Message.setField(this,22,e)},proto.NanoPBOptions.prototype.clearSubmsgCallback=function(){return s.Message.setField(this,22,void 0)},proto.NanoPBOptions.prototype.hasSubmsgCallback=function(){return null!=s.Message.getField(this,22)},proto.NanoPBOptions.prototype.getMangleNames=function(){return s.Message.getFieldWithDefault(this,17,0)},proto.NanoPBOptions.prototype.setMangleNames=function(e){return s.Message.setField(this,17,e)},proto.NanoPBOptions.prototype.clearMangleNames=function(){return s.Message.setField(this,17,void 0)},proto.NanoPBOptions.prototype.hasMangleNames=function(){return null!=s.Message.getField(this,17)},proto.NanoPBOptions.prototype.getCallbackDatatype=function(){return s.Message.getFieldWithDefault(this,18,"pb_callback_t")},proto.NanoPBOptions.prototype.setCallbackDatatype=function(e){return s.Message.setField(this,18,e)},proto.NanoPBOptions.prototype.clearCallbackDatatype=function(){return s.Message.setField(this,18,void 0)},proto.NanoPBOptions.prototype.hasCallbackDatatype=function(){return null!=s.Message.getField(this,18)},proto.NanoPBOptions.prototype.getCallbackFunction=function(){return s.Message.getFieldWithDefault(this,19,"pb_default_field_callback")},proto.NanoPBOptions.prototype.setCallbackFunction=function(e){return s.Message.setField(this,19,e)},proto.NanoPBOptions.prototype.clearCallbackFunction=function(){return s.Message.setField(this,19,void 0)},proto.NanoPBOptions.prototype.hasCallbackFunction=function(){return null!=s.Message.getField(this,19)},proto.NanoPBOptions.prototype.getDescriptorsize=function(){return s.Message.getFieldWithDefault(this,20,0)},proto.NanoPBOptions.prototype.setDescriptorsize=function(e){return s.Message.setField(this,20,e)},proto.NanoPBOptions.prototype.clearDescriptorsize=function(){return s.Message.setField(this,20,void 0)},proto.NanoPBOptions.prototype.hasDescriptorsize=function(){return null!=s.Message.getField(this,20)},proto.NanoPBOptions.prototype.getDefaultHas=function(){return s.Message.getBooleanFieldWithDefault(this,23,!1)},proto.NanoPBOptions.prototype.setDefaultHas=function(e){return s.Message.setField(this,23,e)},proto.NanoPBOptions.prototype.clearDefaultHas=function(){return s.Message.setField(this,23,void 0)},proto.NanoPBOptions.prototype.hasDefaultHas=function(){return null!=s.Message.getField(this,23)},proto.NanoPBOptions.prototype.getIncludeList=function(){return s.Message.getRepeatedField(this,24)},proto.NanoPBOptions.prototype.setIncludeList=function(e){return s.Message.setField(this,24,e||[])},proto.NanoPBOptions.prototype.addInclude=function(e,t){return s.Message.addToRepeatedField(this,24,e,t)},proto.NanoPBOptions.prototype.clearIncludeList=function(){return this.setIncludeList([])},proto.NanoPBOptions.prototype.getExcludeList=function(){return s.Message.getRepeatedField(this,26)},proto.NanoPBOptions.prototype.setExcludeList=function(e){return s.Message.setField(this,26,e||[])},proto.NanoPBOptions.prototype.addExclude=function(e,t){return s.Message.addToRepeatedField(this,26,e,t)},proto.NanoPBOptions.prototype.clearExcludeList=function(){return this.setExcludeList([])},proto.NanoPBOptions.prototype.getPackage=function(){return s.Message.getFieldWithDefault(this,25,"")},proto.NanoPBOptions.prototype.setPackage=function(e){return s.Message.setField(this,25,e)},proto.NanoPBOptions.prototype.clearPackage=function(){return s.Message.setField(this,25,void 0)},proto.NanoPBOptions.prototype.hasPackage=function(){return null!=s.Message.getField(this,25)},proto.NanoPBOptions.prototype.getTypeOverride=function(){return s.Message.getFieldWithDefault(this,27,1)},proto.NanoPBOptions.prototype.setTypeOverride=function(e){return s.Message.setField(this,27,e)},proto.NanoPBOptions.prototype.clearTypeOverride=function(){return s.Message.setField(this,27,void 0)},proto.NanoPBOptions.prototype.hasTypeOverride=function(){return null!=s.Message.getField(this,27)},proto.NanoPBOptions.prototype.getSortByTag=function(){return s.Message.getBooleanFieldWithDefault(this,28,!0)},proto.NanoPBOptions.prototype.setSortByTag=function(e){return s.Message.setField(this,28,e)},proto.NanoPBOptions.prototype.clearSortByTag=function(){return s.Message.setField(this,28,void 0)},proto.NanoPBOptions.prototype.hasSortByTag=function(){return null!=s.Message.getField(this,28)},proto.FieldType={FT_DEFAULT:0,FT_CALLBACK:1,FT_POINTER:4,FT_STATIC:2,FT_IGNORE:3,FT_INLINE:5},proto.IntSize={IS_DEFAULT:0,IS_8:8,IS_16:16,IS_32:32,IS_64:64},proto.TypenameMangling={M_NONE:0,M_STRIP_PACKAGE:1,M_FLATTEN:2,M_PACKAGE_INITIALS:3},proto.DescriptorSize={DS_AUTO:0,DS_1:1,DS_2:2,DS_4:4,DS_8:8},proto.nanopbFileopt=new s.ExtensionFieldInfo(1010,{nanopbFileopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),n.FileOptions.extensionsBinary[1010]=new s.ExtensionFieldBinaryInfo(proto.nanopbFileopt,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),n.FileOptions.extensions[1010]=proto.nanopbFileopt,proto.nanopbMsgopt=new s.ExtensionFieldInfo(1010,{nanopbMsgopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),n.MessageOptions.extensionsBinary[1010]=new s.ExtensionFieldBinaryInfo(proto.nanopbMsgopt,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),n.MessageOptions.extensions[1010]=proto.nanopbMsgopt,proto.nanopbEnumopt=new s.ExtensionFieldInfo(1010,{nanopbEnumopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),n.EnumOptions.extensionsBinary[1010]=new s.ExtensionFieldBinaryInfo(proto.nanopbEnumopt,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),n.EnumOptions.extensions[1010]=proto.nanopbEnumopt,proto.nanopb=new s.ExtensionFieldInfo(1010,{nanopb:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),n.FieldOptions.extensionsBinary[1010]=new s.ExtensionFieldBinaryInfo(proto.nanopb,s.BinaryReader.prototype.readMessage,s.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),n.FieldOptions.extensions[1010]=proto.nanopb,r.object.extend(t,proto)},8393:(e,t,o)=>{"use strict";o.r(t)},3607:(e,t,o)=>{"use strict";o(3138),o(8393),o(4861),o(9044),o(4874)},9044:function(e,t,o){"use strict";var s=o(9755),r=this&&this.__createBinding||(Object.create?function(e,t,o,s){void 0===s&&(s=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,s,r)}:function(e,t,o,s){void 0===s&&(s=o),e[s]=t[o]}),i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var o in e)"default"!==o&&Object.prototype.hasOwnProperty.call(e,o)&&r(t,e,o);return i(t,e),t},a=this&&this.__awaiter||function(e,t,o,s){return new(o||(o=Promise))((function(r,i){function n(e){try{p(s.next(e))}catch(e){i(e)}}function a(e){try{p(s.throw(e))}catch(e){i(e)}}function p(e){var t;e.done?r(e.value):(t=e.value,t instanceof o?t:new o((function(e){e(t)}))).then(n,a)}p((s=s.apply(e,t||[])).next())}))},p=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=o(6492);const u=p(o(646));o(3281);const y=n(o(3138));function d(){s("#flashfilename").val=null,O.StartOTA()}function c(e){"reboot_ota"==e?(s("#reboot_ota_nav").removeClass("active").prop("disabled",!0),re(500,"","reboot_ota")):(s("#reboot_nav").removeClass("active"),re(500,"",e))}function g(e){let t,o,r,i;return"string"==typeof e?(o=e,t=s(`#${o}`)):(o=s(e).attr("id"),t=s(e)),"checkbox"===t.attr("type")?(i=t.prop("checked")?o.replace("cmd_opt_",""):"",r=!0):(i=o.replace("cmd_opt_",""),r=t.val(),"string"==typeof r?r=`${r.includes(" ")?'"':""}${r}${r.includes(" ")?'"':""}`:"number"!=typeof r&&(r=r.toString())),{opt:i,val:r}}function f(){let e=function(e){const t=e&&"string"==typeof e&&e.match("[Yy1]");return t&&null!==t&&t.length>0}(u.default.get("show-nvs"));const t=s("input#show-nvs")[0];t.checked=e,t.checked||R?s('*[href*="-nvs"]').show():s('*[href*="-nvs"]').hide()}var h;window.hideSurrounding=function(e){s(e).parent().parent().hide()},window.hFlash=function(){d()},window.handleReboot=function(e){c(e)},Object.assign(String.prototype,{format(...e){return this.replace(/{(\d+)}/g,(function(t,o){const s=parseInt(o,10);return void 0!==e[s]?e[s]:t}))}}),Object.assign(String.prototype,{encodeHTML(){return l.encode(this).replace(/\n/g,"
")}}),Object.assign(Date.prototype,{toLocalShort(){return this.toLocaleString(void 0,{dateStyle:"short",timeStyle:"short"})}}),function(e){e[e.NVS_TYPE_U8=1]="NVS_TYPE_U8",e[e.NVS_TYPE_I8=17]="NVS_TYPE_I8",e[e.NVS_TYPE_U16=2]="NVS_TYPE_U16",e[e.NVS_TYPE_I16=18]="NVS_TYPE_I16",e[e.NVS_TYPE_U32=4]="NVS_TYPE_U32",e[e.NVS_TYPE_I32=20]="NVS_TYPE_I32",e[e.NVS_TYPE_U64=8]="NVS_TYPE_U64",e[e.NVS_TYPE_I64=24]="NVS_TYPE_I64",e[e.NVS_TYPE_STR=33]="NVS_TYPE_STR",e[e.NVS_TYPE_BLOB=66]="NVS_TYPE_BLOB",e[e.NVS_TYPE_ANY=255]="NVS_TYPE_ANY"}(h||(h={}));const M={bt_playing:{label:"",icon:"media_bluetooth_on"},bt_disconnected:{label:"",icon:"media_bluetooth_off"},bt_neutral:{label:"",icon:"bluetooth"},bt_connecting:{label:"",icon:"bluetooth_searching"},bt_connected:{label:"",icon:"bluetooth_connected"},bt_disabled:{label:"",icon:"bluetooth_disabled"},play_arrow:{label:"",icon:"play_circle_filled"},pause:{label:"",icon:"pause_circle"},stop:{label:"",icon:"stop_circle"},"":{label:"",icon:""}},m=[{icon:"battery_0_bar",label:"▪",ranges:[{f:5.8,t:6.8},{f:8.8,t:10.2}]},{icon:"battery_2_bar",label:"▪▪",ranges:[{f:6.8,t:7.4},{f:10.2,t:11.1}]},{icon:"battery_3_bar",label:"▪▪▪",ranges:[{f:7.4,t:7.5},{f:11.1,t:11.25}]},{icon:"battery_4_bar",label:"▪▪▪▪",ranges:[{f:7.5,t:7.8},{f:11.25,t:11.7}]}],B=[{desc:"Idle",sub:["bt_neutral"]},{desc:"Discovering",sub:["bt_connecting"]},{desc:"Discovered",sub:["bt_connecting"]},{desc:"Unconnected",sub:["bt_disconnected"]},{desc:"Connecting",sub:["bt_connecting"]},{desc:"Connected",sub:["bt_connected","play_arrow","bt_playing","pause","stop"]},{desc:"Disconnecting",sub:["bt_disconnected"]}],F={OK:0,FAIL:1,DISC:2,LOST:3,RESTORE:4,ETH:5},S=["eRunning","eReady","eBlocked","eSuspended","eDeleted"];let O={NONE:0,REBOOT_TO_RECOVERY:2,SET_FWURL:5,FLASHING:6,DONE:7,UPLOADING:8,ERROR:9,UPLOADCOMPLETE:10,_state:-1,olderRecovery:!1,statusText:"",flashURL:"",flashFileName:"",statusPercent:0,Completed:!1,recovery:!1,prevRecovery:!1,updateModal:new y.Modal(document.getElementById("otadiv"),{}),reset:function(){return this.olderRecovery=!1,this.statusText="",this.statusPercent=-1,this.flashURL="",this.flashFileName=void 0,this.UpdateProgress(),s("#rTable tr.release").removeClass("table-success table-warning"),s(".flact").prop("disabled",!1),s("#flashfilename")[0].value=null,s("#fw-url-input")[0].value=null,this.isStateError()||(s("span#flash-status").html(""),s("#fwProgressLabel").parent().removeClass("bg-danger")),this._state=this.NONE,this},isStateUploadComplete:function(){return this._state==this.UPLOADCOMPLETE},isStateError:function(){return this._state==this.ERROR},isStateNone:function(){return this._state==this.NONE},isStateRebootRecovery:function(){return this._state==this.REBOOT_TO_RECOVERY},isStateSetUrl:function(){return this._state==this.SET_FWURL},isStateFlashing:function(){return this._state==this.FLASHING},isStateDone:function(){return this._state==this.DONE},isStateUploading:function(){return this._state==this.UPLOADING},init:function(){return this._state=this.NONE,this},SetStateError:function(){return this._state=this.ERROR,s("#fwProgressLabel").parent().addClass("bg-danger"),this},SetStateNone:function(){return this._state=this.NONE,this},SetStateRebootRecovery:function(){return this._state=this.REBOOT_TO_RECOVERY,this.SetStatusText("Starting recovery mode."),s.ajax({url:"/recovery.zzz",context:this,dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now()}),error:function(e,t,o){var s;this.setOTAError(`Unexpected error while trying to restart to recovery. (status=${null!==(s=e.status)&&void 0!==s?s:""}, error=${null!=o?o:""} ) `)},complete:function(e){this.SetStatusText("Waiting for system to boot.")}}),this},SetStateSetUrl:function(){return this._state=this.SET_FWURL,this.statusText="Sending firmware download location.",I({fwurl:{value:this.flashURL,type:33}}),this},SetStateFlashing:function(){return this._state=this.FLASHING,this},SetStateDone:function(){return this._state=this.DONE,this.reset(),this},SetStateUploading:function(){return this._state=this.UPLOADING,this.SetStatusText("Sending file to device.")},SetStateUploadComplete:function(){return this._state=this.UPLOADCOMPLETE,this},isFlashExecuting:function(){return!0==(this._state!=this.UPLOADING&&(""!==this.statusText||this.statusPercent>=0))},toString:function(){return Object.keys(this).find((e=>this[e]===this._state))},setOTATargets:function(){this.flashURL="",this.flashFileName="",this.flashURL=s("#fw-url-input").val();let e=s("#flashfilename")[0].files;return e.length>0&&(this.flashFileName=e[0]),0==this.flashFileName.length&&0==this.flashURL.length&&this.setOTAError("Invalid url or file. Cannot start OTA"),this},setOTAError:function(e){return this.SetStateError().SetStatusPercent(0).SetStatusText(e).reset(),this},ShowDialog:function(){return this.isStateNone()||(this.updateModal.show(),s(".flact").prop("disabled",!0)),this},SetStatusPercent:function(e){var t=this.statusPercent!=e;return this.statusPercent=e,t&&(this.isStateUploading()||this.isStateFlashing()||this.SetStateFlashing(),100==e&&(this.isStateFlashing()?this.SetStateDone():this.isStateUploading()&&(this.statusPercent=0,this.SetStateFlashing())),this.UpdateProgress().ShowDialog()),this},SetStatusText:function(e){var t=this.statusText!=e;return this.statusText=e,t&&(s("span#flash-status").html(this.statusText),this.ShowDialog()),this},UpdateProgress:function(){return s(".progress-bar").css("width",this.statusPercent+"%").attr("aria-valuenow",this.statusPercent).text(this.statusPercent+"%"),s(".progress-bar").html((this.isStateDone()?100:this.statusPercent)+"%"),this},StartOTA:function(){return this.logEvent(this.StartOTA.name),s("#fwProgressLabel").parent().removeClass("bg-danger"),this.setOTATargets(),this.isStateError()||(R?this.SetStateFlashing().TargetReadyStartOTA():this.SetStateRebootRecovery()),this},UploadLocalFile:function(){this.SetStateUploading();const e=new XMLHttpRequest;var t=this.HandleUploadProgressEvent.bind(this),o=this.setOTAError.bind(this);e.upload.addEventListener("progress",t,!1),e.onreadystatechange=function(){4===e.readyState&&(0!==e.status&&404!==e.status||o("Upload Failed. Recovery version might not support uploading. Please use web update instead."))},e.open("POST","/flash.zzz",!0),e.send(this.flashFileName)},TargetReadyStartOTA:function(){return R&&this.prevRecovery&&!this.isStateRebootRecovery()&&!this.isStateFlashing()?this:(this.logEvent(this.TargetReadyStartOTA.name),R?(this.prevRecovery=!0,void(""!==this.flashFileName?this.UploadLocalFile():""!=this.flashURL?this.SetStateSetUrl():this.setOTAError("Invalid URL or file name while trying to start the OTa process"))):(console.error("Event TargetReadyStartOTA fired in the wrong mode "),this))},HandleUploadProgressEvent:function(e){this.logEvent(this.HandleUploadProgressEvent.name),this.SetStateUploading().SetStatusPercent(Math.round(e.loaded/e.total*100)).SetStatusText("Uploading file to device")},EventTargetStatus:function(e){var t,o;this.isStateNone()||this.logEvent(this.EventTargetStatus.name),null!==(t=e.ota_pct)&&void 0!==t&&t&&(this.olderRecovery=!0,this.SetStatusPercent(e.ota_pct)),""!=(null!==(o=e.ota_dsc)&&void 0!==o?o:"")&&(this.olderRecovery=!0,this.SetStatusText(e.ota_dsc)),null!=e.recovery&&(this.recovery=1===e.recovery),this.isStateRebootRecovery()&&this.recovery&&this.TargetReadyStartOTA()},EventOTAMessageClass:function(e){this.logEvent(this.EventOTAMessageClass.name);var t=JSON.parse(e);this.SetStatusPercent(t.ota_pct).SetStatusText(t.ota_dsc)},logEvent:function(e){console.log(`${e}, flash state ${this.toString()}, recovery: ${this.recovery}, ota pct: ${this.statusPercent}, ota desc: ${this.statusText}`)}},b=!1,E=!1,P=2500;function I(e){let t={timestamp:Date.now(),config:e};s.ajax({url:"/config.zzz",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(t),error:w})}function D(){return null!=U&&U.hasOwnProperty("ip")&&"0.0.0.0"!=U.ip&&""!=U.ip}function v(e){return D()?e.icon:e.label}function C(e){s("#o_type").children("span").css({display:"none"});let t=!1;e!==L&&(t=!0,L=e),s("#"+L).prop("checked",!0),s("#o_"+L).css({display:"inline"}),t&&Object.entries(A[L]).forEach((([e,t])=>{s(`#cmd_opt_${e}`).val(t)}))}function w(e,t,o){console.log(e.status),console.log(o),""!==o&&Be(o,"MESSAGING_ERROR")}function W(e,t,o,r=!1){let i="table-success";"MESSAGING_WARNING"===t?i="table-warning":"MESSAGING_ERROR"===t&&(i="table-danger"),s("#toast_"+e).removeClass("table-success").removeClass("table-warning").removeClass("table-danger").addClass(i).addClass("show");let n=o.substring(0,o.length-1).encodeHTML().replace(/\n/g,"
");n=(s("#msg_"+e).html().length>0&&r?s("#msg_"+e).html()+"
":"")+n,s("#msg_"+e).html(n)}let T="https://api.github.com/repos/sle118/squeezelite-esp32/releases",R=!1,z=!1;const A={i2s:{b:"500:2000",C:"30",W:"",Z:"96000",o:"I2S"},spdif:{b:"500:2000",C:"30",W:"",Z:"48000",o:"SPDIF"},bt:{b:"500:2000",C:"30",W:"",Z:"44100",o:"BT"}};let G,k={codecs:["flac","pcm","mp3","ogg","aac","wma","alac","dsd","mad","mpg"]},N=null,_=0,x="MESSAGING_INFO",j=NaN;var L="";let U,$,q="",V="Squeezelite-ESP32",H="",J=V,Y=16,K="",X=V,Z="",Q="",ee="";const te={CONN:0,MAN:1,STS:2};function oe(e,t){return new Promise(((o,s)=>{e.then((e=>setTimeout((()=>o(e)),t)),(e=>setTimeout((()=>s(e)),t)))}))}function se(e){const t={};s("input.nvs").each((function(o,s){const r=s,i=r.attributes.getNamedItem("nvs_type");if(!e&&i){const e=parseInt(i.value,10);if(""!==r.id){const o=e<=h.NVS_TYPE_I64?parseInt(r.value,10):r.value;t[r.id]={value:o,type:e}}}else""!==r.id&&(t[r.id]=r.value)}));const o=s("#nvs-new-key").val(),r=s("#nvs-new-value").val();return o&&""!==o&&(t[o]=e?r:{value:r,type:h.NVS_TYPE_I8}),t}function re(e,t,o="reboot"){const r=`/${o}.json`;s("tbody#tasks").empty(),s("#tasks_sect").css("visibility","collapse"),oe(Promise.resolve({cmdname:t,url:r}),e).then((function(e){console.log("now triggering reboot"),s("button[onclick*='handleReboot']").addClass("rebooting"),s.ajax({complete:function(){console.log("reboot call completed"),oe(Promise.resolve(e),6e3).then((function(e){}))}})}))}function ie(e){W("cfg-audio-tmpl","MESSAGING_INFO","Saving.\n",!1);let t=`squeezelite -o ${L} `;s(".sqcmd").each((function(){let{opt:e,val:o}=g(s(this));if(e&&e.length>0&&"boolean"==typeof o||"string"==typeof o&&o.length>0){o="boolean"==typeof o?"":o,t+=`${":"===e?e:` -${e} `} ${o}`}}));const o=s("#cmd_opt_R input[name=resample]:checked");o.length>0&&""!==o.attr("suffix")&&(t+=o.attr("suffix"),s("#resample_i").is(":checked")&&"true"==o.attr("aint")&&(t+=s("#resample_i").attr("suffix"))),"bt"===L&&W("cfg-audio-tmpl","MESSAGING_INFO","Remember to configure the Bluetooth audio device name.\n",!0);const r={timestamp:Date.now(),config:{autoexec1:{value:t,type:h.NVS_TYPE_STR}}};s.ajax({url:"/config.zzz",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(r),error:w,complete:function(t){t.responseText&&"OK"===JSON.parse(t.responseText).result?(W("cfg-audio-tmpl","MESSAGING_INFO","Done.\n",!0),e&&re(1500,"cfg-audio-tmpl")):JSON.parse(t.responseText).result?W("cfg-audio-tmpl","MESSAGING_WARNING",JSON.parse(t.responseText).Result+"\n",!0):W("cfg-audio-tmpl","MESSAGING_ERROR",t.statusText+"\n"),console.log(t.responseText)}}),console.log("sent data:",JSON.stringify(r))}function ne(e){return s(".upf").filter((function(){return s(this).text().toUpperCase()===e.toUpperCase()})).length>0&&(s("#splf").val(e).trigger("input"),!0)}function ae(e,t){const o=`cmd_opt_${e}`;let r=`${o}-error`,i=s(`#${r}`),n=s(`#${o}`);return i&&0!=i.length||(n.after(`
`),i=s(`#${r}`)),0==t.length?(i.hide(),n.removeClass("is-invalid"),n.addClass("is-valid"),i.text("")):(i.show(),i.text(t),n.removeClass("is-valid"),n.addClass("is-invalid")),i}function pe(e){return e>=-55?{label:"****",icon:"signal_wifi_statusbar_4_bar"}:e>=-60?{label:"***",icon:"network_wifi_3_bar"}:e>=-65?{label:"**",icon:"network_wifi_2_bar"}:e>=-70?{label:"*",icon:"network_wifi_1_bar"}:{label:".",icon:"signal_wifi_statusbar_null"}}function le(){(null==U?void 0:U.urc)!==F.ETH&&(s.ajaxSetup({timeout:3e3}),s.getJSON("/scan.zzz",(function(){return a(this,void 0,void 0,(function*(){var e;yield(e=2e3,new Promise((t=>setTimeout(t,e)))),s.getJSON("/ap.zzz",(function(e){e.length>0&&(e.sort((function(e,t){const o=e.rssi,s=t.rssi;return os?-1:0})),N=e,ye(N))}))}))})))}function ue(e,t,o){const s=pe(t),r={label:0==o?"🔓":"🔒",icon:0==o?"no_encryption":"lock"};return`${e}\n ${v(s)}\n \t\n ${v(r)}\n `}function ye(e){var t;let o="";if(s("#wifiTable tr td:first-of-type").text(""),s("#wifiTable tr").removeClass("table-success table-warning"),e&&(e.forEach((function(e){o+=ue(e.ssid,e.rssi,e.auth)})),s("#wifiTable").html(o)),0==s(".manual_add").length&&(s("#wifiTable").append(ue("Manual add",0,0)),s("#wifiTable tr:last").addClass("table-light text-dark").addClass("manual_add")),U&&U.ssid&&(U.urc===F.OK||U.urc===F.RESTORE)){const e=`#wifiTable td:contains("${U.ssid}")`;0==s(e).filter((function(){return s(this).text()===U.ssid})).length&&s("#wifiTable").prepend(`${ue(U.ssid,null!==(t=U.rssi)&&void 0!==t?t:0,0)}`),s(e).filter((function(){return s(this).text()===U.ssid})).siblings().first().html("✓").parent().addClass(U.urc===F.OK?"table-success":"table-warning"),s("span#foot-if").html(`SSID: ${U.ssid}, IP: ${U.ip}`);const o=pe(U.rssi),r=v(o);s("#wifiStsIcon").text(r),s("#wifiStsIcon").attr("aria-label",o.label),s("#wifiStsIcon").attr("icon",o.icon)}else(null==U?void 0:U.urc)!==F.ETH&&s("span#foot-if").html("")}function de(e){console.debug(`${this.toLocaleString()}\t${e.nme}\t${e.cpu}\t${S[e.st]}\t${e.minstk}\t${e.bprio}\t${e.cprio}\t${e.num}`),s("tbody#tasks").append(`${e.num}${e.nme}${e.cpu}${S[e.st]}${e.minstk}${e.bprio}${e.cprio}`)}function ce(){s.ajaxSetup({timeout:P}),s.getJSON("/messages.zzz",(function(e){return a(this,void 0,void 0,(function*(){for(const i of e){const e=i.current_time-i.sent_time;var t=new Date;switch(t.setTime(t.getTime()-e),i.class){case"MESSAGING_CLASS_OTA":O.EventOTAMessageClass(i.message);break;case"MESSAGING_CLASS_STATS":var o=JSON.parse(i.message);if(console.debug(t.toLocalShort()+" - Number of running tasks: "+o.ntasks),console.debug(`${t.toLocalShort()}\tname\tcpu\tstate\tminstk\tbprio\tcprio\tnum`),o.tasks){o.tasks;"collapse"===s("#tasks_sect").css("visibility")&&s("#tasks_sect").css("visibility","visible"),s("tbody#tasks").html(""),o.taskList.sort((function(e,t){return t.cpu-e.cpu})).forEach(de,t)}else"visible"===s("#tasks_sect").css("visibility")&&(s("tbody#tasks").empty(),s("#tasks_sect").css("visibility","collapse"));break;case"MESSAGING_CLASS_SYSTEM":Fe(i,t);break;case"MESSAGING_CLASS_CFGCMD":var r=i.message.split(/([^\n]*)\n(.*)/gs);W(r[1],i.type,r[2],!0)}}setTimeout(ce,P)}))})).fail((function(e,t,o){404==e.status?(s(".orec").hide(),z=!0):w(e,0,o),0==e.status&&0==e.readyState?setTimeout(ce,2*P):z||setTimeout(ce,P)}))}function ge(e){if(s("#WifiConnectDialog").is(":visible")){if(U.ip&&s("#ipAddress").text(U.ip),U.ssid&&s("#connectedToSSID").text(U.ssid),U.gw&&s("#gateway").text(U.gw),U.netmask&&s("#netmask").text(U.netmask),(void 0===$.Action||$.Action&&$.Action==te.STS)&&(s("*[class*='connecting']").hide(),s(".connecting-status").show()),G.ap_ssid&&s("#apName").text(G.ap_ssid.value),G.ap_pwd&&s("#apPass").text(G.ap_pwd.value),!e)return;switch(e.urc){case F.OK:e.ssid&&e.ssid===$.ssid&&(s("*[class*='connecting']").hide(),s(".connecting-success").show(),$.Action=te.STS);break;case F.FAIL:$.Action!=te.STS&&$.ssid==e.ssid&&(s("*[class*='connecting']").hide(),s(".connecting-fail").show());break;case F.LOST:break;case F.RESTORE:$.Action!=te.STS&&$.ssid!=e.ssid&&(s("*[class*='connecting']").hide(),s(".connecting-fail").show());case F.DISC:}}}function fe(e){s(".material-icons").each((function(t,o){const s=o;s.textContent=s.getAttribute(e?"aria-label":"data-icon")||""}))}function he(e){fe(!D()),!function(e){return U&&(e.urc!==U.urc||e.ssid!==U.ssid||e.gw!==U.gw||e.netmask!==U.netmask||e.ip!==U.ip||e.rssi!==U.rssi)}(e)&&e.urc||(U=function(e){var t;return{urc:null!==(t=e.urc)&&void 0!==t?t:0,auth:void 0,pwd:void 0,dhcpname:void 0,Action:void 0,ip:e.ip,ssid:e.ssid,rssi:e.rssi,gw:e.gw,netmask:e.netmask}}(e),s(".if_eth").hide(),s(".if_wifi").hide(),e.urc&&U.urc==F.ETH?(s(".if_eth").show(),U.urc===F.ETH&&s("span#foot-if").html(`Network: Ethernet, IP: ${U.ip}`)):(s(".if_wifi").show(),ye())),ge(e)}function Me(){s.ajaxSetup({timeout:2e3}),s.getJSON("/status.zzz",(function(e){var t;if(function(e){var t;1===(null!==(t=e.recovery)&&void 0!==t?t:0)?(R=!0,s(".recovery_element").show(),s(".ota_element").hide(),s("#boot-button").html("Reboot"),s("#boot-form").attr("action","/reboot_ota.zzz")):(!R&&z&&(z=!1,setTimeout(ce,P)),R=!1,s(".recovery_element").hide(),s(".ota_element").show(),s("#boot-button").html("Recovery"),s("#boot-form").attr("action","/recovery.zzz"))}(e),f(),he(e),function(e){var t;let o={label:"",icon:""},r="";if(void 0!==e.bt_status&&void 0!==e.bt_sub_status){const s=null===(t=B[e.bt_status])||void 0===t?void 0:t.sub[e.bt_sub_status];s?(o=M[s],r=B[e.bt_status].desc):(o=M.bt_connected,r="Output status")}s("#o_type").attr("title",r),s("#o_bt").html(D()?o.label:o.icon)}(e),O.EventTargetStatus(e),e.depth&&(Y=e.depth,16==Y?s("#cmd_opt_R").show():s("#cmd_opt_R").hide()),e.project_name&&""!==e.project_name&&(J=e.project_name),e.platform_name&&""!==e.platform_name&&(X=e.platform_name),""===K&&(K=J),""===K&&(K="Squeezelite-ESP32"),e.version&&""!==e.version?(V=e.version,s("#navtitle").html(`${K}${R?"
[recovery]":""}`),s("span#foot-fw").html(`fw: ${V}, mode: ${R?"Recovery":J}`)):s("span#flash-status").html(""),e.Voltage){const t=function(e){for(const r of m)for(const i of r.ranges)if(t=e,o=i.f,s=i.t,(t-o)*(t-s)<=0)return{label:r.label,icon:r.icon};var t,o,s;return{label:"▪▪▪▪",icon:"battery_full"}}(e.Voltage);s("#battery").html(`${v(t)}`),s("#battery").attr("aria-label",t.label),s("#battery").attr("data-icon",t.icon),s("#battery").show()}else s("#battery").hide();if(""!=(null!==(t=e.message)&&void 0!==t?t:"")&&H!=e.message&&(H=e.message,Be(e.message,"MESSAGING_INFO")),E=e.is_i2c_locked,E?s("flds-cfg-hw-preset").hide():s("flds-cfg-hw-preset").show(),s("button[onclick*='handleReboot']").removeClass("rebooting"),void 0===Q||e.lms_ip!=ee&&e.lms_ip&&e.lms_port){const t="http://"+e.lms_ip+":"+e.lms_port;ee=e.lms_ip,s.ajax({url:t+"/plugins/SqueezeESP32/firmware/-check.bin",type:"HEAD",dataType:"text",cache:!1,error:function(){Q=""},success:function(){Q=t}})}s("#o_jack").css({display:Number(e.Jack)?"inline":"none"}),setTimeout(Me,2e3)})).fail((function(e,t,o){w(e,0,o),0==e.status&&0==e.readyState?setTimeout(Me,2*P):setTimeout(Me,P)}))}function me(e,t,o){return void 0!==e[t]?e[t][o]:""}function Be(e,t){Fe({message:e,type:t,class:"",sent_time:0,current_time:0},new Date)}function Fe(e,t){let o="table-success";"MESSAGING_WARNING"===e.type?(o="table-warning","MESSAGING_INFO"===x&&(x="MESSAGING_WARNING")):"MESSAGING_ERROR"===e.type&&("MESSAGING_INFO"!==x&&"MESSAGING_WARNING"!==x||(x="MESSAGING_ERROR"),o="table-danger"),++_>0&&(s("#msgcnt").removeClass("badge-success"),s("#msgcnt").removeClass("badge-warning"),s("#msgcnt").removeClass("badge-danger"),s("#msgcnt").addClass({MESSAGING_INFO:"badge-success",MESSAGING_WARNING:"badge-warning",MESSAGING_ERROR:"badge-danger"}[x]),s("#msgcnt").text(_)),s("#syslogTable").append(`${t.toLocalShort()}${e.message.encodeHTML()}`)}s((function(){s(".material-icons").each((function(e,t){t.setAttribute("data-icon",t.textContent||"")})),fe(!0),f(),O.init(),s("#fw-url-input").on("input",(function(){const e=s(this).val().toString();e.length>8&&(e.startsWith("http://")||e.startsWith("https://"))?s("#start-flash").show():s("#start-flash").hide()})),s(".upSrch").on("input",(function(){const e=this,t=e.value;s("#rTable tr").removeClass(e.id+"_hide"),t.length>0&&s(`#rTable td:nth-child(${s(e).parent().index()+1})`).filter((function(){return!s(this).text().toUpperCase().includes(t.toUpperCase())})).parent().addClass(this.id+"_hide"),s('[class*="_hide"]').hide(),s("#rTable tr").not('[class*="_hide"]').show()})),setTimeout(le,1500),s("#options input").on("input",(function(){const{opt:e,val:t}=g(this);if("c"===e||"e"===e){const o=t.toString().split(",").map((function(e){return e.trim()})).filter((function(e){return!k.codecs.includes(e)}));ae(e,o.length>0?`Invalid codec(s) ${o.join(", ")}`:"")}if("m"===e){ae(e,/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(t.toString())?"":"Invalid MAC address")}if("r"===e){ae(e,/^(\d+\.?\d*|\.\d+)-(\d+\.?\d*|\.\d+)$|^(\d+\.?\d*)$|^(\d+\.?\d*,)+\d+\.?\d*$/.test(t.toString())?"":`Invalid rate(s) ${t}. Acceptable format: |-|,,`)}})),s("#WifiConnectDialog")[0].addEventListener("shown.bs.modal",(function(e){s("*[class*='connecting']").hide(),(null==e?void 0:e.relatedTarget)&&($.Action=te.CONN,s(e.relatedTarget).children("td:eq(1)").text()==U.ssid?$.Action=te.STS:s(e.relatedTarget).is(":last-child")?($.Action=te.MAN,$.ssid="",s("#manual_ssid").val($.ssid)):($.ssid=s(e.relatedTarget).children("td:eq(1)").text(),s("#manual_ssid").val($.ssid))),$.Action!==te.STS?(s(".connecting-init").show(),s("#manual_ssid").trigger("focus")):ge()})),s("#WifiConnectDialog")[0].addEventListener("hidden.bs.modal",(function(){s("#WifiConnectDialog input").val("")})),s("#uCnfrm")[0].addEventListener("shown.bs.modal",(function(){s("#selectedFWURL").text(s("#fw-url-input").val().toString())})),s("input#show-commands")[0].checked=1===j,s('a[href^="#tab-commands"]').hide(),s("#load-nvs").on("click",(function(){s("#nvsfilename").trigger("click")})),s("#nvsfilename").on("change",(function(){const e=this;if("function"!=typeof window.FileReader)throw"The file API isn't supported on this browser.";if(!e.files)throw"This browser does not support the `files` property of the file input.";if(!e.files[0])return;const t=e.files[0];let o=new FileReader;o.onload=function(e){let t;try{t=JSON.parse(e.target.result.toString())}catch(e){alert("Parsing failed!\r\n "+e)}s("input.nvs").each((function(e,o){s(this).parent().removeClass("bg-warning").removeClass("bg-success"),t[o.id]&&(t[o.id]!==o.value?(console.log("Changed "+o.id+" "+o.value+"==>"+t[o.id]),s(this).parent().addClass("bg-warning"),s(this).val(t[o.id])):s(this).parent().addClass("bg-success"))})),s("input.nvs").children(".bg-warning")&&alert("Highlighted values were changed. Press Commit to change on the device")},o.readAsText(t),e.value=null})),s("#clear-syslog").on("click",(function(){_=0,x="MESSAGING_INFO",s("#msgcnt").text(""),s("#syslogTable").html("")})),s("#ok-credits").on("click",(function(){s("#credits").slideUp("fast",(function(){})),s("#app").slideDown("fast",(function(){}))})),s("#acredits").on("click",(function(e){e.preventDefault(),s("#app").slideUp("fast",(function(){})),s("#credits").slideDown("fast",(function(){}))})),s("input#show-commands").on("click",(function(){const e=this;e.checked=!!e.checked,e.checked?(s('a[href^="#tab-commands"]').show(),j=1):(j=0,s('a[href^="#tab-commands"]').hide())})),s("#disable-squeezelite").on("click",(function(){if(this.checked){const e=s("#cmd_opt_s").val();s("#cmd_opt_s").data("originalValue",e),s("#cmd_opt_s").val("-disable")}else{const e=s("#cmd_opt_s").data("originalValue");s("#cmd_opt_s").val(e||"")}})),s("input#show-nvs").on("click",(function(){const e=this;e.checked=!!e.checked,u.default.set("show-nvs",e.checked?"Y":"N"),f()})),s("#btn_reboot_recovery").on("click",(function(){c("recovery")})),s("#btn_reboot").on("click",(function(){c("reboot")})),s("#btn_flash").on("click",(function(){d()})),s("#save-autoexec1").on("click",(function(){ie(!1)})),s("#commit-autoexec1").on("click",(function(){ie(!0)})),s("#btn_disconnect").on("click",(function(){U={auth:void 0,pwd:void 0,dhcpname:void 0,Action:void 0,ip:void 0,ssid:void 0,rssi:void 0,gw:void 0,netmask:void 0,urc:0},ye(),s.ajax({url:"/connect.zzz",dataType:"text",method:"DELETE",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now()})})})),s("#btnJoin").on("click",(function(){$.ssid=s("#manual_ssid").val().toString(),$.pwd=s("#manual_pwd").val().toString(),$.dhcpname=s("#dhcp-name2").val().toString(),s("*[class*='connecting']").hide(),s("#ssid-wait").text($.ssid),s(".connecting").show(),s.ajax({url:"/connect.zzz",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now(),ssid:$.ssid,pwd:$.pwd}),error:w})})),s("#reboot_nav").on("click",(function(){c("reboot")})),s("#reboot_ota_nav").on("click",(function(){c("reboot_ota")})),s("#save-as-nvs").on("click",(function(){const e=se(!0),t=document.createElement("a");t.href=URL.createObjectURL(new Blob([JSON.stringify(e,null,2)],{type:"text/plain"})),t.setAttribute("download","nvs_config_"+q+"_"+Date.now()+"json"),document.body.appendChild(t),t.click(),document.body.removeChild(t)})),s("#save-nvs").on("click",(function(){I(se(!1))})),s("#fwUpload").on("click",(function(){0===document.getElementById("flashfilename").files.length?alert("No file selected!"):(s("#fw-url-input").value=null,O.StartOTA())})),s("[name=output-tmpl]").on("click",(function(){C(this.id)})),s("#chkUpdates").on("click",(function(){s("#rTable").html(""),s.getJSON(T,(function(e){const t=[];e.forEach((function(e){const o=e.name.split("#")[3];t.includes(o)||t.push(o)}));let o="";t.forEach((function(e){o+='"})),s("#fwbranch").append(o),e.forEach((function(e){let t="";e.assets.forEach((function(e){e.name.match(/\.bin$/)&&(t=e.browser_download_url)}));const o=e.name.split("#"),r=o[0],i=o[2],n=o[3];var a=r.substr(r.lastIndexOf("-")+1);a="32"==a||"16"==a?a:"";let p=e.body;p=p.replace(/'/gi,'"'),p=p.replace(/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/,"$1"),p=p.replace(/- \(.+?\) /g,"- ").encodeHTML(),s("#rTable").append(`\n ${r}${new Date(e.created_at).toLocalShort()}\n ${i}${n}${a}`)})),s("#searchfw").css("display","inline"),ne(X)||ne(J),s("#rTable tr.release").on("click",(function(){var e=this.getAttribute("fwurl");Q&&(e=e.replace(/.*\/download\//,Q+"/plugins/SqueezeESP32/firmware/")),s("#fw-url-input").val(e),s("#start-flash").show(),s("#rTable tr.release").removeClass("table-success table-warning"),s(this).addClass("table-success table-warning")}))})).fail((function(){alert("failed to fetch release history!")}))})),s("#fwcheck").on("click",(function(){s("#releaseTable").html(""),s("#fwbranch").empty(),s.getJSON(T,(function(e){let t=0;const o=[];let r;e.forEach((function(e){const t=e.name.split("#")[3];o.includes(t)||o.push(t)})),o.forEach((function(e){r+=``})),s("#fwbranch").append(r),e.forEach((function(e){let o="";e.assets.forEach((function(e){e.name.match(/\.bin$/)&&(o=e.browser_download_url)}));const r=e.name.split("#"),i=r[0],n=r[1],a=r[2],p=r[3];let l=e.body;l=l.replace(/'/gi,'"'),l=l.replace(/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/,"$1"),l=l.replace(/- \(.+?\) /g,"- ");const u=t++>6?" hide":"";s("#releaseTable").append(`${i}${new Date(e.created_at).toLocalShort()}${a}${n}${p}`)})),t>7&&(s("#releaseTable").append(""),s("#showallbutton").on("click",(function(){s("tr.hide").removeClass("hide"),s("tr#showall").addClass("hide")}))),s("#searchfw").css("display","inline")})).fail((function(){alert("failed to fetch release history!")}))})),s("#updateAP").on("click",(function(){le(),console.log("refresh AP")})),function(){s.ajaxSetup({timeout:7e3});var e=new proto.sys.request.Payload;e.setType(proto.sys.request.Type.CONFIG),e.setAction(proto.sys.request.Action.GET);var t=e.serializeBinary();s.ajax({url:"/data.bin",method:"POST",contentType:"application/octet-stream",processData:!1,data:t,success:function(e){console.log("Response received:",e);try{var t=proto.sys.Config.deserializeBinary(new Uint8Array(e));console.log("Config received:",t),document.title=t.getNames().getDevice(),q=t.getNames().getDevice(),T=t.getServices().getReleaseUrl(),s("#s_airplay").css({display:t.getServices().getAirplay().getEnabled()?"inline":"none"}),s("#s_cspot").css({display:t.getServices().getCspot().getEnabled()?"inline":"none"})}catch(e){console.error("Error decoding protobuf message:",e)}},error:function(e,t,o){console.error("Error sending config:",t,o)}}).fail((function(e,t,o){w(e,0,o)}))}(),s.ajaxSetup({timeout:7e3}),s.getJSON("/commands.zzz",(function(e){console.log(e),s(".orec").show(),e.commands.forEach((function(t){if(0===s("#flds-"+t.name).length){const o=t.name.split("-"),r="cfg"===o[0],i="#tab-"+o[0]+"-"+o[1];let n="";n+=`
${t.help.encodeHTML().replace(/\n/g,"
")}
`,t.argtable&&t.argtable.forEach((function(o){let s=o.datatype||"";const r=t.name+"-"+o.longopts,i=me(e.values,t.name,o.longopts);let a=`hasvalue=${o.hasvalue} `;a+='longopts="'+o.longopts+'" ',a+='shortopts="'+o.shortopts+'" ',a+="checkbox="+o.checkbox+" ",a+='cmdname="'+t.name+'" ',a+=`id="${r}" name="${r}" hasvalue="${o.hasvalue}" `;let p=o.mincount>0?"bg-success":"";"hidden"===o.glossary&&(a+=' style="visibility: hidden;"'),o.checkbox?n+=`
`:(n+=`
`,s.includes("|")?(p=s.startsWith("+")?" multiple ":"",s=s.replace("<","").replace("=","").replace(">",""),n+=`"):n+=``),n+=`${o.checkbox?"
":""}Previous value: ${o.checkbox?i?"Checked":"Unchecked":i||""}${o.checkbox?"":"
"}`})),n+=`
\n `,n+=r?`\n`:``,n+="
",r?s(i).append(n):s("#commands-list").append(n)}})),s(".sclk").off("click").on("click",(function(){window.runCommand(this,!1)})),s(".cclk").off("click").on("click",(function(){window.runCommand(this,!0)})),e.commands.forEach((function(t){s("[cmdname="+t.name+"]:input").val(""),s("[cmdname="+t.name+"]:checkbox").prop("checked",!1),t.argtable&&t.argtable.forEach((function(o){const r="#"+t.name+"-"+o.longopts;if(o.checkbox)s(r)[0].checked=me(e,t.name,o.longopts);else{let i=me(e,t.name,o.longopts);void 0!==i&&s(r).val(i.toString()).trigger("change"),0===s(r)[0].value.length&&(o.datatype||"").includes("|")&&(s(r)[0].value="--")}}))})),0!=s("#cfg-hw-preset-model_config").length&&(b||(b=!0,s("#cfg-hw-preset-model_config").html(""),s.getJSON("https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/",{_:(new Date).getTime()},(function(e){s.each(e,(function(e,t){s("#cfg-hw-preset-model_config").append(``),""!==Z&&Z==t.name&&s("#cfg-hw-preset-model_config").val(Z)})),""!==Z&&s("#prev_preset").show().val(Z)})).fail((function(e,t,o){const s=t+", "+o;console.log("Request Failed: "+s)}))))})).fail((function(e,t,o){404==e.status?s(".orec").hide():w(e,0,o),s("#commands-list").empty()})),ce(),Me()})),window.setURL=function(e){let t=e.dataset.url;s('[data-bs-url^="http"]').addClass("btn-success").removeClass("btn-danger"),s('[data-bs-url="'+t+'"]').addClass("btn-danger").removeClass("btn-success"),Q&&(t=t.replace(/.*\/download\//,Q+"/plugins/SqueezeESP32/firmware/")),s("#fwurl").val(t)},window.runCommand=function(e,t){let o=e.getAttribute("cmdname");W(o,"MESSAGING_INFO","Executing.",!1);const r=document.getElementById("flds-"+o),i=null==r?void 0:r.querySelectorAll("select,input");if("cfg-hw-preset"===o)return function(e,t){const o=JSON.parse(e[0].value),r=e[0].getAttribute("cmdname");console.log(`selected model: ${o.name}`);let i={timestamp:Date.now(),config:{model_config:{value:o.name,type:33}}};for(const[e,t]of Object.entries(o.config)){const o="string"==typeof t||t instanceof String?t:JSON.stringify(t);i.config[e]={value:o.toString(),type:h.NVS_TYPE_STR},W(r,"MESSAGING_INFO",`Setting ${e}=${o} `,!0)}W(r,"MESSAGING_INFO","Committing ",!0),s.ajax({url:"/config.zzz",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(i),error:function(e,t,o){w(e,0,o),W(r,"MESSAGING_ERROR",`Unexpected error ${""!==o?o:"with return status = "+e.status} `,!0)},success:function(e){W(r,"MESSAGING_INFO","Saving complete ",!0),console.log(e),t&&re(2500,r)}})}(i,t);if(o+=" ",r)for(const e of i){let t="",s="";const r="SELECT"===e.tagName,i="true"===e.getAttribute("hasvalue"),n=r&&"--"!==e.value||!r&&""!==e.value;if(!i||i&&n){const r=e.getAttribute("longopts"),n=e.getAttribute("shortopts");null!==r&&"undefined"!==r?s+="--"+r:null!==n&&"undefined"!==n&&(s="-"+n),i?(t=/\s/.test(e.value)?'"':"",o+=`${s} ${t}${e.value}${t} `):e.checked&&(o+=`${s} `)}}console.log(o);const n={timestamp:Date.now(),command:o};s.ajax({url:"/commands.zzz",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(n),error:function(e,t,o){var s=JSON.parse(this.data).command;404==e.status?W(s.substr(0,s.indexOf(" ")),"MESSAGING_ERROR",""+(R?"Limited recovery mode active. Unsupported action ":"Unexpected error while processing command"),!0):(w(e,0,o),W(s.substr(0,s.indexOf(" ")-1),"MESSAGING_ERROR",`Unexpected error ${""!==o?o:"with return status = "+e.status}`,!0))},success:function(o){s(".orec").show(),console.log(o),"Success"===JSON.parse(o).Result&&t&&re(2500,e.getAttribute("cmdname"))}})}},4861:e=>{"use strict";e.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEXIycuswsKMjI4rqqZyc3RQlpQ6jIEmJifW2dq5ursppJ8Om4zC0NAFdGYmmpb///8Hg3O4x8cHkoEggX0jko5Ks6/P0dM5r6ocoZb3+PgiiYVevrp/y8bg4uOS09FtxMDs7+7M6um529qoysik2tiNn72gAAAAF3RSTlP94Fr/Wf39BP26/////////////////kibhL0AAAGjSURBVDjLbZMJkoMgEEWtmETEJWpkiSC45P5nnF4wk7HmW2jLfzYIdFYUxbXUYp5nIbTOUFoLAR2ivIKZFQXYuu6TahSHmdAlAqWub0/QNI1jSxrHacKeWw9EdtH1xHbbyiRgCJn67JqVAr9nO2fJnBDMoUuYEvsfmxnJBM66Zj8/iYmaAPKlOvRNJAC/fz8OefINEAngAbYPEMiHTJCCAZrACciVMpCCgDEBKwsAowymMO3IAP3Btqa5vYJx0ZlcOSUZaE/AWznvnTHOyfZ/wMUQvAIg/wb27QNEH94BgGj+APsZiF8AXAhQQEMwkIYYLW7xvsENoyUoF0I0ysf0F2O743kDQNXzXM8+j8Eb6byzDEz7gtpsO1PgrXG5Nd6btNTP+YXarKTny1uQ9JiAN6vbqT9au+BzMQjAWtlq6BiYttdjiVVVqfXxWFWFkk6Cz0DTdYOFPmpHAAK/YQCJoTppQJ8A3TAxVAAhR439Bg5tKe7NgSDEje3mDsf+ovuGCUbYZb/BwoHS6ykHMYfo/U6lx8Xb/+qo3U/x/lf+VP9c/j9c3zy20WEMxgAAAABJRU5ErkJggg=="}},o={};function s(e){var r=o[e];if(void 0!==r)return r.exports;var i=o[e]={id:e,loaded:!1,exports:{}};return t[e].call(i.exports,i,i.exports,s),i.loaded=!0,i.exports}s.m=t,e=[],s.O=(t,o,r,i)=>{if(!o){var n=1/0;for(u=0;u=i)&&Object.keys(s.O).every((e=>s.O[e](o[p])))?o.splice(p--,1):(a=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[o,r,i]},s.d=(e,t)=>{for(var o in t)s.o(t,o)&&!s.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),s.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={826:0};s.O.j=t=>0===e[t];var t=(t,o)=>{var r,i,[n,a,p]=o,l=0;if(n.some((t=>0!==e[t]))){for(r in a)s.o(a,r)&&(s.m[r]=a[r]);if(p)var u=p(s)}for(t&&t(o);ls(3607)));r=s.O(r)})(); +//# sourceMappingURL=index.bundle.js.map \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/js/index.bundle.js.gz b/components/wifi-manager/webapp/dist/js/index.bundle.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..3b598edceae323fa497d61c13401970c62a99900 GIT binary patch literal 38846 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 literal 0 HcmV?d00001 diff --git a/components/wifi-manager/webapp/dist/js/index.bundle.js.map b/components/wifi-manager/webapp/dist/js/index.bundle.js.map new file mode 100644 index 00000000..be7f656c --- /dev/null +++ b/components/wifi-manager/webapp/dist/js/index.bundle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"./js/index.bundle.js","mappings":"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","sources":["webpack://squeezelite-esp32/webpack/runtime/chunk loaded","webpack://squeezelite-esp32/./src/js/proto/AirPlay_pb.js","webpack://squeezelite-esp32/./src/js/proto/Artwork_pb.js","webpack://squeezelite-esp32/./src/js/proto/Battery_pb.js","webpack://squeezelite-esp32/./src/js/proto/Buttons_pb.js","webpack://squeezelite-esp32/./src/js/proto/Common_pb.js","webpack://squeezelite-esp32/./src/js/proto/DAC_pb.js","webpack://squeezelite-esp32/./src/js/proto/DacControlSet_pb.js","webpack://squeezelite-esp32/./src/js/proto/Devices_pb.js","webpack://squeezelite-esp32/./src/js/proto/Display_pb.js","webpack://squeezelite-esp32/./src/js/proto/Equalizer_pb.js","webpack://squeezelite-esp32/./src/js/proto/Ethernet_pb.js","webpack://squeezelite-esp32/./src/js/proto/GPIO_pb.js","webpack://squeezelite-esp32/./src/js/proto/I2CBus_pb.js","webpack://squeezelite-esp32/./src/js/proto/Names_pb.js","webpack://squeezelite-esp32/./src/js/proto/Network_pb.js","webpack://squeezelite-esp32/./src/js/proto/Services_pb.js","webpack://squeezelite-esp32/./src/js/proto/Spotify_pb.js","webpack://squeezelite-esp32/./src/js/proto/Squeezelite_pb.js","webpack://squeezelite-esp32/./src/js/proto/configuration_pb.js","webpack://squeezelite-esp32/./src/js/proto/customoptions_pb.js","webpack://squeezelite-esp32/./src/js/proto/nanopb_pb.js","webpack://squeezelite-esp32/./src/index.ts","webpack://squeezelite-esp32/./src/js/custom.ts","webpack://squeezelite-esp32/webpack/bootstrap","webpack://squeezelite-esp32/webpack/runtime/define property getters","webpack://squeezelite-esp32/webpack/runtime/global","webpack://squeezelite-esp32/webpack/runtime/hasOwnProperty shorthand","webpack://squeezelite-esp32/webpack/runtime/make namespace object","webpack://squeezelite-esp32/webpack/runtime/node module decorator","webpack://squeezelite-esp32/webpack/runtime/jsonp chunk loading","webpack://squeezelite-esp32/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// source: AirPlay.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\ngoog.exportSymbol('proto.sys.AirPlay', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.AirPlay = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.AirPlay, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.AirPlay.displayName = 'proto.sys.AirPlay';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.AirPlay.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.AirPlay.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.AirPlay} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.AirPlay.toObject = function(includeInstance, msg) {\n var f, obj = {\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n port: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.AirPlay}\n */\nproto.sys.AirPlay.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.AirPlay;\n return proto.sys.AirPlay.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.AirPlay} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.AirPlay}\n */\nproto.sys.AirPlay.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setPort(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.AirPlay.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.AirPlay.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.AirPlay} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.AirPlay.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getPort();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional bool enabled = 1;\n * @return {boolean}\n */\nproto.sys.AirPlay.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.AirPlay} returns this\n */\nproto.sys.AirPlay.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional uint32 port = 2;\n * @return {number}\n */\nproto.sys.AirPlay.prototype.getPort = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.AirPlay} returns this\n */\nproto.sys.AirPlay.prototype.setPort = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: Artwork.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Artwork', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Artwork = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Artwork, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Artwork.displayName = 'proto.sys.Artwork';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Artwork.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Artwork.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Artwork} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Artwork.toObject = function(includeInstance, msg) {\n var f, obj = {\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n resize: jspb.Message.getBooleanFieldWithDefault(msg, 2, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Artwork}\n */\nproto.sys.Artwork.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Artwork;\n return proto.sys.Artwork.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Artwork} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Artwork}\n */\nproto.sys.Artwork.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 2:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setResize(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Artwork.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Artwork.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Artwork} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Artwork.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getResize();\n if (f) {\n writer.writeBool(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional bool enabled = 1;\n * @return {boolean}\n */\nproto.sys.Artwork.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Artwork} returns this\n */\nproto.sys.Artwork.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional bool resize = 2;\n * @return {boolean}\n */\nproto.sys.Artwork.prototype.getResize = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Artwork} returns this\n */\nproto.sys.Artwork.prototype.setResize = function(value) {\n return jspb.Message.setProto3BooleanField(this, 2, value);\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: Battery.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Battery', null, global);\ngoog.exportSymbol('proto.sys.BatteryAttenEnum', null, global);\ngoog.exportSymbol('proto.sys.BatteryChannelEnum', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Battery = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Battery, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Battery.displayName = 'proto.sys.Battery';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Battery.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Battery.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Battery} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Battery.toObject = function(includeInstance, msg) {\n var f, obj = {\n channel: jspb.Message.getFieldWithDefault(msg, 1, 0),\n scale: jspb.Message.getFloatingPointFieldWithDefault(msg, 2, 0.0),\n cells: jspb.Message.getFieldWithDefault(msg, 3, 0),\n atten: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Battery}\n */\nproto.sys.Battery.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Battery;\n return proto.sys.Battery.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Battery} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Battery}\n */\nproto.sys.Battery.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.BatteryChannelEnum} */ (reader.readEnum());\n msg.setChannel(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setScale(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setCells(value);\n break;\n case 4:\n var value = /** @type {!proto.sys.BatteryAttenEnum} */ (reader.readEnum());\n msg.setAtten(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Battery.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Battery.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Battery} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Battery.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getChannel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getScale();\n if (f !== 0.0) {\n writer.writeFloat(\n 2,\n f\n );\n }\n f = message.getCells();\n if (f !== 0) {\n writer.writeInt32(\n 3,\n f\n );\n }\n f = message.getAtten();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional BatteryChannelEnum channel = 1;\n * @return {!proto.sys.BatteryChannelEnum}\n */\nproto.sys.Battery.prototype.getChannel = function() {\n return /** @type {!proto.sys.BatteryChannelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.BatteryChannelEnum} value\n * @return {!proto.sys.Battery} returns this\n */\nproto.sys.Battery.prototype.setChannel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional float scale = 2;\n * @return {number}\n */\nproto.sys.Battery.prototype.getScale = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 2, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Battery} returns this\n */\nproto.sys.Battery.prototype.setScale = function(value) {\n return jspb.Message.setProto3FloatField(this, 2, value);\n};\n\n\n/**\n * optional int32 cells = 3;\n * @return {number}\n */\nproto.sys.Battery.prototype.getCells = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Battery} returns this\n */\nproto.sys.Battery.prototype.setCells = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional BatteryAttenEnum atten = 4;\n * @return {!proto.sys.BatteryAttenEnum}\n */\nproto.sys.Battery.prototype.getAtten = function() {\n return /** @type {!proto.sys.BatteryAttenEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.sys.BatteryAttenEnum} value\n * @return {!proto.sys.Battery} returns this\n */\nproto.sys.Battery.prototype.setAtten = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.BatteryChannelEnum = {\n UNSPECIFIED_CH: 0,\n CH0: 1,\n CH1: 2,\n CH2: 3,\n CH3: 4,\n CH4: 5,\n CH5: 6,\n CH6: 7,\n CH7: 8\n};\n\n/**\n * @enum {number}\n */\nproto.sys.BatteryAttenEnum = {\n UNSPECIFIED_ATT: 0,\n ATT_0: 1,\n ATT_1: 2,\n ATT_2: 3,\n ATT_3: 4\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Buttons.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Button', null, global);\ngoog.exportSymbol('proto.sys.ButtonAction', null, global);\ngoog.exportSymbol('proto.sys.ButtonActionChoice', null, global);\ngoog.exportSymbol('proto.sys.ButtonActionChoice.ActiontypeCase', null, global);\ngoog.exportSymbol('proto.sys.ButtonActions', null, global);\ngoog.exportSymbol('proto.sys.ButtonProfile', null, global);\ngoog.exportSymbol('proto.sys.KnobOnly', null, global);\ngoog.exportSymbol('proto.sys.Rotary', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ButtonActionChoice = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.sys.ButtonActionChoice.oneofGroups_);\n};\ngoog.inherits(proto.sys.ButtonActionChoice, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ButtonActionChoice.displayName = 'proto.sys.ButtonActionChoice';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ButtonActions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.ButtonActions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ButtonActions.displayName = 'proto.sys.ButtonActions';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Button = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Button, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Button.displayName = 'proto.sys.Button';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ButtonProfile = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.ButtonProfile.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.ButtonProfile, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ButtonProfile.displayName = 'proto.sys.ButtonProfile';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.KnobOnly = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.KnobOnly, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.KnobOnly.displayName = 'proto.sys.KnobOnly';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Rotary = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Rotary, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Rotary.displayName = 'proto.sys.Rotary';\n}\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.sys.ButtonActionChoice.oneofGroups_ = [[1,2]];\n\n/**\n * @enum {number}\n */\nproto.sys.ButtonActionChoice.ActiontypeCase = {\n ACTIONTYPE_NOT_SET: 0,\n ACTION: 1,\n PROFILE_NAME: 2\n};\n\n/**\n * @return {proto.sys.ButtonActionChoice.ActiontypeCase}\n */\nproto.sys.ButtonActionChoice.prototype.getActiontypeCase = function() {\n return /** @type {proto.sys.ButtonActionChoice.ActiontypeCase} */(jspb.Message.computeOneofCase(this, proto.sys.ButtonActionChoice.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ButtonActionChoice.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ButtonActionChoice.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ButtonActionChoice} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonActionChoice.toObject = function(includeInstance, msg) {\n var f, obj = {\n action: jspb.Message.getFieldWithDefault(msg, 1, 0),\n profileName: jspb.Message.getFieldWithDefault(msg, 2, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActionChoice.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ButtonActionChoice;\n return proto.sys.ButtonActionChoice.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ButtonActionChoice} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActionChoice.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.ButtonAction} */ (reader.readEnum());\n msg.setAction(value);\n break;\n case 2:\n var value = /** @type {string} */ (reader.readString());\n msg.setProfileName(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ButtonActionChoice.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ButtonActionChoice.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ButtonActionChoice} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonActionChoice.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = /** @type {!proto.sys.ButtonAction} */ (jspb.Message.getField(message, 1));\n if (f != null) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 2));\n if (f != null) {\n writer.writeString(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional ButtonAction action = 1;\n * @return {!proto.sys.ButtonAction}\n */\nproto.sys.ButtonActionChoice.prototype.getAction = function() {\n return /** @type {!proto.sys.ButtonAction} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.ButtonAction} value\n * @return {!proto.sys.ButtonActionChoice} returns this\n */\nproto.sys.ButtonActionChoice.prototype.setAction = function(value) {\n return jspb.Message.setOneofField(this, 1, proto.sys.ButtonActionChoice.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.sys.ButtonActionChoice} returns this\n */\nproto.sys.ButtonActionChoice.prototype.clearAction = function() {\n return jspb.Message.setOneofField(this, 1, proto.sys.ButtonActionChoice.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActionChoice.prototype.hasAction = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional string profile_name = 2;\n * @return {string}\n */\nproto.sys.ButtonActionChoice.prototype.getProfileName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.ButtonActionChoice} returns this\n */\nproto.sys.ButtonActionChoice.prototype.setProfileName = function(value) {\n return jspb.Message.setOneofField(this, 2, proto.sys.ButtonActionChoice.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.sys.ButtonActionChoice} returns this\n */\nproto.sys.ButtonActionChoice.prototype.clearProfileName = function() {\n return jspb.Message.setOneofField(this, 2, proto.sys.ButtonActionChoice.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActionChoice.prototype.hasProfileName = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ButtonActions.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ButtonActions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ButtonActions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonActions.toObject = function(includeInstance, msg) {\n var f, obj = {\n normal: (f = msg.getNormal()) && proto.sys.ButtonActionChoice.toObject(includeInstance, f),\n longpress: (f = msg.getLongpress()) && proto.sys.ButtonActionChoice.toObject(includeInstance, f),\n shifted: (f = msg.getShifted()) && proto.sys.ButtonActionChoice.toObject(includeInstance, f),\n longshifted: (f = msg.getLongshifted()) && proto.sys.ButtonActionChoice.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ButtonActions}\n */\nproto.sys.ButtonActions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ButtonActions;\n return proto.sys.ButtonActions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ButtonActions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ButtonActions}\n */\nproto.sys.ButtonActions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.ButtonActionChoice;\n reader.readMessage(value,proto.sys.ButtonActionChoice.deserializeBinaryFromReader);\n msg.setNormal(value);\n break;\n case 2:\n var value = new proto.sys.ButtonActionChoice;\n reader.readMessage(value,proto.sys.ButtonActionChoice.deserializeBinaryFromReader);\n msg.setLongpress(value);\n break;\n case 3:\n var value = new proto.sys.ButtonActionChoice;\n reader.readMessage(value,proto.sys.ButtonActionChoice.deserializeBinaryFromReader);\n msg.setShifted(value);\n break;\n case 4:\n var value = new proto.sys.ButtonActionChoice;\n reader.readMessage(value,proto.sys.ButtonActionChoice.deserializeBinaryFromReader);\n msg.setLongshifted(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ButtonActions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ButtonActions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ButtonActions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonActions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getNormal();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.ButtonActionChoice.serializeBinaryToWriter\n );\n }\n f = message.getLongpress();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.ButtonActionChoice.serializeBinaryToWriter\n );\n }\n f = message.getShifted();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.ButtonActionChoice.serializeBinaryToWriter\n );\n }\n f = message.getLongshifted();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.ButtonActionChoice.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional ButtonActionChoice normal = 1;\n * @return {?proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActions.prototype.getNormal = function() {\n return /** @type{?proto.sys.ButtonActionChoice} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActionChoice, 1));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActionChoice|undefined} value\n * @return {!proto.sys.ButtonActions} returns this\n*/\nproto.sys.ButtonActions.prototype.setNormal = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ButtonActions} returns this\n */\nproto.sys.ButtonActions.prototype.clearNormal = function() {\n return this.setNormal(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActions.prototype.hasNormal = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional ButtonActionChoice longpress = 2;\n * @return {?proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActions.prototype.getLongpress = function() {\n return /** @type{?proto.sys.ButtonActionChoice} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActionChoice, 2));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActionChoice|undefined} value\n * @return {!proto.sys.ButtonActions} returns this\n*/\nproto.sys.ButtonActions.prototype.setLongpress = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ButtonActions} returns this\n */\nproto.sys.ButtonActions.prototype.clearLongpress = function() {\n return this.setLongpress(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActions.prototype.hasLongpress = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional ButtonActionChoice shifted = 3;\n * @return {?proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActions.prototype.getShifted = function() {\n return /** @type{?proto.sys.ButtonActionChoice} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActionChoice, 3));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActionChoice|undefined} value\n * @return {!proto.sys.ButtonActions} returns this\n*/\nproto.sys.ButtonActions.prototype.setShifted = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ButtonActions} returns this\n */\nproto.sys.ButtonActions.prototype.clearShifted = function() {\n return this.setShifted(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActions.prototype.hasShifted = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional ButtonActionChoice longshifted = 4;\n * @return {?proto.sys.ButtonActionChoice}\n */\nproto.sys.ButtonActions.prototype.getLongshifted = function() {\n return /** @type{?proto.sys.ButtonActionChoice} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActionChoice, 4));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActionChoice|undefined} value\n * @return {!proto.sys.ButtonActions} returns this\n*/\nproto.sys.ButtonActions.prototype.setLongshifted = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ButtonActions} returns this\n */\nproto.sys.ButtonActions.prototype.clearLongshifted = function() {\n return this.setLongshifted(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ButtonActions.prototype.hasLongshifted = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Button.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Button.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Button} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Button.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpio: (f = msg.getGpio()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n pull: jspb.Message.getBooleanFieldWithDefault(msg, 2, false),\n debounce: jspb.Message.getFieldWithDefault(msg, 3, 0),\n shifter: (f = msg.getShifter()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n longduration: jspb.Message.getFieldWithDefault(msg, 5, 0),\n pressed: (f = msg.getPressed()) && proto.sys.ButtonActions.toObject(includeInstance, f),\n released: (f = msg.getReleased()) && proto.sys.ButtonActions.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Button}\n */\nproto.sys.Button.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Button;\n return proto.sys.Button.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Button} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Button}\n */\nproto.sys.Button.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n case 2:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPull(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setDebounce(value);\n break;\n case 4:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setShifter(value);\n break;\n case 5:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setLongduration(value);\n break;\n case 6:\n var value = new proto.sys.ButtonActions;\n reader.readMessage(value,proto.sys.ButtonActions.deserializeBinaryFromReader);\n msg.setPressed(value);\n break;\n case 7:\n var value = new proto.sys.ButtonActions;\n reader.readMessage(value,proto.sys.ButtonActions.deserializeBinaryFromReader);\n msg.setReleased(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Button.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Button.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Button} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Button.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getPull();\n if (f) {\n writer.writeBool(\n 2,\n f\n );\n }\n f = message.getDebounce();\n if (f !== 0) {\n writer.writeInt32(\n 3,\n f\n );\n }\n f = message.getShifter();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getLongduration();\n if (f !== 0) {\n writer.writeInt32(\n 5,\n f\n );\n }\n f = message.getPressed();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.sys.ButtonActions.serializeBinaryToWriter\n );\n }\n f = message.getReleased();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.sys.ButtonActions.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO gpio = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Button.prototype.getGpio = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Button} returns this\n*/\nproto.sys.Button.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Button.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional bool pull = 2;\n * @return {boolean}\n */\nproto.sys.Button.prototype.getPull = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.setPull = function(value) {\n return jspb.Message.setProto3BooleanField(this, 2, value);\n};\n\n\n/**\n * optional int32 debounce = 3;\n * @return {number}\n */\nproto.sys.Button.prototype.getDebounce = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.setDebounce = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional GPIO shifter = 4;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Button.prototype.getShifter = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Button} returns this\n*/\nproto.sys.Button.prototype.setShifter = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.clearShifter = function() {\n return this.setShifter(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Button.prototype.hasShifter = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional int32 longduration = 5;\n * @return {number}\n */\nproto.sys.Button.prototype.getLongduration = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.setLongduration = function(value) {\n return jspb.Message.setProto3IntField(this, 5, value);\n};\n\n\n/**\n * optional ButtonActions pressed = 6;\n * @return {?proto.sys.ButtonActions}\n */\nproto.sys.Button.prototype.getPressed = function() {\n return /** @type{?proto.sys.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActions, 6));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActions|undefined} value\n * @return {!proto.sys.Button} returns this\n*/\nproto.sys.Button.prototype.setPressed = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.clearPressed = function() {\n return this.setPressed(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Button.prototype.hasPressed = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional ButtonActions released = 7;\n * @return {?proto.sys.ButtonActions}\n */\nproto.sys.Button.prototype.getReleased = function() {\n return /** @type{?proto.sys.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.sys.ButtonActions, 7));\n};\n\n\n/**\n * @param {?proto.sys.ButtonActions|undefined} value\n * @return {!proto.sys.Button} returns this\n*/\nproto.sys.Button.prototype.setReleased = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Button} returns this\n */\nproto.sys.Button.prototype.clearReleased = function() {\n return this.setReleased(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Button.prototype.hasReleased = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.ButtonProfile.repeatedFields_ = [2];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ButtonProfile.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ButtonProfile.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ButtonProfile} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonProfile.toObject = function(includeInstance, msg) {\n var f, obj = {\n profileName: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n buttonList: jspb.Message.toObjectList(msg.getButtonList(),\n proto.sys.Button.toObject, includeInstance)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ButtonProfile}\n */\nproto.sys.ButtonProfile.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ButtonProfile;\n return proto.sys.ButtonProfile.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ButtonProfile} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ButtonProfile}\n */\nproto.sys.ButtonProfile.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setProfileName(value);\n break;\n case 2:\n var value = new proto.sys.Button;\n reader.readMessage(value,proto.sys.Button.deserializeBinaryFromReader);\n msg.addButton(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ButtonProfile.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ButtonProfile.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ButtonProfile} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ButtonProfile.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getProfileName();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getButtonList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 2,\n f,\n proto.sys.Button.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional string profile_name = 1;\n * @return {string}\n */\nproto.sys.ButtonProfile.prototype.getProfileName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.ButtonProfile} returns this\n */\nproto.sys.ButtonProfile.prototype.setProfileName = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * repeated Button button = 2;\n * @return {!Array}\n */\nproto.sys.ButtonProfile.prototype.getButtonList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.sys.Button, 2));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.ButtonProfile} returns this\n*/\nproto.sys.ButtonProfile.prototype.setButtonList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 2, value);\n};\n\n\n/**\n * @param {!proto.sys.Button=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.Button}\n */\nproto.sys.ButtonProfile.prototype.addButton = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.sys.Button, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.ButtonProfile} returns this\n */\nproto.sys.ButtonProfile.prototype.clearButtonList = function() {\n return this.setButtonList([]);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.KnobOnly.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.KnobOnly.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.KnobOnly} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.KnobOnly.toObject = function(includeInstance, msg) {\n var f, obj = {\n enable: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n delayMs: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.KnobOnly}\n */\nproto.sys.KnobOnly.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.KnobOnly;\n return proto.sys.KnobOnly.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.KnobOnly} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.KnobOnly}\n */\nproto.sys.KnobOnly.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnable(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setDelayMs(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.KnobOnly.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.KnobOnly.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.KnobOnly} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.KnobOnly.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnable();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getDelayMs();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional bool enable = 1;\n * @return {boolean}\n */\nproto.sys.KnobOnly.prototype.getEnable = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.KnobOnly} returns this\n */\nproto.sys.KnobOnly.prototype.setEnable = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional int32 delay_ms = 2;\n * @return {number}\n */\nproto.sys.KnobOnly.prototype.getDelayMs = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.KnobOnly} returns this\n */\nproto.sys.KnobOnly.prototype.setDelayMs = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Rotary.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Rotary.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Rotary} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Rotary.toObject = function(includeInstance, msg) {\n var f, obj = {\n a: (f = msg.getA()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n b: (f = msg.getB()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n sw: (f = msg.getSw()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n knobonly: (f = msg.getKnobonly()) && proto.sys.KnobOnly.toObject(includeInstance, f),\n volume: jspb.Message.getBooleanFieldWithDefault(msg, 5, false),\n longpress: jspb.Message.getBooleanFieldWithDefault(msg, 6, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Rotary}\n */\nproto.sys.Rotary.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Rotary;\n return proto.sys.Rotary.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Rotary} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Rotary}\n */\nproto.sys.Rotary.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setA(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setB(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setSw(value);\n break;\n case 4:\n var value = new proto.sys.KnobOnly;\n reader.readMessage(value,proto.sys.KnobOnly.deserializeBinaryFromReader);\n msg.setKnobonly(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setVolume(value);\n break;\n case 6:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setLongpress(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Rotary.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Rotary.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Rotary} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Rotary.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getA();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getB();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSw();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getKnobonly();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.KnobOnly.serializeBinaryToWriter\n );\n }\n f = message.getVolume();\n if (f) {\n writer.writeBool(\n 5,\n f\n );\n }\n f = message.getLongpress();\n if (f) {\n writer.writeBool(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO A = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Rotary.prototype.getA = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Rotary} returns this\n*/\nproto.sys.Rotary.prototype.setA = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.clearA = function() {\n return this.setA(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.hasA = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO B = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Rotary.prototype.getB = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Rotary} returns this\n*/\nproto.sys.Rotary.prototype.setB = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.clearB = function() {\n return this.setB(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.hasB = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO SW = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Rotary.prototype.getSw = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Rotary} returns this\n*/\nproto.sys.Rotary.prototype.setSw = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.clearSw = function() {\n return this.setSw(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.hasSw = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional KnobOnly knobonly = 4;\n * @return {?proto.sys.KnobOnly}\n */\nproto.sys.Rotary.prototype.getKnobonly = function() {\n return /** @type{?proto.sys.KnobOnly} */ (\n jspb.Message.getWrapperField(this, proto.sys.KnobOnly, 4));\n};\n\n\n/**\n * @param {?proto.sys.KnobOnly|undefined} value\n * @return {!proto.sys.Rotary} returns this\n*/\nproto.sys.Rotary.prototype.setKnobonly = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.clearKnobonly = function() {\n return this.setKnobonly(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.hasKnobonly = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional bool volume = 5;\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.getVolume = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.setVolume = function(value) {\n return jspb.Message.setProto3BooleanField(this, 5, value);\n};\n\n\n/**\n * optional bool longpress = 6;\n * @return {boolean}\n */\nproto.sys.Rotary.prototype.getLongpress = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Rotary} returns this\n */\nproto.sys.Rotary.prototype.setLongpress = function(value) {\n return jspb.Message.setProto3BooleanField(this, 6, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.ButtonAction = {\n ACTRLS_NONE: 0,\n ACTRLS_POWER: 1,\n ACTRLS_VOLUP: 2,\n ACTRLS_VOLDOWN: 3,\n ACTRLS_TOGGLE: 4,\n ACTRLS_PLAY: 5,\n ACTRLS_PAUSE: 6,\n ACTRLS_STOP: 7,\n ACTRLS_REW: 8,\n ACTRLS_FWD: 9,\n ACTRLS_PREV: 10,\n ACTRLS_NEXT: 11,\n BCTRLS_UP: 12,\n BCTRLS_DOWN: 13,\n BCTRLS_LEFT: 14,\n BCTRLS_RIGHT: 15,\n BCTRLS_PS1: 16,\n BCTRLS_PS2: 17,\n BCTRLS_PS3: 18,\n BCTRLS_PS4: 19,\n BCTRLS_PS5: 20,\n BCTRLS_PS6: 21,\n BCTRLS_PS7: 22,\n BCTRLS_PS8: 23,\n BCTRLS_PS9: 24,\n BCTRLS_PS10: 25,\n KNOB_LEFT: 26,\n KNOB_RIGHT: 27,\n KNOB_PUSH: 28,\n ACTRLS_SLEEP: 29\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Common.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.DeviceTypeEnum', null, global);\ngoog.exportSymbol('proto.sys.HostEnum', null, global);\ngoog.exportSymbol('proto.sys.PortEnum', null, global);\n/**\n * @enum {number}\n */\nproto.sys.DeviceTypeEnum = {\n UNSPECIFIED_TYPE: 0,\n DEVTYPE_SPI: 1,\n DEVTYPE_I2C: 2,\n DEVTYPE__RMII: 3\n};\n\n/**\n * @enum {number}\n */\nproto.sys.PortEnum = {\n UNSPECIFIED_SYSTPORT: 0,\n SYSTEM: 1,\n DAC_PORT: 2\n};\n\n/**\n * @enum {number}\n */\nproto.sys.HostEnum = {\n UNSPECIFIED_HOST: 0,\n HOST0: 1,\n HOST1: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: DAC.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar DacControlSet_pb = require('./DacControlSet_pb.js');\ngoog.object.extend(proto, DacControlSet_pb);\nvar I2CBus_pb = require('./I2CBus_pb.js');\ngoog.object.extend(proto, I2CBus_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.DAC', null, global);\ngoog.exportSymbol('proto.sys.DACModelEnum', null, global);\ngoog.exportSymbol('proto.sys.MCKEnum', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DAC = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.DAC, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DAC.displayName = 'proto.sys.DAC';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DAC.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DAC.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DAC} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DAC.toObject = function(includeInstance, msg) {\n var f, obj = {\n bck: (f = msg.getBck()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n ws: (f = msg.getWs()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n dout: (f = msg.getDout()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n mck: jspb.Message.getFieldWithDefault(msg, 4, 0),\n mute: (f = msg.getMute()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n model: jspb.Message.getFieldWithDefault(msg, 6, 0),\n i2c: (f = msg.getI2c()) && I2CBus_pb.I2CBus.toObject(includeInstance, f),\n daccontrolset: (f = msg.getDaccontrolset()) && DacControlSet_pb.DacControlSet.toObject(includeInstance, f),\n jackMutesAmp: jspb.Message.getBooleanFieldWithDefault(msg, 9, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DAC}\n */\nproto.sys.DAC.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DAC;\n return proto.sys.DAC.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DAC} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DAC}\n */\nproto.sys.DAC.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setBck(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setWs(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setDout(value);\n break;\n case 4:\n var value = /** @type {!proto.sys.MCKEnum} */ (reader.readEnum());\n msg.setMck(value);\n break;\n case 5:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setMute(value);\n break;\n case 6:\n var value = /** @type {!proto.sys.DACModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 7:\n var value = new I2CBus_pb.I2CBus;\n reader.readMessage(value,I2CBus_pb.I2CBus.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 8:\n var value = new DacControlSet_pb.DacControlSet;\n reader.readMessage(value,DacControlSet_pb.DacControlSet.deserializeBinaryFromReader);\n msg.setDaccontrolset(value);\n break;\n case 9:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setJackMutesAmp(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DAC.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DAC.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DAC} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DAC.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getBck();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getWs();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getDout();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMck();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n f = message.getMute();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 6,\n f\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n I2CBus_pb.I2CBus.serializeBinaryToWriter\n );\n }\n f = message.getDaccontrolset();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n DacControlSet_pb.DacControlSet.serializeBinaryToWriter\n );\n }\n f = message.getJackMutesAmp();\n if (f) {\n writer.writeBool(\n 9,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO bck = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DAC.prototype.getBck = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setBck = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearBck = function() {\n return this.setBck(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasBck = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO ws = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DAC.prototype.getWs = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setWs = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearWs = function() {\n return this.setWs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasWs = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO dout = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DAC.prototype.getDout = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setDout = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearDout = function() {\n return this.setDout(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasDout = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional MCKEnum mck = 4;\n * @return {!proto.sys.MCKEnum}\n */\nproto.sys.DAC.prototype.getMck = function() {\n return /** @type {!proto.sys.MCKEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.sys.MCKEnum} value\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.setMck = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * optional GPIO mute = 5;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DAC.prototype.getMute = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 5));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setMute = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearMute = function() {\n return this.setMute(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasMute = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional DACModelEnum model = 6;\n * @return {!proto.sys.DACModelEnum}\n */\nproto.sys.DAC.prototype.getModel = function() {\n return /** @type {!proto.sys.DACModelEnum} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {!proto.sys.DACModelEnum} value\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 6, value);\n};\n\n\n/**\n * optional I2CBus i2c = 7;\n * @return {?proto.sys.I2CBus}\n */\nproto.sys.DAC.prototype.getI2c = function() {\n return /** @type{?proto.sys.I2CBus} */ (\n jspb.Message.getWrapperField(this, I2CBus_pb.I2CBus, 7));\n};\n\n\n/**\n * @param {?proto.sys.I2CBus|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setI2c = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional DacControlSet daccontrolset = 8;\n * @return {?proto.sys.DacControlSet}\n */\nproto.sys.DAC.prototype.getDaccontrolset = function() {\n return /** @type{?proto.sys.DacControlSet} */ (\n jspb.Message.getWrapperField(this, DacControlSet_pb.DacControlSet, 8));\n};\n\n\n/**\n * @param {?proto.sys.DacControlSet|undefined} value\n * @return {!proto.sys.DAC} returns this\n*/\nproto.sys.DAC.prototype.setDaccontrolset = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.clearDaccontrolset = function() {\n return this.setDaccontrolset(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DAC.prototype.hasDaccontrolset = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional bool jack_mutes_amp = 9;\n * @return {boolean}\n */\nproto.sys.DAC.prototype.getJackMutesAmp = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DAC} returns this\n */\nproto.sys.DAC.prototype.setJackMutesAmp = function(value) {\n return jspb.Message.setProto3BooleanField(this, 9, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.DACModelEnum = {\n UNSPECIFIED_MODEL: 0,\n TAS57XX: 1,\n TAS5713: 2,\n AC101: 3,\n WM8978: 4,\n ES8388: 5,\n I2S: 6,\n CS4265: 7\n};\n\n/**\n * @enum {number}\n */\nproto.sys.MCKEnum = {\n UNSPECIFIED_MCK: 0,\n MCK0: 1,\n MCK1: 2,\n MCK2: 3\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: DacControlSet.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.ControlCommand', null, global);\ngoog.exportSymbol('proto.sys.ControlCommandType', null, global);\ngoog.exportSymbol('proto.sys.ControlItem', null, global);\ngoog.exportSymbol('proto.sys.ControlItem.ItemTypeCase', null, global);\ngoog.exportSymbol('proto.sys.DacControlSet', null, global);\ngoog.exportSymbol('proto.sys.DelayAction', null, global);\ngoog.exportSymbol('proto.sys.GpioAction', null, global);\ngoog.exportSymbol('proto.sys.GpioActionLevel', null, global);\ngoog.exportSymbol('proto.sys.Mode', null, global);\ngoog.exportSymbol('proto.sys.RegisterAction', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DacControlSet = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.DacControlSet.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.DacControlSet, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DacControlSet.displayName = 'proto.sys.DacControlSet';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ControlCommand = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.ControlCommand.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.ControlCommand, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ControlCommand.displayName = 'proto.sys.ControlCommand';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ControlItem = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.sys.ControlItem.oneofGroups_);\n};\ngoog.inherits(proto.sys.ControlItem, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ControlItem.displayName = 'proto.sys.ControlItem';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.RegisterAction = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.RegisterAction, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.RegisterAction.displayName = 'proto.sys.RegisterAction';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.GpioAction = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.GpioAction, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.GpioAction.displayName = 'proto.sys.GpioAction';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DelayAction = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.DelayAction, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DelayAction.displayName = 'proto.sys.DelayAction';\n}\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.DacControlSet.repeatedFields_ = [1];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DacControlSet.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DacControlSet.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DacControlSet} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DacControlSet.toObject = function(includeInstance, msg) {\n var f, obj = {\n commandsList: jspb.Message.toObjectList(msg.getCommandsList(),\n proto.sys.ControlCommand.toObject, includeInstance)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DacControlSet}\n */\nproto.sys.DacControlSet.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DacControlSet;\n return proto.sys.DacControlSet.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DacControlSet} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DacControlSet}\n */\nproto.sys.DacControlSet.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.ControlCommand;\n reader.readMessage(value,proto.sys.ControlCommand.deserializeBinaryFromReader);\n msg.addCommands(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DacControlSet.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DacControlSet.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DacControlSet} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DacControlSet.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCommandsList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 1,\n f,\n proto.sys.ControlCommand.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * repeated ControlCommand commands = 1;\n * @return {!Array}\n */\nproto.sys.DacControlSet.prototype.getCommandsList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.sys.ControlCommand, 1));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.DacControlSet} returns this\n*/\nproto.sys.DacControlSet.prototype.setCommandsList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 1, value);\n};\n\n\n/**\n * @param {!proto.sys.ControlCommand=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.ControlCommand}\n */\nproto.sys.DacControlSet.prototype.addCommands = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.sys.ControlCommand, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.DacControlSet} returns this\n */\nproto.sys.DacControlSet.prototype.clearCommandsList = function() {\n return this.setCommandsList([]);\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.ControlCommand.repeatedFields_ = [2];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ControlCommand.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ControlCommand.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ControlCommand} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ControlCommand.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n itemsList: jspb.Message.toObjectList(msg.getItemsList(),\n proto.sys.ControlItem.toObject, includeInstance)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ControlCommand}\n */\nproto.sys.ControlCommand.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ControlCommand;\n return proto.sys.ControlCommand.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ControlCommand} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ControlCommand}\n */\nproto.sys.ControlCommand.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.ControlCommandType} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new proto.sys.ControlItem;\n reader.readMessage(value,proto.sys.ControlItem.deserializeBinaryFromReader);\n msg.addItems(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ControlCommand.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ControlCommand.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ControlCommand} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ControlCommand.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getItemsList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 2,\n f,\n proto.sys.ControlItem.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional ControlCommandType type = 1;\n * @return {!proto.sys.ControlCommandType}\n */\nproto.sys.ControlCommand.prototype.getType = function() {\n return /** @type {!proto.sys.ControlCommandType} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.ControlCommandType} value\n * @return {!proto.sys.ControlCommand} returns this\n */\nproto.sys.ControlCommand.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * repeated ControlItem items = 2;\n * @return {!Array}\n */\nproto.sys.ControlCommand.prototype.getItemsList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.sys.ControlItem, 2));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.ControlCommand} returns this\n*/\nproto.sys.ControlCommand.prototype.setItemsList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 2, value);\n};\n\n\n/**\n * @param {!proto.sys.ControlItem=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.ControlItem}\n */\nproto.sys.ControlCommand.prototype.addItems = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.sys.ControlItem, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.ControlCommand} returns this\n */\nproto.sys.ControlCommand.prototype.clearItemsList = function() {\n return this.setItemsList([]);\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.sys.ControlItem.oneofGroups_ = [[1,2,3]];\n\n/**\n * @enum {number}\n */\nproto.sys.ControlItem.ItemTypeCase = {\n ITEM_TYPE_NOT_SET: 0,\n REG_ACTION: 1,\n GPIO_ACTION: 2,\n DELAY_ACTION: 3\n};\n\n/**\n * @return {proto.sys.ControlItem.ItemTypeCase}\n */\nproto.sys.ControlItem.prototype.getItemTypeCase = function() {\n return /** @type {proto.sys.ControlItem.ItemTypeCase} */(jspb.Message.computeOneofCase(this, proto.sys.ControlItem.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ControlItem.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ControlItem.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ControlItem} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ControlItem.toObject = function(includeInstance, msg) {\n var f, obj = {\n regAction: (f = msg.getRegAction()) && proto.sys.RegisterAction.toObject(includeInstance, f),\n gpioAction: (f = msg.getGpioAction()) && proto.sys.GpioAction.toObject(includeInstance, f),\n delayAction: (f = msg.getDelayAction()) && proto.sys.DelayAction.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ControlItem}\n */\nproto.sys.ControlItem.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ControlItem;\n return proto.sys.ControlItem.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ControlItem} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ControlItem}\n */\nproto.sys.ControlItem.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.RegisterAction;\n reader.readMessage(value,proto.sys.RegisterAction.deserializeBinaryFromReader);\n msg.setRegAction(value);\n break;\n case 2:\n var value = new proto.sys.GpioAction;\n reader.readMessage(value,proto.sys.GpioAction.deserializeBinaryFromReader);\n msg.setGpioAction(value);\n break;\n case 3:\n var value = new proto.sys.DelayAction;\n reader.readMessage(value,proto.sys.DelayAction.deserializeBinaryFromReader);\n msg.setDelayAction(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ControlItem.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ControlItem.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ControlItem} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ControlItem.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getRegAction();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.RegisterAction.serializeBinaryToWriter\n );\n }\n f = message.getGpioAction();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.GpioAction.serializeBinaryToWriter\n );\n }\n f = message.getDelayAction();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.DelayAction.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional RegisterAction reg_action = 1;\n * @return {?proto.sys.RegisterAction}\n */\nproto.sys.ControlItem.prototype.getRegAction = function() {\n return /** @type{?proto.sys.RegisterAction} */ (\n jspb.Message.getWrapperField(this, proto.sys.RegisterAction, 1));\n};\n\n\n/**\n * @param {?proto.sys.RegisterAction|undefined} value\n * @return {!proto.sys.ControlItem} returns this\n*/\nproto.sys.ControlItem.prototype.setRegAction = function(value) {\n return jspb.Message.setOneofWrapperField(this, 1, proto.sys.ControlItem.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ControlItem} returns this\n */\nproto.sys.ControlItem.prototype.clearRegAction = function() {\n return this.setRegAction(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ControlItem.prototype.hasRegAction = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GpioAction gpio_action = 2;\n * @return {?proto.sys.GpioAction}\n */\nproto.sys.ControlItem.prototype.getGpioAction = function() {\n return /** @type{?proto.sys.GpioAction} */ (\n jspb.Message.getWrapperField(this, proto.sys.GpioAction, 2));\n};\n\n\n/**\n * @param {?proto.sys.GpioAction|undefined} value\n * @return {!proto.sys.ControlItem} returns this\n*/\nproto.sys.ControlItem.prototype.setGpioAction = function(value) {\n return jspb.Message.setOneofWrapperField(this, 2, proto.sys.ControlItem.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ControlItem} returns this\n */\nproto.sys.ControlItem.prototype.clearGpioAction = function() {\n return this.setGpioAction(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ControlItem.prototype.hasGpioAction = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional DelayAction delay_action = 3;\n * @return {?proto.sys.DelayAction}\n */\nproto.sys.ControlItem.prototype.getDelayAction = function() {\n return /** @type{?proto.sys.DelayAction} */ (\n jspb.Message.getWrapperField(this, proto.sys.DelayAction, 3));\n};\n\n\n/**\n * @param {?proto.sys.DelayAction|undefined} value\n * @return {!proto.sys.ControlItem} returns this\n*/\nproto.sys.ControlItem.prototype.setDelayAction = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.sys.ControlItem.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.ControlItem} returns this\n */\nproto.sys.ControlItem.prototype.clearDelayAction = function() {\n return this.setDelayAction(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.ControlItem.prototype.hasDelayAction = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.RegisterAction.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.RegisterAction.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.RegisterAction} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.RegisterAction.toObject = function(includeInstance, msg) {\n var f, obj = {\n reg: jspb.Message.getFieldWithDefault(msg, 1, 0),\n val: jspb.Message.getFieldWithDefault(msg, 2, 0),\n mode: jspb.Message.getFieldWithDefault(msg, 3, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.RegisterAction}\n */\nproto.sys.RegisterAction.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.RegisterAction;\n return proto.sys.RegisterAction.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.RegisterAction} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.RegisterAction}\n */\nproto.sys.RegisterAction.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setReg(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setVal(value);\n break;\n case 3:\n var value = /** @type {!proto.sys.Mode} */ (reader.readEnum());\n msg.setMode(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.RegisterAction.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.RegisterAction.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.RegisterAction} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.RegisterAction.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getReg();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getVal();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getMode();\n if (f !== 0.0) {\n writer.writeEnum(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional int32 reg = 1;\n * @return {number}\n */\nproto.sys.RegisterAction.prototype.getReg = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.RegisterAction} returns this\n */\nproto.sys.RegisterAction.prototype.setReg = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 val = 2;\n * @return {number}\n */\nproto.sys.RegisterAction.prototype.getVal = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.RegisterAction} returns this\n */\nproto.sys.RegisterAction.prototype.setVal = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional Mode mode = 3;\n * @return {!proto.sys.Mode}\n */\nproto.sys.RegisterAction.prototype.getMode = function() {\n return /** @type {!proto.sys.Mode} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.sys.Mode} value\n * @return {!proto.sys.RegisterAction} returns this\n */\nproto.sys.RegisterAction.prototype.setMode = function(value) {\n return jspb.Message.setProto3EnumField(this, 3, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.GpioAction.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.GpioAction.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.GpioAction} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GpioAction.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpio: jspb.Message.getFieldWithDefault(msg, 1, 0),\n level: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.GpioAction}\n */\nproto.sys.GpioAction.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.GpioAction;\n return proto.sys.GpioAction.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.GpioAction} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.GpioAction}\n */\nproto.sys.GpioAction.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setGpio(value);\n break;\n case 2:\n var value = /** @type {!proto.sys.GpioActionLevel} */ (reader.readEnum());\n msg.setLevel(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.GpioAction.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.GpioAction.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.GpioAction} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GpioAction.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpio();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getLevel();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional int32 gpio = 1;\n * @return {number}\n */\nproto.sys.GpioAction.prototype.getGpio = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GpioAction} returns this\n */\nproto.sys.GpioAction.prototype.setGpio = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional GpioActionLevel level = 2;\n * @return {!proto.sys.GpioActionLevel}\n */\nproto.sys.GpioAction.prototype.getLevel = function() {\n return /** @type {!proto.sys.GpioActionLevel} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.sys.GpioActionLevel} value\n * @return {!proto.sys.GpioAction} returns this\n */\nproto.sys.GpioAction.prototype.setLevel = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DelayAction.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DelayAction.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DelayAction} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DelayAction.toObject = function(includeInstance, msg) {\n var f, obj = {\n delay: jspb.Message.getFieldWithDefault(msg, 1, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DelayAction}\n */\nproto.sys.DelayAction.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DelayAction;\n return proto.sys.DelayAction.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DelayAction} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DelayAction}\n */\nproto.sys.DelayAction.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setDelay(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DelayAction.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DelayAction.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DelayAction} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DelayAction.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDelay();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n};\n\n\n/**\n * optional int32 delay = 1;\n * @return {number}\n */\nproto.sys.DelayAction.prototype.getDelay = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DelayAction} returns this\n */\nproto.sys.DelayAction.prototype.setDelay = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.ControlCommandType = {\n INIT: 0,\n POWER_ON: 1,\n POWER_OFF: 2,\n SPEAKER_ON: 3,\n SPEAKER_OFF: 4,\n HEADSET_ON: 5,\n HEADSET_OFF: 6\n};\n\n/**\n * @enum {number}\n */\nproto.sys.GpioActionLevel = {\n ACTION_LEVEL_UNDEFINED: 0,\n ACTION_LEVEL_1: 1,\n ACTION_LEVEL_0: 2\n};\n\n/**\n * @enum {number}\n */\nproto.sys.Mode = {\n REG_MODE_NOTHING: 0,\n REG_MODE_OR: 1,\n REG_MODE_AND: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Devices.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar Common_pb = require('./Common_pb.js');\ngoog.object.extend(proto, Common_pb);\nvar I2CBus_pb = require('./I2CBus_pb.js');\ngoog.object.extend(proto, I2CBus_pb);\nvar DAC_pb = require('./DAC_pb.js');\ngoog.object.extend(proto, DAC_pb);\nvar Display_pb = require('./Display_pb.js');\ngoog.object.extend(proto, Display_pb);\nvar Buttons_pb = require('./Buttons_pb.js');\ngoog.object.extend(proto, Buttons_pb);\nvar Battery_pb = require('./Battery_pb.js');\ngoog.object.extend(proto, Battery_pb);\nvar Ethernet_pb = require('./Ethernet_pb.js');\ngoog.object.extend(proto, Ethernet_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Dev', null, global);\ngoog.exportSymbol('proto.sys.Infrared', null, global);\ngoog.exportSymbol('proto.sys.InfraredType', null, global);\ngoog.exportSymbol('proto.sys.LEDStrip', null, global);\ngoog.exportSymbol('proto.sys.LEDStripType', null, global);\ngoog.exportSymbol('proto.sys.SPDIF', null, global);\ngoog.exportSymbol('proto.sys.SPIBus', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.SPDIF = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.SPDIF, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.SPDIF.displayName = 'proto.sys.SPDIF';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.SPIBus = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.SPIBus, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.SPIBus.displayName = 'proto.sys.SPIBus';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.LEDStrip = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.LEDStrip, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.LEDStrip.displayName = 'proto.sys.LEDStrip';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Infrared = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Infrared, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Infrared.displayName = 'proto.sys.Infrared';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Dev = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.Dev.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.Dev, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Dev.displayName = 'proto.sys.Dev';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.SPDIF.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.SPDIF.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.SPDIF} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPDIF.toObject = function(includeInstance, msg) {\n var f, obj = {\n ws: (f = msg.getWs()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n data: (f = msg.getData()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n clk: (f = msg.getClk()) && GPIO_pb.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.SPDIF}\n */\nproto.sys.SPDIF.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.SPDIF;\n return proto.sys.SPDIF.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.SPDIF} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.SPDIF}\n */\nproto.sys.SPDIF.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setWs(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setData(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setClk(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.SPDIF.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.SPDIF.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.SPDIF} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPDIF.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getWs();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getData();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getClk();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO ws = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPDIF.prototype.getWs = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPDIF} returns this\n*/\nproto.sys.SPDIF.prototype.setWs = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPDIF} returns this\n */\nproto.sys.SPDIF.prototype.clearWs = function() {\n return this.setWs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPDIF.prototype.hasWs = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO data = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPDIF.prototype.getData = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPDIF} returns this\n*/\nproto.sys.SPDIF.prototype.setData = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPDIF} returns this\n */\nproto.sys.SPDIF.prototype.clearData = function() {\n return this.setData(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPDIF.prototype.hasData = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO clk = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPDIF.prototype.getClk = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPDIF} returns this\n*/\nproto.sys.SPDIF.prototype.setClk = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPDIF} returns this\n */\nproto.sys.SPDIF.prototype.clearClk = function() {\n return this.setClk(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPDIF.prototype.hasClk = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.SPIBus.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.SPIBus.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.SPIBus} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPIBus.toObject = function(includeInstance, msg) {\n var f, obj = {\n mosi: (f = msg.getMosi()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n miso: (f = msg.getMiso()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n clk: (f = msg.getClk()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n dc: (f = msg.getDc()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n host: jspb.Message.getFieldWithDefault(msg, 5, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.SPIBus}\n */\nproto.sys.SPIBus.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.SPIBus;\n return proto.sys.SPIBus.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.SPIBus} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.SPIBus}\n */\nproto.sys.SPIBus.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setMosi(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setMiso(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setClk(value);\n break;\n case 4:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setDc(value);\n break;\n case 5:\n var value = /** @type {!proto.sys.HostEnum} */ (reader.readEnum());\n msg.setHost(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.SPIBus.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.SPIBus.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.SPIBus} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPIBus.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMosi();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMiso();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getClk();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getDc();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getHost();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO mosi = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPIBus.prototype.getMosi = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPIBus} returns this\n*/\nproto.sys.SPIBus.prototype.setMosi = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPIBus} returns this\n */\nproto.sys.SPIBus.prototype.clearMosi = function() {\n return this.setMosi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPIBus.prototype.hasMosi = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO miso = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPIBus.prototype.getMiso = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPIBus} returns this\n*/\nproto.sys.SPIBus.prototype.setMiso = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPIBus} returns this\n */\nproto.sys.SPIBus.prototype.clearMiso = function() {\n return this.setMiso(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPIBus.prototype.hasMiso = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO clk = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPIBus.prototype.getClk = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPIBus} returns this\n*/\nproto.sys.SPIBus.prototype.setClk = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPIBus} returns this\n */\nproto.sys.SPIBus.prototype.clearClk = function() {\n return this.setClk(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPIBus.prototype.hasClk = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO dc = 4;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPIBus.prototype.getDc = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPIBus} returns this\n*/\nproto.sys.SPIBus.prototype.setDc = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPIBus} returns this\n */\nproto.sys.SPIBus.prototype.clearDc = function() {\n return this.setDc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPIBus.prototype.hasDc = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional HostEnum host = 5;\n * @return {!proto.sys.HostEnum}\n */\nproto.sys.SPIBus.prototype.getHost = function() {\n return /** @type {!proto.sys.HostEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.sys.HostEnum} value\n * @return {!proto.sys.SPIBus} returns this\n */\nproto.sys.SPIBus.prototype.setHost = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.LEDStrip.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.LEDStrip.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.LEDStrip} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.LEDStrip.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpio: (f = msg.getGpio()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n length: jspb.Message.getFieldWithDefault(msg, 2, 0),\n stripType: jspb.Message.getFieldWithDefault(msg, 3, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.LEDStrip}\n */\nproto.sys.LEDStrip.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.LEDStrip;\n return proto.sys.LEDStrip.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.LEDStrip} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.LEDStrip}\n */\nproto.sys.LEDStrip.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setLength(value);\n break;\n case 3:\n var value = /** @type {!proto.sys.LEDStripType} */ (reader.readEnum());\n msg.setStripType(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.LEDStrip.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.LEDStrip.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.LEDStrip} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.LEDStrip.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getLength();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getStripType();\n if (f !== 0.0) {\n writer.writeEnum(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO gpio = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.LEDStrip.prototype.getGpio = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.LEDStrip} returns this\n*/\nproto.sys.LEDStrip.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.LEDStrip} returns this\n */\nproto.sys.LEDStrip.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.LEDStrip.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 length = 2;\n * @return {number}\n */\nproto.sys.LEDStrip.prototype.getLength = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.LEDStrip} returns this\n */\nproto.sys.LEDStrip.prototype.setLength = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional LEDStripType strip_type = 3;\n * @return {!proto.sys.LEDStripType}\n */\nproto.sys.LEDStrip.prototype.getStripType = function() {\n return /** @type {!proto.sys.LEDStripType} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.sys.LEDStripType} value\n * @return {!proto.sys.LEDStrip} returns this\n */\nproto.sys.LEDStrip.prototype.setStripType = function(value) {\n return jspb.Message.setProto3EnumField(this, 3, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Infrared.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Infrared.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Infrared} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Infrared.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n gpio: (f = msg.getGpio()) && GPIO_pb.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Infrared}\n */\nproto.sys.Infrared.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Infrared;\n return proto.sys.Infrared.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Infrared} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Infrared}\n */\nproto.sys.Infrared.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.InfraredType} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Infrared.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Infrared.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Infrared} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Infrared.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional InfraredType type = 1;\n * @return {!proto.sys.InfraredType}\n */\nproto.sys.Infrared.prototype.getType = function() {\n return /** @type {!proto.sys.InfraredType} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.InfraredType} value\n * @return {!proto.sys.Infrared} returns this\n */\nproto.sys.Infrared.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional GPIO gpio = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Infrared.prototype.getGpio = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Infrared} returns this\n*/\nproto.sys.Infrared.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Infrared} returns this\n */\nproto.sys.Infrared.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Infrared.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.Dev.repeatedFields_ = [6,9];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Dev.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Dev.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Dev} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Dev.toObject = function(includeInstance, msg) {\n var f, obj = {\n spi: (f = msg.getSpi()) && proto.sys.SPIBus.toObject(includeInstance, f),\n i2c: (f = msg.getI2c()) && I2CBus_pb.I2CBus.toObject(includeInstance, f),\n dac: (f = msg.getDac()) && DAC_pb.DAC.toObject(includeInstance, f),\n spdif: (f = msg.getSpdif()) && proto.sys.SPDIF.toObject(includeInstance, f),\n display: (f = msg.getDisplay()) && Display_pb.Display.toObject(includeInstance, f),\n gpioExpList: jspb.Message.toObjectList(msg.getGpioExpList(),\n GPIO_pb.GPIOExp.toObject, includeInstance),\n ledStrip: (f = msg.getLedStrip()) && proto.sys.LEDStrip.toObject(includeInstance, f),\n rotary: (f = msg.getRotary()) && Buttons_pb.Rotary.toObject(includeInstance, f),\n buttonsList: jspb.Message.toObjectList(msg.getButtonsList(),\n Buttons_pb.ButtonProfile.toObject, includeInstance),\n eth: (f = msg.getEth()) && Ethernet_pb.Eth.toObject(includeInstance, f),\n battery: (f = msg.getBattery()) && Battery_pb.Battery.toObject(includeInstance, f),\n ir: (f = msg.getIr()) && proto.sys.Infrared.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Dev}\n */\nproto.sys.Dev.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Dev;\n return proto.sys.Dev.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Dev} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Dev}\n */\nproto.sys.Dev.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.SPIBus;\n reader.readMessage(value,proto.sys.SPIBus.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n case 2:\n var value = new I2CBus_pb.I2CBus;\n reader.readMessage(value,I2CBus_pb.I2CBus.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 3:\n var value = new DAC_pb.DAC;\n reader.readMessage(value,DAC_pb.DAC.deserializeBinaryFromReader);\n msg.setDac(value);\n break;\n case 4:\n var value = new proto.sys.SPDIF;\n reader.readMessage(value,proto.sys.SPDIF.deserializeBinaryFromReader);\n msg.setSpdif(value);\n break;\n case 5:\n var value = new Display_pb.Display;\n reader.readMessage(value,Display_pb.Display.deserializeBinaryFromReader);\n msg.setDisplay(value);\n break;\n case 6:\n var value = new GPIO_pb.GPIOExp;\n reader.readMessage(value,GPIO_pb.GPIOExp.deserializeBinaryFromReader);\n msg.addGpioExp(value);\n break;\n case 7:\n var value = new proto.sys.LEDStrip;\n reader.readMessage(value,proto.sys.LEDStrip.deserializeBinaryFromReader);\n msg.setLedStrip(value);\n break;\n case 8:\n var value = new Buttons_pb.Rotary;\n reader.readMessage(value,Buttons_pb.Rotary.deserializeBinaryFromReader);\n msg.setRotary(value);\n break;\n case 9:\n var value = new Buttons_pb.ButtonProfile;\n reader.readMessage(value,Buttons_pb.ButtonProfile.deserializeBinaryFromReader);\n msg.addButtons(value);\n break;\n case 10:\n var value = new Ethernet_pb.Eth;\n reader.readMessage(value,Ethernet_pb.Eth.deserializeBinaryFromReader);\n msg.setEth(value);\n break;\n case 11:\n var value = new Battery_pb.Battery;\n reader.readMessage(value,Battery_pb.Battery.deserializeBinaryFromReader);\n msg.setBattery(value);\n break;\n case 12:\n var value = new proto.sys.Infrared;\n reader.readMessage(value,proto.sys.Infrared.deserializeBinaryFromReader);\n msg.setIr(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Dev.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Dev.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Dev} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Dev.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.SPIBus.serializeBinaryToWriter\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n I2CBus_pb.I2CBus.serializeBinaryToWriter\n );\n }\n f = message.getDac();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n DAC_pb.DAC.serializeBinaryToWriter\n );\n }\n f = message.getSpdif();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.SPDIF.serializeBinaryToWriter\n );\n }\n f = message.getDisplay();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n Display_pb.Display.serializeBinaryToWriter\n );\n }\n f = message.getGpioExpList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 6,\n f,\n GPIO_pb.GPIOExp.serializeBinaryToWriter\n );\n }\n f = message.getLedStrip();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.sys.LEDStrip.serializeBinaryToWriter\n );\n }\n f = message.getRotary();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n Buttons_pb.Rotary.serializeBinaryToWriter\n );\n }\n f = message.getButtonsList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 9,\n f,\n Buttons_pb.ButtonProfile.serializeBinaryToWriter\n );\n }\n f = message.getEth();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n Ethernet_pb.Eth.serializeBinaryToWriter\n );\n }\n f = message.getBattery();\n if (f != null) {\n writer.writeMessage(\n 11,\n f,\n Battery_pb.Battery.serializeBinaryToWriter\n );\n }\n f = message.getIr();\n if (f != null) {\n writer.writeMessage(\n 12,\n f,\n proto.sys.Infrared.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional SPIBus spi = 1;\n * @return {?proto.sys.SPIBus}\n */\nproto.sys.Dev.prototype.getSpi = function() {\n return /** @type{?proto.sys.SPIBus} */ (\n jspb.Message.getWrapperField(this, proto.sys.SPIBus, 1));\n};\n\n\n/**\n * @param {?proto.sys.SPIBus|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setSpi = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional I2CBus i2c = 2;\n * @return {?proto.sys.I2CBus}\n */\nproto.sys.Dev.prototype.getI2c = function() {\n return /** @type{?proto.sys.I2CBus} */ (\n jspb.Message.getWrapperField(this, I2CBus_pb.I2CBus, 2));\n};\n\n\n/**\n * @param {?proto.sys.I2CBus|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setI2c = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional DAC dac = 3;\n * @return {?proto.sys.DAC}\n */\nproto.sys.Dev.prototype.getDac = function() {\n return /** @type{?proto.sys.DAC} */ (\n jspb.Message.getWrapperField(this, DAC_pb.DAC, 3));\n};\n\n\n/**\n * @param {?proto.sys.DAC|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setDac = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearDac = function() {\n return this.setDac(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasDac = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional SPDIF spdif = 4;\n * @return {?proto.sys.SPDIF}\n */\nproto.sys.Dev.prototype.getSpdif = function() {\n return /** @type{?proto.sys.SPDIF} */ (\n jspb.Message.getWrapperField(this, proto.sys.SPDIF, 4));\n};\n\n\n/**\n * @param {?proto.sys.SPDIF|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setSpdif = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearSpdif = function() {\n return this.setSpdif(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasSpdif = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional Display display = 5;\n * @return {?proto.sys.Display}\n */\nproto.sys.Dev.prototype.getDisplay = function() {\n return /** @type{?proto.sys.Display} */ (\n jspb.Message.getWrapperField(this, Display_pb.Display, 5));\n};\n\n\n/**\n * @param {?proto.sys.Display|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setDisplay = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearDisplay = function() {\n return this.setDisplay(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasDisplay = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * repeated GPIOExp gpio_exp = 6;\n * @return {!Array}\n */\nproto.sys.Dev.prototype.getGpioExpList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, GPIO_pb.GPIOExp, 6));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setGpioExpList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 6, value);\n};\n\n\n/**\n * @param {!proto.sys.GPIOExp=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.GPIOExp}\n */\nproto.sys.Dev.prototype.addGpioExp = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 6, opt_value, proto.sys.GPIOExp, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearGpioExpList = function() {\n return this.setGpioExpList([]);\n};\n\n\n/**\n * optional LEDStrip led_strip = 7;\n * @return {?proto.sys.LEDStrip}\n */\nproto.sys.Dev.prototype.getLedStrip = function() {\n return /** @type{?proto.sys.LEDStrip} */ (\n jspb.Message.getWrapperField(this, proto.sys.LEDStrip, 7));\n};\n\n\n/**\n * @param {?proto.sys.LEDStrip|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setLedStrip = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearLedStrip = function() {\n return this.setLedStrip(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasLedStrip = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional Rotary rotary = 8;\n * @return {?proto.sys.Rotary}\n */\nproto.sys.Dev.prototype.getRotary = function() {\n return /** @type{?proto.sys.Rotary} */ (\n jspb.Message.getWrapperField(this, Buttons_pb.Rotary, 8));\n};\n\n\n/**\n * @param {?proto.sys.Rotary|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setRotary = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearRotary = function() {\n return this.setRotary(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasRotary = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * repeated ButtonProfile buttons = 9;\n * @return {!Array}\n */\nproto.sys.Dev.prototype.getButtonsList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, Buttons_pb.ButtonProfile, 9));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setButtonsList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 9, value);\n};\n\n\n/**\n * @param {!proto.sys.ButtonProfile=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.ButtonProfile}\n */\nproto.sys.Dev.prototype.addButtons = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.sys.ButtonProfile, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearButtonsList = function() {\n return this.setButtonsList([]);\n};\n\n\n/**\n * optional Eth eth = 10;\n * @return {?proto.sys.Eth}\n */\nproto.sys.Dev.prototype.getEth = function() {\n return /** @type{?proto.sys.Eth} */ (\n jspb.Message.getWrapperField(this, Ethernet_pb.Eth, 10));\n};\n\n\n/**\n * @param {?proto.sys.Eth|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setEth = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearEth = function() {\n return this.setEth(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasEth = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional Battery battery = 11;\n * @return {?proto.sys.Battery}\n */\nproto.sys.Dev.prototype.getBattery = function() {\n return /** @type{?proto.sys.Battery} */ (\n jspb.Message.getWrapperField(this, Battery_pb.Battery, 11));\n};\n\n\n/**\n * @param {?proto.sys.Battery|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setBattery = function(value) {\n return jspb.Message.setWrapperField(this, 11, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearBattery = function() {\n return this.setBattery(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasBattery = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n/**\n * optional Infrared ir = 12;\n * @return {?proto.sys.Infrared}\n */\nproto.sys.Dev.prototype.getIr = function() {\n return /** @type{?proto.sys.Infrared} */ (\n jspb.Message.getWrapperField(this, proto.sys.Infrared, 12));\n};\n\n\n/**\n * @param {?proto.sys.Infrared|undefined} value\n * @return {!proto.sys.Dev} returns this\n*/\nproto.sys.Dev.prototype.setIr = function(value) {\n return jspb.Message.setWrapperField(this, 12, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Dev} returns this\n */\nproto.sys.Dev.prototype.clearIr = function() {\n return this.setIr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Dev.prototype.hasIr = function() {\n return jspb.Message.getField(this, 12) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.LEDStripType = {\n LS_UNKNOWN: 0,\n LS_WS2812: 1,\n LS_SK6812: 2,\n LS_APA106: 3\n};\n\n/**\n * @enum {number}\n */\nproto.sys.InfraredType = {\n IR_UNKNOWN: 0,\n IR_RC5: 1,\n IR_NEC: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Display.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar Common_pb = require('./Common_pb.js');\ngoog.object.extend(proto, Common_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.DispCommon', null, global);\ngoog.exportSymbol('proto.sys.DispOffsets', null, global);\ngoog.exportSymbol('proto.sys.Display', null, global);\ngoog.exportSymbol('proto.sys.Display.DisptypeCase', null, global);\ngoog.exportSymbol('proto.sys.DisplayDriverEnum', null, global);\ngoog.exportSymbol('proto.sys.I2CDisplay', null, global);\ngoog.exportSymbol('proto.sys.SPIDisplay', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DispOffsets = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.DispOffsets, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DispOffsets.displayName = 'proto.sys.DispOffsets';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.I2CDisplay = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.I2CDisplay, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.I2CDisplay.displayName = 'proto.sys.I2CDisplay';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.SPIDisplay = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.SPIDisplay, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.SPIDisplay.displayName = 'proto.sys.SPIDisplay';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DispCommon = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.DispCommon, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DispCommon.displayName = 'proto.sys.DispCommon';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Display = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.sys.Display.oneofGroups_);\n};\ngoog.inherits(proto.sys.Display, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Display.displayName = 'proto.sys.Display';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DispOffsets.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DispOffsets.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DispOffsets} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DispOffsets.toObject = function(includeInstance, msg) {\n var f, obj = {\n height: jspb.Message.getFieldWithDefault(msg, 1, 0),\n width: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DispOffsets}\n */\nproto.sys.DispOffsets.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DispOffsets;\n return proto.sys.DispOffsets.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DispOffsets} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DispOffsets}\n */\nproto.sys.DispOffsets.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHeight(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setWidth(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DispOffsets.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DispOffsets.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DispOffsets} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DispOffsets.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getHeight();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getWidth();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional int32 height = 1;\n * @return {number}\n */\nproto.sys.DispOffsets.prototype.getHeight = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DispOffsets} returns this\n */\nproto.sys.DispOffsets.prototype.setHeight = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 width = 2;\n * @return {number}\n */\nproto.sys.DispOffsets.prototype.getWidth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DispOffsets} returns this\n */\nproto.sys.DispOffsets.prototype.setWidth = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.I2CDisplay.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.I2CDisplay.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.I2CDisplay} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.I2CDisplay.toObject = function(includeInstance, msg) {\n var f, obj = {\n address: jspb.Message.getFieldWithDefault(msg, 1, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.I2CDisplay}\n */\nproto.sys.I2CDisplay.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.I2CDisplay;\n return proto.sys.I2CDisplay.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.I2CDisplay} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.I2CDisplay}\n */\nproto.sys.I2CDisplay.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setAddress(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.I2CDisplay.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.I2CDisplay.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.I2CDisplay} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.I2CDisplay.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getAddress();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n};\n\n\n/**\n * optional int32 address = 1;\n * @return {number}\n */\nproto.sys.I2CDisplay.prototype.getAddress = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.I2CDisplay} returns this\n */\nproto.sys.I2CDisplay.prototype.setAddress = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.SPIDisplay.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.SPIDisplay.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.SPIDisplay} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPIDisplay.toObject = function(includeInstance, msg) {\n var f, obj = {\n cs: (f = msg.getCs()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n speed: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.SPIDisplay}\n */\nproto.sys.SPIDisplay.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.SPIDisplay;\n return proto.sys.SPIDisplay.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.SPIDisplay} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.SPIDisplay}\n */\nproto.sys.SPIDisplay.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.SPIDisplay.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.SPIDisplay.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.SPIDisplay} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SPIDisplay.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO cs = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SPIDisplay.prototype.getCs = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SPIDisplay} returns this\n*/\nproto.sys.SPIDisplay.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SPIDisplay} returns this\n */\nproto.sys.SPIDisplay.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SPIDisplay.prototype.hasCs = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 speed = 4;\n * @return {number}\n */\nproto.sys.SPIDisplay.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.SPIDisplay} returns this\n */\nproto.sys.SPIDisplay.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DispCommon.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DispCommon.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DispCommon} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DispCommon.toObject = function(includeInstance, msg) {\n var f, obj = {\n width: jspb.Message.getFieldWithDefault(msg, 1, 0),\n height: jspb.Message.getFieldWithDefault(msg, 2, 0),\n hflip: jspb.Message.getBooleanFieldWithDefault(msg, 3, false),\n vflip: jspb.Message.getBooleanFieldWithDefault(msg, 4, false),\n driver: jspb.Message.getFieldWithDefault(msg, 5, 0),\n bitdepth: jspb.Message.getFieldWithDefault(msg, 6, 0),\n back: (f = msg.getBack()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n reset: (f = msg.getReset()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n ready: (f = msg.getReady()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n offsets: (f = msg.getOffsets()) && proto.sys.DispOffsets.toObject(includeInstance, f),\n rotate: jspb.Message.getBooleanFieldWithDefault(msg, 11, false),\n invert: jspb.Message.getBooleanFieldWithDefault(msg, 12, false),\n colowSwap: jspb.Message.getBooleanFieldWithDefault(msg, 13, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DispCommon}\n */\nproto.sys.DispCommon.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DispCommon;\n return proto.sys.DispCommon.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DispCommon} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DispCommon}\n */\nproto.sys.DispCommon.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setWidth(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHeight(value);\n break;\n case 3:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setHflip(value);\n break;\n case 4:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setVflip(value);\n break;\n case 5:\n var value = /** @type {!proto.sys.DisplayDriverEnum} */ (reader.readEnum());\n msg.setDriver(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setBitdepth(value);\n break;\n case 7:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setBack(value);\n break;\n case 8:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setReset(value);\n break;\n case 9:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setReady(value);\n break;\n case 10:\n var value = new proto.sys.DispOffsets;\n reader.readMessage(value,proto.sys.DispOffsets.deserializeBinaryFromReader);\n msg.setOffsets(value);\n break;\n case 11:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setRotate(value);\n break;\n case 12:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setInvert(value);\n break;\n case 13:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setColowSwap(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DispCommon.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DispCommon.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DispCommon} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DispCommon.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getWidth();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getHeight();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getHflip();\n if (f) {\n writer.writeBool(\n 3,\n f\n );\n }\n f = message.getVflip();\n if (f) {\n writer.writeBool(\n 4,\n f\n );\n }\n f = message.getDriver();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n f = message.getBitdepth();\n if (f !== 0) {\n writer.writeInt32(\n 6,\n f\n );\n }\n f = message.getBack();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getReset();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getReady();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getOffsets();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n proto.sys.DispOffsets.serializeBinaryToWriter\n );\n }\n f = message.getRotate();\n if (f) {\n writer.writeBool(\n 11,\n f\n );\n }\n f = message.getInvert();\n if (f) {\n writer.writeBool(\n 12,\n f\n );\n }\n f = message.getColowSwap();\n if (f) {\n writer.writeBool(\n 13,\n f\n );\n }\n};\n\n\n/**\n * optional int32 width = 1;\n * @return {number}\n */\nproto.sys.DispCommon.prototype.getWidth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setWidth = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 height = 2;\n * @return {number}\n */\nproto.sys.DispCommon.prototype.getHeight = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setHeight = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional bool HFlip = 3;\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.getHflip = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setHflip = function(value) {\n return jspb.Message.setProto3BooleanField(this, 3, value);\n};\n\n\n/**\n * optional bool VFlip = 4;\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.getVflip = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setVflip = function(value) {\n return jspb.Message.setProto3BooleanField(this, 4, value);\n};\n\n\n/**\n * optional DisplayDriverEnum driver = 5;\n * @return {!proto.sys.DisplayDriverEnum}\n */\nproto.sys.DispCommon.prototype.getDriver = function() {\n return /** @type {!proto.sys.DisplayDriverEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.sys.DisplayDriverEnum} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setDriver = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n/**\n * optional int32 bitDepth = 6;\n * @return {number}\n */\nproto.sys.DispCommon.prototype.getBitdepth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setBitdepth = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional GPIO back = 7;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DispCommon.prototype.getBack = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DispCommon} returns this\n*/\nproto.sys.DispCommon.prototype.setBack = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.clearBack = function() {\n return this.setBack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.hasBack = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional GPIO reset = 8;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DispCommon.prototype.getReset = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 8));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DispCommon} returns this\n*/\nproto.sys.DispCommon.prototype.setReset = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.clearReset = function() {\n return this.setReset(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.hasReset = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional GPIO ready = 9;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.DispCommon.prototype.getReady = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 9));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.DispCommon} returns this\n*/\nproto.sys.DispCommon.prototype.setReady = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.clearReady = function() {\n return this.setReady(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.hasReady = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional DispOffsets offsets = 10;\n * @return {?proto.sys.DispOffsets}\n */\nproto.sys.DispCommon.prototype.getOffsets = function() {\n return /** @type{?proto.sys.DispOffsets} */ (\n jspb.Message.getWrapperField(this, proto.sys.DispOffsets, 10));\n};\n\n\n/**\n * @param {?proto.sys.DispOffsets|undefined} value\n * @return {!proto.sys.DispCommon} returns this\n*/\nproto.sys.DispCommon.prototype.setOffsets = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.clearOffsets = function() {\n return this.setOffsets(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.hasOffsets = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional bool rotate = 11;\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.getRotate = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 11, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setRotate = function(value) {\n return jspb.Message.setProto3BooleanField(this, 11, value);\n};\n\n\n/**\n * optional bool invert = 12;\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.getInvert = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 12, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setInvert = function(value) {\n return jspb.Message.setProto3BooleanField(this, 12, value);\n};\n\n\n/**\n * optional bool colow_swap = 13;\n * @return {boolean}\n */\nproto.sys.DispCommon.prototype.getColowSwap = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 13, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.DispCommon} returns this\n */\nproto.sys.DispCommon.prototype.setColowSwap = function(value) {\n return jspb.Message.setProto3BooleanField(this, 13, value);\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.sys.Display.oneofGroups_ = [[3,4]];\n\n/**\n * @enum {number}\n */\nproto.sys.Display.DisptypeCase = {\n DISPTYPE_NOT_SET: 0,\n I2C: 3,\n SPI: 4\n};\n\n/**\n * @return {proto.sys.Display.DisptypeCase}\n */\nproto.sys.Display.prototype.getDisptypeCase = function() {\n return /** @type {proto.sys.Display.DisptypeCase} */(jspb.Message.computeOneofCase(this, proto.sys.Display.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Display.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Display.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Display} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Display.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n common: (f = msg.getCommon()) && proto.sys.DispCommon.toObject(includeInstance, f),\n i2c: (f = msg.getI2c()) && proto.sys.I2CDisplay.toObject(includeInstance, f),\n spi: (f = msg.getSpi()) && proto.sys.SPIDisplay.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Display}\n */\nproto.sys.Display.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Display;\n return proto.sys.Display.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Display} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Display}\n */\nproto.sys.Display.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.DeviceTypeEnum} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new proto.sys.DispCommon;\n reader.readMessage(value,proto.sys.DispCommon.deserializeBinaryFromReader);\n msg.setCommon(value);\n break;\n case 3:\n var value = new proto.sys.I2CDisplay;\n reader.readMessage(value,proto.sys.I2CDisplay.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 4:\n var value = new proto.sys.SPIDisplay;\n reader.readMessage(value,proto.sys.SPIDisplay.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Display.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Display.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Display} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Display.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getCommon();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.DispCommon.serializeBinaryToWriter\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.I2CDisplay.serializeBinaryToWriter\n );\n }\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.SPIDisplay.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional DeviceTypeEnum type = 1;\n * @return {!proto.sys.DeviceTypeEnum}\n */\nproto.sys.Display.prototype.getType = function() {\n return /** @type {!proto.sys.DeviceTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.DeviceTypeEnum} value\n * @return {!proto.sys.Display} returns this\n */\nproto.sys.Display.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional DispCommon common = 2;\n * @return {?proto.sys.DispCommon}\n */\nproto.sys.Display.prototype.getCommon = function() {\n return /** @type{?proto.sys.DispCommon} */ (\n jspb.Message.getWrapperField(this, proto.sys.DispCommon, 2));\n};\n\n\n/**\n * @param {?proto.sys.DispCommon|undefined} value\n * @return {!proto.sys.Display} returns this\n*/\nproto.sys.Display.prototype.setCommon = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Display} returns this\n */\nproto.sys.Display.prototype.clearCommon = function() {\n return this.setCommon(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Display.prototype.hasCommon = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional I2CDisplay i2c = 3;\n * @return {?proto.sys.I2CDisplay}\n */\nproto.sys.Display.prototype.getI2c = function() {\n return /** @type{?proto.sys.I2CDisplay} */ (\n jspb.Message.getWrapperField(this, proto.sys.I2CDisplay, 3));\n};\n\n\n/**\n * @param {?proto.sys.I2CDisplay|undefined} value\n * @return {!proto.sys.Display} returns this\n*/\nproto.sys.Display.prototype.setI2c = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.sys.Display.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Display} returns this\n */\nproto.sys.Display.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Display.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional SPIDisplay spi = 4;\n * @return {?proto.sys.SPIDisplay}\n */\nproto.sys.Display.prototype.getSpi = function() {\n return /** @type{?proto.sys.SPIDisplay} */ (\n jspb.Message.getWrapperField(this, proto.sys.SPIDisplay, 4));\n};\n\n\n/**\n * @param {?proto.sys.SPIDisplay|undefined} value\n * @return {!proto.sys.Display} returns this\n*/\nproto.sys.Display.prototype.setSpi = function(value) {\n return jspb.Message.setOneofWrapperField(this, 4, proto.sys.Display.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Display} returns this\n */\nproto.sys.Display.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Display.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.DisplayDriverEnum = {\n UNSPECIFIED_DRIVER: 0,\n SSD1306: 1,\n SSD1322: 2,\n SSD1326: 3,\n SSD1327: 4,\n SH1106: 5,\n SSD1675: 6,\n ST7735: 7,\n ST7789: 8,\n ILI9341: 9,\n ILI9341_24: 10,\n SSD1351: 11\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Equalizer.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Equalizer', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Equalizer = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.Equalizer.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.Equalizer, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Equalizer.displayName = 'proto.sys.Equalizer';\n}\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.Equalizer.repeatedFields_ = [1];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Equalizer.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Equalizer.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Equalizer} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Equalizer.toObject = function(includeInstance, msg) {\n var f, obj = {\n gainsList: (f = jspb.Message.getRepeatedFloatingPointField(msg, 1)) == null ? undefined : f,\n loudness: jspb.Message.getFloatingPointFieldWithDefault(msg, 2, 0.0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Equalizer}\n */\nproto.sys.Equalizer.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Equalizer;\n return proto.sys.Equalizer.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Equalizer} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Equalizer}\n */\nproto.sys.Equalizer.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var values = /** @type {!Array} */ (reader.isDelimited() ? reader.readPackedFloat() : [reader.readFloat()]);\n for (var i = 0; i < values.length; i++) {\n msg.addGains(values[i]);\n }\n break;\n case 2:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setLoudness(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Equalizer.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Equalizer.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Equalizer} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Equalizer.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGainsList();\n if (f.length > 0) {\n writer.writePackedFloat(\n 1,\n f\n );\n }\n f = message.getLoudness();\n if (f !== 0.0) {\n writer.writeFloat(\n 2,\n f\n );\n }\n};\n\n\n/**\n * repeated float gains = 1;\n * @return {!Array}\n */\nproto.sys.Equalizer.prototype.getGainsList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedFloatingPointField(this, 1));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Equalizer} returns this\n */\nproto.sys.Equalizer.prototype.setGainsList = function(value) {\n return jspb.Message.setField(this, 1, value || []);\n};\n\n\n/**\n * @param {number} value\n * @param {number=} opt_index\n * @return {!proto.sys.Equalizer} returns this\n */\nproto.sys.Equalizer.prototype.addGains = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 1, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Equalizer} returns this\n */\nproto.sys.Equalizer.prototype.clearGainsList = function() {\n return this.setGainsList([]);\n};\n\n\n/**\n * optional float loudness = 2;\n * @return {number}\n */\nproto.sys.Equalizer.prototype.getLoudness = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 2, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Equalizer} returns this\n */\nproto.sys.Equalizer.prototype.setLoudness = function(value) {\n return jspb.Message.setProto3FloatField(this, 2, value);\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: Ethernet.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar Common_pb = require('./Common_pb.js');\ngoog.object.extend(proto, Common_pb);\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\ngoog.exportSymbol('proto.sys.Eth', null, global);\ngoog.exportSymbol('proto.sys.Eth.EthtypeCase', null, global);\ngoog.exportSymbol('proto.sys.EthCommon', null, global);\ngoog.exportSymbol('proto.sys.EthModelEnum', null, global);\ngoog.exportSymbol('proto.sys.EthRMII', null, global);\ngoog.exportSymbol('proto.sys.EthSPI', null, global);\ngoog.exportSymbol('proto.sys.EthType', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.EthCommon = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.EthCommon, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.EthCommon.displayName = 'proto.sys.EthCommon';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.EthSPI = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.EthSPI, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.EthSPI.displayName = 'proto.sys.EthSPI';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.EthRMII = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.EthRMII, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.EthRMII.displayName = 'proto.sys.EthRMII';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Eth = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.sys.Eth.oneofGroups_);\n};\ngoog.inherits(proto.sys.Eth, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Eth.displayName = 'proto.sys.Eth';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.EthCommon.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.EthCommon.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.EthCommon} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthCommon.toObject = function(includeInstance, msg) {\n var f, obj = {\n model: jspb.Message.getFieldWithDefault(msg, 1, 0),\n rst: (f = msg.getRst()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n ethtmoutS: jspb.Message.getFieldWithDefault(msg, 3, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.EthCommon}\n */\nproto.sys.EthCommon.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.EthCommon;\n return proto.sys.EthCommon.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.EthCommon} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.EthCommon}\n */\nproto.sys.EthCommon.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.EthModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setRst(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setEthtmoutS(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.EthCommon.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.EthCommon.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.EthCommon} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthCommon.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getRst();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getEthtmoutS();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional EthModelEnum model = 1;\n * @return {!proto.sys.EthModelEnum}\n */\nproto.sys.EthCommon.prototype.getModel = function() {\n return /** @type {!proto.sys.EthModelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.EthModelEnum} value\n * @return {!proto.sys.EthCommon} returns this\n */\nproto.sys.EthCommon.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional GPIO rst = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.EthCommon.prototype.getRst = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.EthCommon} returns this\n*/\nproto.sys.EthCommon.prototype.setRst = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.EthCommon} returns this\n */\nproto.sys.EthCommon.prototype.clearRst = function() {\n return this.setRst(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.EthCommon.prototype.hasRst = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional uint32 ethtmout_s = 3;\n * @return {number}\n */\nproto.sys.EthCommon.prototype.getEthtmoutS = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.EthCommon} returns this\n */\nproto.sys.EthCommon.prototype.setEthtmoutS = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.EthSPI.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.EthSPI.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.EthSPI} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthSPI.toObject = function(includeInstance, msg) {\n var f, obj = {\n cs: (f = msg.getCs()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n intr: (f = msg.getIntr()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n host: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.EthSPI}\n */\nproto.sys.EthSPI.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.EthSPI;\n return proto.sys.EthSPI.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.EthSPI} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.EthSPI}\n */\nproto.sys.EthSPI.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setIntr(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHost(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.EthSPI.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.EthSPI.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.EthSPI} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthSPI.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getIntr();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getHost();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO cs = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.EthSPI.prototype.getCs = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.EthSPI} returns this\n*/\nproto.sys.EthSPI.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.EthSPI} returns this\n */\nproto.sys.EthSPI.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.EthSPI.prototype.hasCs = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 speed = 2;\n * @return {number}\n */\nproto.sys.EthSPI.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.EthSPI} returns this\n */\nproto.sys.EthSPI.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO intr = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.EthSPI.prototype.getIntr = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.EthSPI} returns this\n*/\nproto.sys.EthSPI.prototype.setIntr = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.EthSPI} returns this\n */\nproto.sys.EthSPI.prototype.clearIntr = function() {\n return this.setIntr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.EthSPI.prototype.hasIntr = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional int32 host = 4;\n * @return {number}\n */\nproto.sys.EthSPI.prototype.getHost = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.EthSPI} returns this\n */\nproto.sys.EthSPI.prototype.setHost = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.EthRMII.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.EthRMII.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.EthRMII} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthRMII.toObject = function(includeInstance, msg) {\n var f, obj = {\n mdc: (f = msg.getMdc()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n mdio: (f = msg.getMdio()) && GPIO_pb.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.EthRMII}\n */\nproto.sys.EthRMII.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.EthRMII;\n return proto.sys.EthRMII.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.EthRMII} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.EthRMII}\n */\nproto.sys.EthRMII.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setMdc(value);\n break;\n case 2:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setMdio(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.EthRMII.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.EthRMII.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.EthRMII} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.EthRMII.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMdc();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMdio();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO mdc = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.EthRMII.prototype.getMdc = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.EthRMII} returns this\n*/\nproto.sys.EthRMII.prototype.setMdc = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.EthRMII} returns this\n */\nproto.sys.EthRMII.prototype.clearMdc = function() {\n return this.setMdc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.EthRMII.prototype.hasMdc = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO mdio = 2;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.EthRMII.prototype.getMdio = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.EthRMII} returns this\n*/\nproto.sys.EthRMII.prototype.setMdio = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.EthRMII} returns this\n */\nproto.sys.EthRMII.prototype.clearMdio = function() {\n return this.setMdio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.EthRMII.prototype.hasMdio = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.sys.Eth.oneofGroups_ = [[3,4]];\n\n/**\n * @enum {number}\n */\nproto.sys.Eth.EthtypeCase = {\n ETHTYPE_NOT_SET: 0,\n SPI: 3,\n RMII: 4\n};\n\n/**\n * @return {proto.sys.Eth.EthtypeCase}\n */\nproto.sys.Eth.prototype.getEthtypeCase = function() {\n return /** @type {proto.sys.Eth.EthtypeCase} */(jspb.Message.computeOneofCase(this, proto.sys.Eth.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Eth.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Eth.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Eth} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Eth.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n common: (f = msg.getCommon()) && proto.sys.EthCommon.toObject(includeInstance, f),\n spi: (f = msg.getSpi()) && proto.sys.EthSPI.toObject(includeInstance, f),\n rmii: (f = msg.getRmii()) && proto.sys.EthRMII.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Eth}\n */\nproto.sys.Eth.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Eth;\n return proto.sys.Eth.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Eth} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Eth}\n */\nproto.sys.Eth.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.DeviceTypeEnum} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new proto.sys.EthCommon;\n reader.readMessage(value,proto.sys.EthCommon.deserializeBinaryFromReader);\n msg.setCommon(value);\n break;\n case 3:\n var value = new proto.sys.EthSPI;\n reader.readMessage(value,proto.sys.EthSPI.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n case 4:\n var value = new proto.sys.EthRMII;\n reader.readMessage(value,proto.sys.EthRMII.deserializeBinaryFromReader);\n msg.setRmii(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Eth.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Eth.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Eth} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Eth.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getCommon();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.EthCommon.serializeBinaryToWriter\n );\n }\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.EthSPI.serializeBinaryToWriter\n );\n }\n f = message.getRmii();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.EthRMII.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional DeviceTypeEnum type = 1;\n * @return {!proto.sys.DeviceTypeEnum}\n */\nproto.sys.Eth.prototype.getType = function() {\n return /** @type {!proto.sys.DeviceTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.DeviceTypeEnum} value\n * @return {!proto.sys.Eth} returns this\n */\nproto.sys.Eth.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional EthCommon common = 2;\n * @return {?proto.sys.EthCommon}\n */\nproto.sys.Eth.prototype.getCommon = function() {\n return /** @type{?proto.sys.EthCommon} */ (\n jspb.Message.getWrapperField(this, proto.sys.EthCommon, 2));\n};\n\n\n/**\n * @param {?proto.sys.EthCommon|undefined} value\n * @return {!proto.sys.Eth} returns this\n*/\nproto.sys.Eth.prototype.setCommon = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Eth} returns this\n */\nproto.sys.Eth.prototype.clearCommon = function() {\n return this.setCommon(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Eth.prototype.hasCommon = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional EthSPI spi = 3;\n * @return {?proto.sys.EthSPI}\n */\nproto.sys.Eth.prototype.getSpi = function() {\n return /** @type{?proto.sys.EthSPI} */ (\n jspb.Message.getWrapperField(this, proto.sys.EthSPI, 3));\n};\n\n\n/**\n * @param {?proto.sys.EthSPI|undefined} value\n * @return {!proto.sys.Eth} returns this\n*/\nproto.sys.Eth.prototype.setSpi = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.sys.Eth.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Eth} returns this\n */\nproto.sys.Eth.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Eth.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional EthRMII rmii = 4;\n * @return {?proto.sys.EthRMII}\n */\nproto.sys.Eth.prototype.getRmii = function() {\n return /** @type{?proto.sys.EthRMII} */ (\n jspb.Message.getWrapperField(this, proto.sys.EthRMII, 4));\n};\n\n\n/**\n * @param {?proto.sys.EthRMII|undefined} value\n * @return {!proto.sys.Eth} returns this\n*/\nproto.sys.Eth.prototype.setRmii = function(value) {\n return jspb.Message.setOneofWrapperField(this, 4, proto.sys.Eth.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Eth} returns this\n */\nproto.sys.Eth.prototype.clearRmii = function() {\n return this.setRmii(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Eth.prototype.hasRmii = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.EthModelEnum = {\n UNSPECIFIED_ETHMODEL: 0,\n LAN8720: 1,\n DM9051: 2,\n W5500: 3\n};\n\n/**\n * @enum {number}\n */\nproto.sys.EthType = {\n UNSPECIFIED_ETH: 0,\n SPI: 1,\n RMII: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: GPIO.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar Common_pb = require('./Common_pb.js');\ngoog.object.extend(proto, Common_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.GPIO', null, global);\ngoog.exportSymbol('proto.sys.GPIOExp', null, global);\ngoog.exportSymbol('proto.sys.GPIOExp.ExptypeCase', null, global);\ngoog.exportSymbol('proto.sys.GPIOExpI2C', null, global);\ngoog.exportSymbol('proto.sys.GPIOExpModelEnum', null, global);\ngoog.exportSymbol('proto.sys.GPIOExpSPI', null, global);\ngoog.exportSymbol('proto.sys.Gpios', null, global);\ngoog.exportSymbol('proto.sys.LED', null, global);\ngoog.exportSymbol('proto.sys.LedTypesEnum', null, global);\ngoog.exportSymbol('proto.sys.LevelsEnum', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.GPIO = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.GPIO, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.GPIO.displayName = 'proto.sys.GPIO';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.LED = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.LED, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.LED.displayName = 'proto.sys.LED';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Gpios = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Gpios, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Gpios.displayName = 'proto.sys.Gpios';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.GPIOExpI2C = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.GPIOExpI2C, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.GPIOExpI2C.displayName = 'proto.sys.GPIOExpI2C';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.GPIOExpSPI = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.GPIOExpSPI, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.GPIOExpSPI.displayName = 'proto.sys.GPIOExpSPI';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.GPIOExp = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.sys.GPIOExp.oneofGroups_);\n};\ngoog.inherits(proto.sys.GPIOExp, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.GPIOExp.displayName = 'proto.sys.GPIOExp';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.GPIO.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.GPIO.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.GPIO} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIO.toObject = function(includeInstance, msg) {\n var f, obj = {\n pin: jspb.Message.getFieldWithDefault(msg, 1, 0),\n level: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.GPIO}\n */\nproto.sys.GPIO.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.GPIO;\n return proto.sys.GPIO.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.GPIO} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.GPIO}\n */\nproto.sys.GPIO.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setPin(value);\n break;\n case 2:\n var value = /** @type {!proto.sys.LevelsEnum} */ (reader.readEnum());\n msg.setLevel(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.GPIO.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.GPIO.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.GPIO} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIO.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPin();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getLevel();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional int32 pin = 1;\n * @return {number}\n */\nproto.sys.GPIO.prototype.getPin = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GPIO} returns this\n */\nproto.sys.GPIO.prototype.setPin = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional LevelsEnum level = 2;\n * @return {!proto.sys.LevelsEnum}\n */\nproto.sys.GPIO.prototype.getLevel = function() {\n return /** @type {!proto.sys.LevelsEnum} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.sys.LevelsEnum} value\n * @return {!proto.sys.GPIO} returns this\n */\nproto.sys.GPIO.prototype.setLevel = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.LED.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.LED.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.LED} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.LED.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpio: (f = msg.getGpio()) && proto.sys.GPIO.toObject(includeInstance, f),\n brightness: jspb.Message.getFieldWithDefault(msg, 2, 0),\n ledType: jspb.Message.getFieldWithDefault(msg, 3, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.LED}\n */\nproto.sys.LED.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.LED;\n return proto.sys.LED.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.LED} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.LED}\n */\nproto.sys.LED.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setBrightness(value);\n break;\n case 3:\n var value = /** @type {!proto.sys.LedTypesEnum} */ (reader.readEnum());\n msg.setLedType(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.LED.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.LED.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.LED} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.LED.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getBrightness();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getLedType();\n if (f !== 0.0) {\n writer.writeEnum(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO gpio = 1;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.LED.prototype.getGpio = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.LED} returns this\n*/\nproto.sys.LED.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.LED} returns this\n */\nproto.sys.LED.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.LED.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 brightness = 2;\n * @return {number}\n */\nproto.sys.LED.prototype.getBrightness = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.LED} returns this\n */\nproto.sys.LED.prototype.setBrightness = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional LedTypesEnum led_type = 3;\n * @return {!proto.sys.LedTypesEnum}\n */\nproto.sys.LED.prototype.getLedType = function() {\n return /** @type {!proto.sys.LedTypesEnum} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.sys.LedTypesEnum} value\n * @return {!proto.sys.LED} returns this\n */\nproto.sys.LED.prototype.setLedType = function(value) {\n return jspb.Message.setProto3EnumField(this, 3, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Gpios.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Gpios.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Gpios} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Gpios.toObject = function(includeInstance, msg) {\n var f, obj = {\n greenled: (f = msg.getGreenled()) && proto.sys.LED.toObject(includeInstance, f),\n redled: (f = msg.getRedled()) && proto.sys.LED.toObject(includeInstance, f),\n audiojack: (f = msg.getAudiojack()) && proto.sys.GPIO.toObject(includeInstance, f),\n amp: (f = msg.getAmp()) && proto.sys.GPIO.toObject(includeInstance, f),\n power: (f = msg.getPower()) && proto.sys.GPIO.toObject(includeInstance, f),\n jack: (f = msg.getJack()) && proto.sys.GPIO.toObject(includeInstance, f),\n spkfault: (f = msg.getSpkfault()) && proto.sys.GPIO.toObject(includeInstance, f),\n vcc: (f = msg.getVcc()) && proto.sys.GPIO.toObject(includeInstance, f),\n gnd: (f = msg.getGnd()) && proto.sys.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Gpios}\n */\nproto.sys.Gpios.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Gpios;\n return proto.sys.Gpios.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Gpios} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Gpios}\n */\nproto.sys.Gpios.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.LED;\n reader.readMessage(value,proto.sys.LED.deserializeBinaryFromReader);\n msg.setGreenled(value);\n break;\n case 2:\n var value = new proto.sys.LED;\n reader.readMessage(value,proto.sys.LED.deserializeBinaryFromReader);\n msg.setRedled(value);\n break;\n case 3:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setAudiojack(value);\n break;\n case 4:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setAmp(value);\n break;\n case 5:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setPower(value);\n break;\n case 6:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setJack(value);\n break;\n case 7:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setSpkfault(value);\n break;\n case 8:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setVcc(value);\n break;\n case 9:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setGnd(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Gpios.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Gpios.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Gpios} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Gpios.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGreenled();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.LED.serializeBinaryToWriter\n );\n }\n f = message.getRedled();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.LED.serializeBinaryToWriter\n );\n }\n f = message.getAudiojack();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getAmp();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getPower();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getJack();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpkfault();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getVcc();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getGnd();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional LED greenLED = 1;\n * @return {?proto.sys.LED}\n */\nproto.sys.Gpios.prototype.getGreenled = function() {\n return /** @type{?proto.sys.LED} */ (\n jspb.Message.getWrapperField(this, proto.sys.LED, 1));\n};\n\n\n/**\n * @param {?proto.sys.LED|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setGreenled = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearGreenled = function() {\n return this.setGreenled(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasGreenled = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional LED redLED = 2;\n * @return {?proto.sys.LED}\n */\nproto.sys.Gpios.prototype.getRedled = function() {\n return /** @type{?proto.sys.LED} */ (\n jspb.Message.getWrapperField(this, proto.sys.LED, 2));\n};\n\n\n/**\n * @param {?proto.sys.LED|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setRedled = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearRedled = function() {\n return this.setRedled(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasRedled = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO audioJack = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getAudiojack = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setAudiojack = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearAudiojack = function() {\n return this.setAudiojack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasAudiojack = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO amp = 4;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getAmp = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setAmp = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearAmp = function() {\n return this.setAmp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasAmp = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional GPIO power = 5;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getPower = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 5));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setPower = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearPower = function() {\n return this.setPower(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasPower = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional GPIO jack = 6;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getJack = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 6));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setJack = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearJack = function() {\n return this.setJack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasJack = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional GPIO spkfault = 7;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getSpkfault = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setSpkfault = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearSpkfault = function() {\n return this.setSpkfault(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasSpkfault = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional GPIO Vcc = 8;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getVcc = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 8));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setVcc = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearVcc = function() {\n return this.setVcc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasVcc = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional GPIO GND = 9;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.Gpios.prototype.getGnd = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 9));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.Gpios} returns this\n*/\nproto.sys.Gpios.prototype.setGnd = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Gpios} returns this\n */\nproto.sys.Gpios.prototype.clearGnd = function() {\n return this.setGnd(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Gpios.prototype.hasGnd = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.GPIOExpI2C.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.GPIOExpI2C.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.GPIOExpI2C} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExpI2C.toObject = function(includeInstance, msg) {\n var f, obj = {\n port: jspb.Message.getFieldWithDefault(msg, 5, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.GPIOExpI2C}\n */\nproto.sys.GPIOExpI2C.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.GPIOExpI2C;\n return proto.sys.GPIOExpI2C.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.GPIOExpI2C} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.GPIOExpI2C}\n */\nproto.sys.GPIOExpI2C.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 5:\n var value = /** @type {!proto.sys.PortEnum} */ (reader.readEnum());\n msg.setPort(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.GPIOExpI2C.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.GPIOExpI2C.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.GPIOExpI2C} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExpI2C.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPort();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n};\n\n\n/**\n * optional PortEnum port = 5;\n * @return {!proto.sys.PortEnum}\n */\nproto.sys.GPIOExpI2C.prototype.getPort = function() {\n return /** @type {!proto.sys.PortEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.sys.PortEnum} value\n * @return {!proto.sys.GPIOExpI2C} returns this\n */\nproto.sys.GPIOExpI2C.prototype.setPort = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.GPIOExpSPI.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.GPIOExpSPI.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.GPIOExpSPI} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExpSPI.toObject = function(includeInstance, msg) {\n var f, obj = {\n speed: jspb.Message.getFieldWithDefault(msg, 1, 0),\n host: jspb.Message.getFieldWithDefault(msg, 2, 0),\n cs: (f = msg.getCs()) && proto.sys.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.GPIOExpSPI}\n */\nproto.sys.GPIOExpSPI.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.GPIOExpSPI;\n return proto.sys.GPIOExpSPI.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.GPIOExpSPI} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.GPIOExpSPI}\n */\nproto.sys.GPIOExpSPI.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 2:\n var value = /** @type {!proto.sys.HostEnum} */ (reader.readEnum());\n msg.setHost(value);\n break;\n case 3:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.GPIOExpSPI.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.GPIOExpSPI.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.GPIOExpSPI} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExpSPI.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getHost();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional int32 speed = 1;\n * @return {number}\n */\nproto.sys.GPIOExpSPI.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GPIOExpSPI} returns this\n */\nproto.sys.GPIOExpSPI.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional HostEnum host = 2;\n * @return {!proto.sys.HostEnum}\n */\nproto.sys.GPIOExpSPI.prototype.getHost = function() {\n return /** @type {!proto.sys.HostEnum} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.sys.HostEnum} value\n * @return {!proto.sys.GPIOExpSPI} returns this\n */\nproto.sys.GPIOExpSPI.prototype.setHost = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n/**\n * optional GPIO cs = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.GPIOExpSPI.prototype.getCs = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.GPIOExpSPI} returns this\n*/\nproto.sys.GPIOExpSPI.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.GPIOExpSPI} returns this\n */\nproto.sys.GPIOExpSPI.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.GPIOExpSPI.prototype.hasCs = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.sys.GPIOExp.oneofGroups_ = [[3,4]];\n\n/**\n * @enum {number}\n */\nproto.sys.GPIOExp.ExptypeCase = {\n EXPTYPE_NOT_SET: 0,\n I2C: 3,\n SPI: 4\n};\n\n/**\n * @return {proto.sys.GPIOExp.ExptypeCase}\n */\nproto.sys.GPIOExp.prototype.getExptypeCase = function() {\n return /** @type {proto.sys.GPIOExp.ExptypeCase} */(jspb.Message.computeOneofCase(this, proto.sys.GPIOExp.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.GPIOExp.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.GPIOExp.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.GPIOExp} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExp.toObject = function(includeInstance, msg) {\n var f, obj = {\n model: jspb.Message.getFieldWithDefault(msg, 1, 0),\n addr: jspb.Message.getFieldWithDefault(msg, 2, 0),\n i2c: (f = msg.getI2c()) && proto.sys.GPIOExpI2C.toObject(includeInstance, f),\n spi: (f = msg.getSpi()) && proto.sys.GPIOExpSPI.toObject(includeInstance, f),\n base: jspb.Message.getFieldWithDefault(msg, 5, 0),\n count: jspb.Message.getFieldWithDefault(msg, 6, 0),\n intr: (f = msg.getIntr()) && proto.sys.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.GPIOExp}\n */\nproto.sys.GPIOExp.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.GPIOExp;\n return proto.sys.GPIOExp.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.GPIOExp} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.GPIOExp}\n */\nproto.sys.GPIOExp.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.GPIOExpModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setAddr(value);\n break;\n case 3:\n var value = new proto.sys.GPIOExpI2C;\n reader.readMessage(value,proto.sys.GPIOExpI2C.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 4:\n var value = new proto.sys.GPIOExpSPI;\n reader.readMessage(value,proto.sys.GPIOExpSPI.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n case 5:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setBase(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setCount(value);\n break;\n case 7:\n var value = new proto.sys.GPIO;\n reader.readMessage(value,proto.sys.GPIO.deserializeBinaryFromReader);\n msg.setIntr(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.GPIOExp.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.GPIOExp.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.GPIOExp} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.GPIOExp.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getAddr();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.sys.GPIOExpI2C.serializeBinaryToWriter\n );\n }\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.GPIOExpSPI.serializeBinaryToWriter\n );\n }\n f = message.getBase();\n if (f !== 0) {\n writer.writeInt32(\n 5,\n f\n );\n }\n f = message.getCount();\n if (f !== 0) {\n writer.writeInt32(\n 6,\n f\n );\n }\n f = message.getIntr();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.sys.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIOExpModelEnum model = 1;\n * @return {!proto.sys.GPIOExpModelEnum}\n */\nproto.sys.GPIOExp.prototype.getModel = function() {\n return /** @type {!proto.sys.GPIOExpModelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.GPIOExpModelEnum} value\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional int32 addr = 2;\n * @return {number}\n */\nproto.sys.GPIOExp.prototype.getAddr = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.setAddr = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIOExpI2C i2c = 3;\n * @return {?proto.sys.GPIOExpI2C}\n */\nproto.sys.GPIOExp.prototype.getI2c = function() {\n return /** @type{?proto.sys.GPIOExpI2C} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIOExpI2C, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIOExpI2C|undefined} value\n * @return {!proto.sys.GPIOExp} returns this\n*/\nproto.sys.GPIOExp.prototype.setI2c = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.sys.GPIOExp.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.GPIOExp.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIOExpSPI spi = 4;\n * @return {?proto.sys.GPIOExpSPI}\n */\nproto.sys.GPIOExp.prototype.getSpi = function() {\n return /** @type{?proto.sys.GPIOExpSPI} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIOExpSPI, 4));\n};\n\n\n/**\n * @param {?proto.sys.GPIOExpSPI|undefined} value\n * @return {!proto.sys.GPIOExp} returns this\n*/\nproto.sys.GPIOExp.prototype.setSpi = function(value) {\n return jspb.Message.setOneofWrapperField(this, 4, proto.sys.GPIOExp.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.GPIOExp.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional int32 base = 5;\n * @return {number}\n */\nproto.sys.GPIOExp.prototype.getBase = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.setBase = function(value) {\n return jspb.Message.setProto3IntField(this, 5, value);\n};\n\n\n/**\n * optional int32 count = 6;\n * @return {number}\n */\nproto.sys.GPIOExp.prototype.getCount = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.setCount = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional GPIO intr = 7;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.GPIOExp.prototype.getIntr = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.sys.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.GPIOExp} returns this\n*/\nproto.sys.GPIOExp.prototype.setIntr = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.GPIOExp} returns this\n */\nproto.sys.GPIOExp.prototype.clearIntr = function() {\n return this.setIntr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.GPIOExp.prototype.hasIntr = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.LevelsEnum = {\n L_LOW: 0,\n L_HIGH: 1\n};\n\n/**\n * @enum {number}\n */\nproto.sys.LedTypesEnum = {\n UNKNOWN: 0,\n LED_TYPE_GPIO: 1,\n LED_TYPE_WS2812: 2\n};\n\n/**\n * @enum {number}\n */\nproto.sys.GPIOExpModelEnum = {\n UNSPECIFIED_EXP: 0,\n PCA9535: 1,\n PCA85XX: 2,\n MCP23017: 3,\n MCP23S17: 4\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: I2CBus.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.I2CBus', null, global);\ngoog.exportSymbol('proto.sys.I2CPortEnum', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.I2CBus = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.I2CBus, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.I2CBus.displayName = 'proto.sys.I2CBus';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.I2CBus.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.I2CBus.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.I2CBus} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.I2CBus.toObject = function(includeInstance, msg) {\n var f, obj = {\n port: jspb.Message.getFieldWithDefault(msg, 1, 0),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n sda: (f = msg.getSda()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n scl: (f = msg.getScl()) && GPIO_pb.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.I2CBus}\n */\nproto.sys.I2CBus.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.I2CBus;\n return proto.sys.I2CBus.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.I2CBus} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.I2CBus}\n */\nproto.sys.I2CBus.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.I2CPortEnum} */ (reader.readEnum());\n msg.setPort(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setSda(value);\n break;\n case 4:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setScl(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.I2CBus.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.I2CBus.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.I2CBus} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.I2CBus.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPort();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getSda();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getScl();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional I2CPortEnum port = 1;\n * @return {!proto.sys.I2CPortEnum}\n */\nproto.sys.I2CBus.prototype.getPort = function() {\n return /** @type {!proto.sys.I2CPortEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.I2CPortEnum} value\n * @return {!proto.sys.I2CBus} returns this\n */\nproto.sys.I2CBus.prototype.setPort = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional int32 speed = 2;\n * @return {number}\n */\nproto.sys.I2CBus.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.I2CBus} returns this\n */\nproto.sys.I2CBus.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO sda = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.I2CBus.prototype.getSda = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.I2CBus} returns this\n*/\nproto.sys.I2CBus.prototype.setSda = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.I2CBus} returns this\n */\nproto.sys.I2CBus.prototype.clearSda = function() {\n return this.setSda(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.I2CBus.prototype.hasSda = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO scl = 4;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.I2CBus.prototype.getScl = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.I2CBus} returns this\n*/\nproto.sys.I2CBus.prototype.setScl = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.I2CBus} returns this\n */\nproto.sys.I2CBus.prototype.clearScl = function() {\n return this.setScl(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.I2CBus.prototype.hasScl = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.I2CPortEnum = {\n UNSPECIFIED_PORT: 0,\n I2CPORT0: 1,\n I2CPORT1: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Names.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Names', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Names = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Names, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Names.displayName = 'proto.sys.Names';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Names.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Names.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Names} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Names.toObject = function(includeInstance, msg) {\n var f, obj = {\n device: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n airplay: jspb.Message.getFieldWithDefault(msg, 2, \"\"),\n spotify: jspb.Message.getFieldWithDefault(msg, 3, \"\"),\n bluetooth: jspb.Message.getFieldWithDefault(msg, 4, \"\"),\n squeezelite: jspb.Message.getFieldWithDefault(msg, 5, \"\"),\n wifiApName: jspb.Message.getFieldWithDefault(msg, 6, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Names}\n */\nproto.sys.Names.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Names;\n return proto.sys.Names.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Names} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Names}\n */\nproto.sys.Names.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setDevice(value);\n break;\n case 2:\n var value = /** @type {string} */ (reader.readString());\n msg.setAirplay(value);\n break;\n case 3:\n var value = /** @type {string} */ (reader.readString());\n msg.setSpotify(value);\n break;\n case 4:\n var value = /** @type {string} */ (reader.readString());\n msg.setBluetooth(value);\n break;\n case 5:\n var value = /** @type {string} */ (reader.readString());\n msg.setSqueezelite(value);\n break;\n case 6:\n var value = /** @type {string} */ (reader.readString());\n msg.setWifiApName(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Names.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Names.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Names} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Names.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDevice();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getAirplay();\n if (f.length > 0) {\n writer.writeString(\n 2,\n f\n );\n }\n f = message.getSpotify();\n if (f.length > 0) {\n writer.writeString(\n 3,\n f\n );\n }\n f = message.getBluetooth();\n if (f.length > 0) {\n writer.writeString(\n 4,\n f\n );\n }\n f = message.getSqueezelite();\n if (f.length > 0) {\n writer.writeString(\n 5,\n f\n );\n }\n f = message.getWifiApName();\n if (f.length > 0) {\n writer.writeString(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional string device = 1;\n * @return {string}\n */\nproto.sys.Names.prototype.getDevice = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setDevice = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional string airplay = 2;\n * @return {string}\n */\nproto.sys.Names.prototype.getAirplay = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setAirplay = function(value) {\n return jspb.Message.setProto3StringField(this, 2, value);\n};\n\n\n/**\n * optional string spotify = 3;\n * @return {string}\n */\nproto.sys.Names.prototype.getSpotify = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setSpotify = function(value) {\n return jspb.Message.setProto3StringField(this, 3, value);\n};\n\n\n/**\n * optional string bluetooth = 4;\n * @return {string}\n */\nproto.sys.Names.prototype.getBluetooth = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setBluetooth = function(value) {\n return jspb.Message.setProto3StringField(this, 4, value);\n};\n\n\n/**\n * optional string squeezelite = 5;\n * @return {string}\n */\nproto.sys.Names.prototype.getSqueezelite = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setSqueezelite = function(value) {\n return jspb.Message.setProto3StringField(this, 5, value);\n};\n\n\n/**\n * optional string wifi_ap_name = 6;\n * @return {string}\n */\nproto.sys.Names.prototype.getWifiApName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Names} returns this\n */\nproto.sys.Names.prototype.setWifiApName = function(value) {\n return jspb.Message.setProto3StringField(this, 6, value);\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: Network.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js');\ngoog.object.extend(proto, google_protobuf_timestamp_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.IP', null, global);\ngoog.exportSymbol('proto.sys.NetworkConfig', null, global);\ngoog.exportSymbol('proto.sys.NetworkConfig.PowerSaveTypeEnum', null, global);\ngoog.exportSymbol('proto.sys.Server', null, global);\ngoog.exportSymbol('proto.sys.WifiAP', null, global);\ngoog.exportSymbol('proto.sys.WifiAuthTypeEnum', null, global);\ngoog.exportSymbol('proto.sys.WifiRadioTypesEnum', null, global);\ngoog.exportSymbol('proto.sys.WifiSTAEntry', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.IP = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.IP, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.IP.displayName = 'proto.sys.IP';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.WifiSTAEntry = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.WifiSTAEntry, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.WifiSTAEntry.displayName = 'proto.sys.WifiSTAEntry';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.WifiAP = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.WifiAP, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.WifiAP.displayName = 'proto.sys.WifiAP';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Server = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Server, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Server.displayName = 'proto.sys.Server';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.NetworkConfig = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.NetworkConfig.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.NetworkConfig, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.NetworkConfig.displayName = 'proto.sys.NetworkConfig';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.IP.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.IP.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.IP} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.IP.toObject = function(includeInstance, msg) {\n var f, obj = {\n ip: jspb.Message.getFieldWithDefault(msg, 14, \"\"),\n netmask: jspb.Message.getFieldWithDefault(msg, 15, \"\"),\n gw: jspb.Message.getFieldWithDefault(msg, 16, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.IP}\n */\nproto.sys.IP.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.IP;\n return proto.sys.IP.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.IP} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.IP}\n */\nproto.sys.IP.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 14:\n var value = /** @type {string} */ (reader.readString());\n msg.setIp(value);\n break;\n case 15:\n var value = /** @type {string} */ (reader.readString());\n msg.setNetmask(value);\n break;\n case 16:\n var value = /** @type {string} */ (reader.readString());\n msg.setGw(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.IP.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.IP.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.IP} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.IP.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getIp();\n if (f.length > 0) {\n writer.writeString(\n 14,\n f\n );\n }\n f = message.getNetmask();\n if (f.length > 0) {\n writer.writeString(\n 15,\n f\n );\n }\n f = message.getGw();\n if (f.length > 0) {\n writer.writeString(\n 16,\n f\n );\n }\n};\n\n\n/**\n * optional string ip = 14;\n * @return {string}\n */\nproto.sys.IP.prototype.getIp = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 14, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.IP} returns this\n */\nproto.sys.IP.prototype.setIp = function(value) {\n return jspb.Message.setProto3StringField(this, 14, value);\n};\n\n\n/**\n * optional string netmask = 15;\n * @return {string}\n */\nproto.sys.IP.prototype.getNetmask = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 15, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.IP} returns this\n */\nproto.sys.IP.prototype.setNetmask = function(value) {\n return jspb.Message.setProto3StringField(this, 15, value);\n};\n\n\n/**\n * optional string gw = 16;\n * @return {string}\n */\nproto.sys.IP.prototype.getGw = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 16, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.IP} returns this\n */\nproto.sys.IP.prototype.setGw = function(value) {\n return jspb.Message.setProto3StringField(this, 16, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.WifiSTAEntry.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.WifiSTAEntry.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.WifiSTAEntry} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.WifiSTAEntry.toObject = function(includeInstance, msg) {\n var f, obj = {\n ssid: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n bssid: jspb.Message.getFieldWithDefault(msg, 2, \"\"),\n channel: jspb.Message.getFieldWithDefault(msg, 3, 0),\n authType: jspb.Message.getFieldWithDefault(msg, 4, 0),\n radioType: jspb.Message.getFieldWithDefault(msg, 5, 0),\n lastTry: (f = msg.getLastTry()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f),\n lastSeen: (f = msg.getLastSeen()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f),\n connected: jspb.Message.getBooleanFieldWithDefault(msg, 8, false),\n password: jspb.Message.getFieldWithDefault(msg, 9, \"\"),\n rssi: jspb.Message.getFieldWithDefault(msg, 10, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.WifiSTAEntry}\n */\nproto.sys.WifiSTAEntry.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.WifiSTAEntry;\n return proto.sys.WifiSTAEntry.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.WifiSTAEntry} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.WifiSTAEntry}\n */\nproto.sys.WifiSTAEntry.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setSsid(value);\n break;\n case 2:\n var value = /** @type {string} */ (reader.readString());\n msg.setBssid(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setChannel(value);\n break;\n case 4:\n var value = /** @type {!proto.sys.WifiAuthTypeEnum} */ (reader.readEnum());\n msg.setAuthType(value);\n break;\n case 5:\n var value = /** @type {!proto.sys.WifiRadioTypesEnum} */ (reader.readEnum());\n msg.setRadioType(value);\n break;\n case 6:\n var value = new google_protobuf_timestamp_pb.Timestamp;\n reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader);\n msg.setLastTry(value);\n break;\n case 7:\n var value = new google_protobuf_timestamp_pb.Timestamp;\n reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader);\n msg.setLastSeen(value);\n break;\n case 8:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setConnected(value);\n break;\n case 9:\n var value = /** @type {string} */ (reader.readString());\n msg.setPassword(value);\n break;\n case 10:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setRssi(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.WifiSTAEntry.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.WifiSTAEntry.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.WifiSTAEntry} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.WifiSTAEntry.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getSsid();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getBssid();\n if (f.length > 0) {\n writer.writeString(\n 2,\n f\n );\n }\n f = message.getChannel();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n f = message.getAuthType();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n f = message.getRadioType();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n f = message.getLastTry();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter\n );\n }\n f = message.getLastSeen();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter\n );\n }\n f = message.getConnected();\n if (f) {\n writer.writeBool(\n 8,\n f\n );\n }\n f = message.getPassword();\n if (f.length > 0) {\n writer.writeString(\n 9,\n f\n );\n }\n f = message.getRssi();\n if (f !== 0) {\n writer.writeUint32(\n 10,\n f\n );\n }\n};\n\n\n/**\n * optional string ssid = 1;\n * @return {string}\n */\nproto.sys.WifiSTAEntry.prototype.getSsid = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setSsid = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional string bssid = 2;\n * @return {string}\n */\nproto.sys.WifiSTAEntry.prototype.getBssid = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setBssid = function(value) {\n return jspb.Message.setProto3StringField(this, 2, value);\n};\n\n\n/**\n * optional uint32 channel = 3;\n * @return {number}\n */\nproto.sys.WifiSTAEntry.prototype.getChannel = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setChannel = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional WifiAuthTypeEnum auth_type = 4;\n * @return {!proto.sys.WifiAuthTypeEnum}\n */\nproto.sys.WifiSTAEntry.prototype.getAuthType = function() {\n return /** @type {!proto.sys.WifiAuthTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.sys.WifiAuthTypeEnum} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setAuthType = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * optional WifiRadioTypesEnum radio_type = 5;\n * @return {!proto.sys.WifiRadioTypesEnum}\n */\nproto.sys.WifiSTAEntry.prototype.getRadioType = function() {\n return /** @type {!proto.sys.WifiRadioTypesEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.sys.WifiRadioTypesEnum} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setRadioType = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n/**\n * optional google.protobuf.Timestamp last_try = 6;\n * @return {?proto.google.protobuf.Timestamp}\n */\nproto.sys.WifiSTAEntry.prototype.getLastTry = function() {\n return /** @type{?proto.google.protobuf.Timestamp} */ (\n jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 6));\n};\n\n\n/**\n * @param {?proto.google.protobuf.Timestamp|undefined} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n*/\nproto.sys.WifiSTAEntry.prototype.setLastTry = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.clearLastTry = function() {\n return this.setLastTry(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.WifiSTAEntry.prototype.hasLastTry = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional google.protobuf.Timestamp last_seen = 7;\n * @return {?proto.google.protobuf.Timestamp}\n */\nproto.sys.WifiSTAEntry.prototype.getLastSeen = function() {\n return /** @type{?proto.google.protobuf.Timestamp} */ (\n jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 7));\n};\n\n\n/**\n * @param {?proto.google.protobuf.Timestamp|undefined} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n*/\nproto.sys.WifiSTAEntry.prototype.setLastSeen = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.clearLastSeen = function() {\n return this.setLastSeen(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.WifiSTAEntry.prototype.hasLastSeen = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional bool connected = 8;\n * @return {boolean}\n */\nproto.sys.WifiSTAEntry.prototype.getConnected = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 8, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setConnected = function(value) {\n return jspb.Message.setProto3BooleanField(this, 8, value);\n};\n\n\n/**\n * optional string password = 9;\n * @return {string}\n */\nproto.sys.WifiSTAEntry.prototype.getPassword = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setPassword = function(value) {\n return jspb.Message.setProto3StringField(this, 9, value);\n};\n\n\n/**\n * optional uint32 rssi = 10;\n * @return {number}\n */\nproto.sys.WifiSTAEntry.prototype.getRssi = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.WifiSTAEntry} returns this\n */\nproto.sys.WifiSTAEntry.prototype.setRssi = function(value) {\n return jspb.Message.setProto3IntField(this, 10, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.WifiAP.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.WifiAP.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.WifiAP} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.WifiAP.toObject = function(includeInstance, msg) {\n var f, obj = {\n ip: (f = msg.getIp()) && proto.sys.IP.toObject(includeInstance, f),\n password: jspb.Message.getFieldWithDefault(msg, 2, \"\"),\n channel: jspb.Message.getFieldWithDefault(msg, 3, 0),\n authMode: jspb.Message.getFieldWithDefault(msg, 4, 0),\n hidden: jspb.Message.getBooleanFieldWithDefault(msg, 5, false),\n maxConnection: jspb.Message.getFieldWithDefault(msg, 6, 0),\n beaconInterval: jspb.Message.getFieldWithDefault(msg, 7, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.WifiAP}\n */\nproto.sys.WifiAP.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.WifiAP;\n return proto.sys.WifiAP.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.WifiAP} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.WifiAP}\n */\nproto.sys.WifiAP.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.IP;\n reader.readMessage(value,proto.sys.IP.deserializeBinaryFromReader);\n msg.setIp(value);\n break;\n case 2:\n var value = /** @type {string} */ (reader.readString());\n msg.setPassword(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setChannel(value);\n break;\n case 4:\n var value = /** @type {!proto.sys.WifiAuthTypeEnum} */ (reader.readEnum());\n msg.setAuthMode(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setHidden(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxConnection(value);\n break;\n case 7:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setBeaconInterval(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.WifiAP.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.WifiAP.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.WifiAP} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.WifiAP.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getIp();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.IP.serializeBinaryToWriter\n );\n }\n f = message.getPassword();\n if (f.length > 0) {\n writer.writeString(\n 2,\n f\n );\n }\n f = message.getChannel();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n f = message.getAuthMode();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n f = message.getHidden();\n if (f) {\n writer.writeBool(\n 5,\n f\n );\n }\n f = message.getMaxConnection();\n if (f !== 0) {\n writer.writeUint32(\n 6,\n f\n );\n }\n f = message.getBeaconInterval();\n if (f !== 0) {\n writer.writeUint32(\n 7,\n f\n );\n }\n};\n\n\n/**\n * optional IP ip = 1;\n * @return {?proto.sys.IP}\n */\nproto.sys.WifiAP.prototype.getIp = function() {\n return /** @type{?proto.sys.IP} */ (\n jspb.Message.getWrapperField(this, proto.sys.IP, 1));\n};\n\n\n/**\n * @param {?proto.sys.IP|undefined} value\n * @return {!proto.sys.WifiAP} returns this\n*/\nproto.sys.WifiAP.prototype.setIp = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.clearIp = function() {\n return this.setIp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.WifiAP.prototype.hasIp = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional string password = 2;\n * @return {string}\n */\nproto.sys.WifiAP.prototype.getPassword = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setPassword = function(value) {\n return jspb.Message.setProto3StringField(this, 2, value);\n};\n\n\n/**\n * optional uint32 channel = 3;\n * @return {number}\n */\nproto.sys.WifiAP.prototype.getChannel = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setChannel = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional WifiAuthTypeEnum auth_mode = 4;\n * @return {!proto.sys.WifiAuthTypeEnum}\n */\nproto.sys.WifiAP.prototype.getAuthMode = function() {\n return /** @type {!proto.sys.WifiAuthTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.sys.WifiAuthTypeEnum} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setAuthMode = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * optional bool hidden = 5;\n * @return {boolean}\n */\nproto.sys.WifiAP.prototype.getHidden = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setHidden = function(value) {\n return jspb.Message.setProto3BooleanField(this, 5, value);\n};\n\n\n/**\n * optional uint32 max_connection = 6;\n * @return {number}\n */\nproto.sys.WifiAP.prototype.getMaxConnection = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setMaxConnection = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional uint32 beacon_interval = 7;\n * @return {number}\n */\nproto.sys.WifiAP.prototype.getBeaconInterval = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.WifiAP} returns this\n */\nproto.sys.WifiAP.prototype.setBeaconInterval = function(value) {\n return jspb.Message.setProto3IntField(this, 7, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Server.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Server.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Server} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Server.toObject = function(includeInstance, msg) {\n var f, obj = {\n cport: jspb.Message.getFieldWithDefault(msg, 1, 0),\n port: jspb.Message.getFieldWithDefault(msg, 2, 0),\n ip: jspb.Message.getFieldWithDefault(msg, 3, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Server}\n */\nproto.sys.Server.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Server;\n return proto.sys.Server.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Server} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Server}\n */\nproto.sys.Server.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setCport(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setPort(value);\n break;\n case 3:\n var value = /** @type {string} */ (reader.readString());\n msg.setIp(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Server.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Server.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Server} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Server.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCport();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getPort();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getIp();\n if (f.length > 0) {\n writer.writeString(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional int32 cport = 1;\n * @return {number}\n */\nproto.sys.Server.prototype.getCport = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Server} returns this\n */\nproto.sys.Server.prototype.setCport = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 port = 2;\n * @return {number}\n */\nproto.sys.Server.prototype.getPort = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Server} returns this\n */\nproto.sys.Server.prototype.setPort = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional string ip = 3;\n * @return {string}\n */\nproto.sys.Server.prototype.getIp = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Server} returns this\n */\nproto.sys.Server.prototype.setIp = function(value) {\n return jspb.Message.setProto3StringField(this, 3, value);\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.NetworkConfig.repeatedFields_ = [3];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.NetworkConfig.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.NetworkConfig.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.NetworkConfig} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.NetworkConfig.toObject = function(includeInstance, msg) {\n var f, obj = {\n disableDhcp: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n manualIp: (f = msg.getManualIp()) && proto.sys.IP.toObject(includeInstance, f),\n credentialsList: jspb.Message.toObjectList(msg.getCredentialsList(),\n proto.sys.WifiSTAEntry.toObject, includeInstance),\n ap: (f = msg.getAp()) && proto.sys.WifiAP.toObject(includeInstance, f),\n staPollingMaxS: jspb.Message.getFieldWithDefault(msg, 5, 0),\n apDurationS: jspb.Message.getFieldWithDefault(msg, 6, 0),\n staPollingMinS: jspb.Message.getFieldWithDefault(msg, 7, 0),\n dhcpTmoutS: jspb.Message.getFieldWithDefault(msg, 8, 0),\n ethBoot: jspb.Message.getBooleanFieldWithDefault(msg, 9, false),\n maxWifiRetry: jspb.Message.getFieldWithDefault(msg, 10, 0),\n maxApNum: jspb.Message.getFieldWithDefault(msg, 11, 0),\n maxSsidSize: jspb.Message.getFieldWithDefault(msg, 12, 0),\n maxPasswordSize: jspb.Message.getFieldWithDefault(msg, 13, 0),\n taskPriority: jspb.Message.getFieldWithDefault(msg, 14, 0),\n powerSaveMode: jspb.Message.getFieldWithDefault(msg, 15, 0),\n maxInitialWifiAttempt: jspb.Message.getFieldWithDefault(msg, 16, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.NetworkConfig}\n */\nproto.sys.NetworkConfig.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.NetworkConfig;\n return proto.sys.NetworkConfig.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.NetworkConfig} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.NetworkConfig}\n */\nproto.sys.NetworkConfig.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setDisableDhcp(value);\n break;\n case 2:\n var value = new proto.sys.IP;\n reader.readMessage(value,proto.sys.IP.deserializeBinaryFromReader);\n msg.setManualIp(value);\n break;\n case 3:\n var value = new proto.sys.WifiSTAEntry;\n reader.readMessage(value,proto.sys.WifiSTAEntry.deserializeBinaryFromReader);\n msg.addCredentials(value);\n break;\n case 4:\n var value = new proto.sys.WifiAP;\n reader.readMessage(value,proto.sys.WifiAP.deserializeBinaryFromReader);\n msg.setAp(value);\n break;\n case 5:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setStaPollingMaxS(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setApDurationS(value);\n break;\n case 7:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setStaPollingMinS(value);\n break;\n case 8:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setDhcpTmoutS(value);\n break;\n case 9:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEthBoot(value);\n break;\n case 10:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxWifiRetry(value);\n break;\n case 11:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxApNum(value);\n break;\n case 12:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxSsidSize(value);\n break;\n case 13:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxPasswordSize(value);\n break;\n case 14:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setTaskPriority(value);\n break;\n case 15:\n var value = /** @type {!proto.sys.NetworkConfig.PowerSaveTypeEnum} */ (reader.readEnum());\n msg.setPowerSaveMode(value);\n break;\n case 16:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxInitialWifiAttempt(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.NetworkConfig.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.NetworkConfig.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.NetworkConfig} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.NetworkConfig.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDisableDhcp();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getManualIp();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.IP.serializeBinaryToWriter\n );\n }\n f = message.getCredentialsList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 3,\n f,\n proto.sys.WifiSTAEntry.serializeBinaryToWriter\n );\n }\n f = message.getAp();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.sys.WifiAP.serializeBinaryToWriter\n );\n }\n f = message.getStaPollingMaxS();\n if (f !== 0) {\n writer.writeUint32(\n 5,\n f\n );\n }\n f = message.getApDurationS();\n if (f !== 0) {\n writer.writeUint32(\n 6,\n f\n );\n }\n f = message.getStaPollingMinS();\n if (f !== 0) {\n writer.writeUint32(\n 7,\n f\n );\n }\n f = message.getDhcpTmoutS();\n if (f !== 0) {\n writer.writeUint32(\n 8,\n f\n );\n }\n f = message.getEthBoot();\n if (f) {\n writer.writeBool(\n 9,\n f\n );\n }\n f = message.getMaxWifiRetry();\n if (f !== 0) {\n writer.writeUint32(\n 10,\n f\n );\n }\n f = message.getMaxApNum();\n if (f !== 0) {\n writer.writeUint32(\n 11,\n f\n );\n }\n f = message.getMaxSsidSize();\n if (f !== 0) {\n writer.writeUint32(\n 12,\n f\n );\n }\n f = message.getMaxPasswordSize();\n if (f !== 0) {\n writer.writeUint32(\n 13,\n f\n );\n }\n f = message.getTaskPriority();\n if (f !== 0) {\n writer.writeUint32(\n 14,\n f\n );\n }\n f = message.getPowerSaveMode();\n if (f !== 0.0) {\n writer.writeEnum(\n 15,\n f\n );\n }\n f = message.getMaxInitialWifiAttempt();\n if (f !== 0) {\n writer.writeUint32(\n 16,\n f\n );\n }\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.NetworkConfig.PowerSaveTypeEnum = {\n WIFI_PS_NONE: 0,\n WIFI_PS_MIN_MODEM: 1,\n WIFI_PS_MAX_MODEM: 2\n};\n\n/**\n * optional bool disable_dhcp = 1;\n * @return {boolean}\n */\nproto.sys.NetworkConfig.prototype.getDisableDhcp = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setDisableDhcp = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional IP manual_ip = 2;\n * @return {?proto.sys.IP}\n */\nproto.sys.NetworkConfig.prototype.getManualIp = function() {\n return /** @type{?proto.sys.IP} */ (\n jspb.Message.getWrapperField(this, proto.sys.IP, 2));\n};\n\n\n/**\n * @param {?proto.sys.IP|undefined} value\n * @return {!proto.sys.NetworkConfig} returns this\n*/\nproto.sys.NetworkConfig.prototype.setManualIp = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.clearManualIp = function() {\n return this.setManualIp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.NetworkConfig.prototype.hasManualIp = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * repeated WifiSTAEntry credentials = 3;\n * @return {!Array}\n */\nproto.sys.NetworkConfig.prototype.getCredentialsList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.sys.WifiSTAEntry, 3));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.NetworkConfig} returns this\n*/\nproto.sys.NetworkConfig.prototype.setCredentialsList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 3, value);\n};\n\n\n/**\n * @param {!proto.sys.WifiSTAEntry=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.WifiSTAEntry}\n */\nproto.sys.NetworkConfig.prototype.addCredentials = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.sys.WifiSTAEntry, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.clearCredentialsList = function() {\n return this.setCredentialsList([]);\n};\n\n\n/**\n * optional WifiAP ap = 4;\n * @return {?proto.sys.WifiAP}\n */\nproto.sys.NetworkConfig.prototype.getAp = function() {\n return /** @type{?proto.sys.WifiAP} */ (\n jspb.Message.getWrapperField(this, proto.sys.WifiAP, 4));\n};\n\n\n/**\n * @param {?proto.sys.WifiAP|undefined} value\n * @return {!proto.sys.NetworkConfig} returns this\n*/\nproto.sys.NetworkConfig.prototype.setAp = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.clearAp = function() {\n return this.setAp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.NetworkConfig.prototype.hasAp = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional uint32 sta_polling_max_s = 5;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getStaPollingMaxS = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setStaPollingMaxS = function(value) {\n return jspb.Message.setProto3IntField(this, 5, value);\n};\n\n\n/**\n * optional uint32 ap_duration_s = 6;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getApDurationS = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setApDurationS = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional uint32 sta_polling_min_s = 7;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getStaPollingMinS = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setStaPollingMinS = function(value) {\n return jspb.Message.setProto3IntField(this, 7, value);\n};\n\n\n/**\n * optional uint32 dhcp_tmout_s = 8;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getDhcpTmoutS = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setDhcpTmoutS = function(value) {\n return jspb.Message.setProto3IntField(this, 8, value);\n};\n\n\n/**\n * optional bool eth_boot = 9;\n * @return {boolean}\n */\nproto.sys.NetworkConfig.prototype.getEthBoot = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setEthBoot = function(value) {\n return jspb.Message.setProto3BooleanField(this, 9, value);\n};\n\n\n/**\n * optional uint32 max_wifi_retry = 10;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getMaxWifiRetry = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setMaxWifiRetry = function(value) {\n return jspb.Message.setProto3IntField(this, 10, value);\n};\n\n\n/**\n * optional uint32 max_ap_num = 11;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getMaxApNum = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 11, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setMaxApNum = function(value) {\n return jspb.Message.setProto3IntField(this, 11, value);\n};\n\n\n/**\n * optional uint32 max_ssid_size = 12;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getMaxSsidSize = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 12, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setMaxSsidSize = function(value) {\n return jspb.Message.setProto3IntField(this, 12, value);\n};\n\n\n/**\n * optional uint32 max_password_size = 13;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getMaxPasswordSize = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 13, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setMaxPasswordSize = function(value) {\n return jspb.Message.setProto3IntField(this, 13, value);\n};\n\n\n/**\n * optional uint32 task_priority = 14;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getTaskPriority = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setTaskPriority = function(value) {\n return jspb.Message.setProto3IntField(this, 14, value);\n};\n\n\n/**\n * optional PowerSaveTypeEnum power_save_mode = 15;\n * @return {!proto.sys.NetworkConfig.PowerSaveTypeEnum}\n */\nproto.sys.NetworkConfig.prototype.getPowerSaveMode = function() {\n return /** @type {!proto.sys.NetworkConfig.PowerSaveTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 15, 0));\n};\n\n\n/**\n * @param {!proto.sys.NetworkConfig.PowerSaveTypeEnum} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setPowerSaveMode = function(value) {\n return jspb.Message.setProto3EnumField(this, 15, value);\n};\n\n\n/**\n * optional uint32 max_initial_wifi_attempt = 16;\n * @return {number}\n */\nproto.sys.NetworkConfig.prototype.getMaxInitialWifiAttempt = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 16, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.NetworkConfig} returns this\n */\nproto.sys.NetworkConfig.prototype.setMaxInitialWifiAttempt = function(value) {\n return jspb.Message.setProto3IntField(this, 16, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.WifiAuthTypeEnum = {\n AUTH_UNKNOWN: 0,\n AUTH_OPEN: 1,\n AUTH_WEP: 2,\n AUTH_WPA_PSK: 3,\n AUTH_WPA2_PSK: 4,\n AUTH_WPA_WPA2_PSK: 5,\n AUTH_WPA2_ENTERPRISE: 6,\n AUTH_WPA3_PSK: 7,\n AUTH_WPA2_WPA3_PSK: 8,\n AUTH_WAPI_PSK: 9\n};\n\n/**\n * @enum {number}\n */\nproto.sys.WifiRadioTypesEnum = {\n PHY_UNKNOWN: 0,\n PHY_11B: 1,\n PHY_11G: 2,\n PHY_11N: 3,\n PHY_LR: 4,\n PHY_WPS: 5,\n PHY_FTM_RESPONDER: 6,\n PHY_FTM_INITIATOR: 7\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Services.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar Artwork_pb = require('./Artwork_pb.js');\ngoog.object.extend(proto, Artwork_pb);\nvar Spotify_pb = require('./Spotify_pb.js');\ngoog.object.extend(proto, Spotify_pb);\nvar AirPlay_pb = require('./AirPlay_pb.js');\ngoog.object.extend(proto, AirPlay_pb);\nvar Squeezelite_pb = require('./Squeezelite_pb.js');\ngoog.object.extend(proto, Squeezelite_pb);\nvar Equalizer_pb = require('./Equalizer_pb.js');\ngoog.object.extend(proto, Equalizer_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\ngoog.exportSymbol('proto.sys.BluetoothSink', null, global);\ngoog.exportSymbol('proto.sys.Metadata', null, global);\ngoog.exportSymbol('proto.sys.Services', null, global);\ngoog.exportSymbol('proto.sys.SleepService', null, global);\ngoog.exportSymbol('proto.sys.Telnet', null, global);\ngoog.exportSymbol('proto.sys.TelnetEnableEnum', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.SleepService = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.SleepService.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.SleepService, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.SleepService.displayName = 'proto.sys.SleepService';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Telnet = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Telnet, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Telnet.displayName = 'proto.sys.Telnet';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Metadata = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Metadata, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Metadata.displayName = 'proto.sys.Metadata';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.BluetoothSink = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.BluetoothSink, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.BluetoothSink.displayName = 'proto.sys.BluetoothSink';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Services = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.Services.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.Services, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Services.displayName = 'proto.sys.Services';\n}\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.SleepService.repeatedFields_ = [4,5];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.SleepService.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.SleepService.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.SleepService} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SleepService.toObject = function(includeInstance, msg) {\n var f, obj = {\n delay: jspb.Message.getFieldWithDefault(msg, 1, 0),\n spurious: jspb.Message.getFieldWithDefault(msg, 2, 0),\n sleep: (f = msg.getSleep()) && GPIO_pb.GPIO.toObject(includeInstance, f),\n wakeList: jspb.Message.toObjectList(msg.getWakeList(),\n GPIO_pb.GPIO.toObject, includeInstance),\n rtcList: jspb.Message.toObjectList(msg.getRtcList(),\n GPIO_pb.GPIO.toObject, includeInstance),\n batt: jspb.Message.getFloatingPointFieldWithDefault(msg, 6, 0.0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.SleepService}\n */\nproto.sys.SleepService.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.SleepService;\n return proto.sys.SleepService.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.SleepService} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.SleepService}\n */\nproto.sys.SleepService.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setDelay(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpurious(value);\n break;\n case 3:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.setSleep(value);\n break;\n case 4:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.addWake(value);\n break;\n case 5:\n var value = new GPIO_pb.GPIO;\n reader.readMessage(value,GPIO_pb.GPIO.deserializeBinaryFromReader);\n msg.addRtc(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setBatt(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.SleepService.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.SleepService.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.SleepService} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SleepService.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDelay();\n if (f !== 0) {\n writer.writeUint32(\n 1,\n f\n );\n }\n f = message.getSpurious();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getSleep();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getWakeList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 4,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getRtcList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 5,\n f,\n GPIO_pb.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getBatt();\n if (f !== 0.0) {\n writer.writeFloat(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional uint32 delay = 1;\n * @return {number}\n */\nproto.sys.SleepService.prototype.getDelay = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.setDelay = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 spurious = 2;\n * @return {number}\n */\nproto.sys.SleepService.prototype.getSpurious = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.setSpurious = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO sleep = 3;\n * @return {?proto.sys.GPIO}\n */\nproto.sys.SleepService.prototype.getSleep = function() {\n return /** @type{?proto.sys.GPIO} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.sys.GPIO|undefined} value\n * @return {!proto.sys.SleepService} returns this\n*/\nproto.sys.SleepService.prototype.setSleep = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.clearSleep = function() {\n return this.setSleep(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SleepService.prototype.hasSleep = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * repeated GPIO wake = 4;\n * @return {!Array}\n */\nproto.sys.SleepService.prototype.getWakeList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, GPIO_pb.GPIO, 4));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.SleepService} returns this\n*/\nproto.sys.SleepService.prototype.setWakeList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 4, value);\n};\n\n\n/**\n * @param {!proto.sys.GPIO=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.GPIO}\n */\nproto.sys.SleepService.prototype.addWake = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 4, opt_value, proto.sys.GPIO, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.clearWakeList = function() {\n return this.setWakeList([]);\n};\n\n\n/**\n * repeated GPIO rtc = 5;\n * @return {!Array}\n */\nproto.sys.SleepService.prototype.getRtcList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, GPIO_pb.GPIO, 5));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.SleepService} returns this\n*/\nproto.sys.SleepService.prototype.setRtcList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 5, value);\n};\n\n\n/**\n * @param {!proto.sys.GPIO=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.GPIO}\n */\nproto.sys.SleepService.prototype.addRtc = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 5, opt_value, proto.sys.GPIO, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.clearRtcList = function() {\n return this.setRtcList([]);\n};\n\n\n/**\n * optional float batt = 6;\n * @return {number}\n */\nproto.sys.SleepService.prototype.getBatt = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 6, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.SleepService} returns this\n */\nproto.sys.SleepService.prototype.setBatt = function(value) {\n return jspb.Message.setProto3FloatField(this, 6, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Telnet.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Telnet.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Telnet} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Telnet.toObject = function(includeInstance, msg) {\n var f, obj = {\n enable: jspb.Message.getFieldWithDefault(msg, 1, 0),\n block: jspb.Message.getFieldWithDefault(msg, 2, 0),\n buffer: jspb.Message.getFieldWithDefault(msg, 3, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Telnet}\n */\nproto.sys.Telnet.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Telnet;\n return proto.sys.Telnet.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Telnet} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Telnet}\n */\nproto.sys.Telnet.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.TelnetEnableEnum} */ (reader.readEnum());\n msg.setEnable(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setBlock(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setBuffer(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Telnet.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Telnet.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Telnet} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Telnet.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnable();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getBlock();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n f = message.getBuffer();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional TelnetEnableEnum enable = 1;\n * @return {!proto.sys.TelnetEnableEnum}\n */\nproto.sys.Telnet.prototype.getEnable = function() {\n return /** @type {!proto.sys.TelnetEnableEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.TelnetEnableEnum} value\n * @return {!proto.sys.Telnet} returns this\n */\nproto.sys.Telnet.prototype.setEnable = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional uint32 block = 2;\n * @return {number}\n */\nproto.sys.Telnet.prototype.getBlock = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Telnet} returns this\n */\nproto.sys.Telnet.prototype.setBlock = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional uint32 buffer = 3;\n * @return {number}\n */\nproto.sys.Telnet.prototype.getBuffer = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Telnet} returns this\n */\nproto.sys.Telnet.prototype.setBuffer = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Metadata.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Metadata.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Metadata} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Metadata.toObject = function(includeInstance, msg) {\n var f, obj = {\n format: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n pause: jspb.Message.getFieldWithDefault(msg, 3, 0),\n artwork: (f = msg.getArtwork()) && Artwork_pb.Artwork.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Metadata}\n */\nproto.sys.Metadata.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Metadata;\n return proto.sys.Metadata.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Metadata} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Metadata}\n */\nproto.sys.Metadata.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setFormat(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setPause(value);\n break;\n case 4:\n var value = new Artwork_pb.Artwork;\n reader.readMessage(value,Artwork_pb.Artwork.deserializeBinaryFromReader);\n msg.setArtwork(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Metadata.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Metadata.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Metadata} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Metadata.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getFormat();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n f = message.getPause();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n f = message.getArtwork();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n Artwork_pb.Artwork.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional string format = 1;\n * @return {string}\n */\nproto.sys.Metadata.prototype.getFormat = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Metadata} returns this\n */\nproto.sys.Metadata.prototype.setFormat = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional uint32 speed = 2;\n * @return {number}\n */\nproto.sys.Metadata.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Metadata} returns this\n */\nproto.sys.Metadata.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional uint32 pause = 3;\n * @return {number}\n */\nproto.sys.Metadata.prototype.getPause = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Metadata} returns this\n */\nproto.sys.Metadata.prototype.setPause = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional Artwork artwork = 4;\n * @return {?proto.sys.Artwork}\n */\nproto.sys.Metadata.prototype.getArtwork = function() {\n return /** @type{?proto.sys.Artwork} */ (\n jspb.Message.getWrapperField(this, Artwork_pb.Artwork, 4));\n};\n\n\n/**\n * @param {?proto.sys.Artwork|undefined} value\n * @return {!proto.sys.Metadata} returns this\n*/\nproto.sys.Metadata.prototype.setArtwork = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Metadata} returns this\n */\nproto.sys.Metadata.prototype.clearArtwork = function() {\n return this.setArtwork(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Metadata.prototype.hasArtwork = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.BluetoothSink.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.BluetoothSink.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.BluetoothSink} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.BluetoothSink.toObject = function(includeInstance, msg) {\n var f, obj = {\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n volume: jspb.Message.getFieldWithDefault(msg, 2, 0),\n pin: jspb.Message.getFieldWithDefault(msg, 3, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.BluetoothSink}\n */\nproto.sys.BluetoothSink.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.BluetoothSink;\n return proto.sys.BluetoothSink.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.BluetoothSink} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.BluetoothSink}\n */\nproto.sys.BluetoothSink.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setVolume(value);\n break;\n case 3:\n var value = /** @type {string} */ (reader.readString());\n msg.setPin(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.BluetoothSink.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.BluetoothSink.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.BluetoothSink} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.BluetoothSink.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getVolume();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n f = message.getPin();\n if (f.length > 0) {\n writer.writeString(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional bool enabled = 1;\n * @return {boolean}\n */\nproto.sys.BluetoothSink.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.BluetoothSink} returns this\n */\nproto.sys.BluetoothSink.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional uint32 volume = 2;\n * @return {number}\n */\nproto.sys.BluetoothSink.prototype.getVolume = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.BluetoothSink} returns this\n */\nproto.sys.BluetoothSink.prototype.setVolume = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional string pin = 3;\n * @return {string}\n */\nproto.sys.BluetoothSink.prototype.getPin = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.BluetoothSink} returns this\n */\nproto.sys.BluetoothSink.prototype.setPin = function(value) {\n return jspb.Message.setProto3StringField(this, 3, value);\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.Services.repeatedFields_ = [6];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Services.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Services.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Services} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Services.toObject = function(includeInstance, msg) {\n var f, obj = {\n metadata: (f = msg.getMetadata()) && proto.sys.Metadata.toObject(includeInstance, f),\n sleep: (f = msg.getSleep()) && proto.sys.SleepService.toObject(includeInstance, f),\n cspot: (f = msg.getCspot()) && Spotify_pb.Spotify.toObject(includeInstance, f),\n airplay: (f = msg.getAirplay()) && AirPlay_pb.AirPlay.toObject(includeInstance, f),\n squeezeliteProfilesList: jspb.Message.toObjectList(msg.getSqueezeliteProfilesList(),\n Squeezelite_pb.SqueezeliteProfile.toObject, includeInstance),\n releaseUrl: jspb.Message.getFieldWithDefault(msg, 7, \"\"),\n btSink: (f = msg.getBtSink()) && proto.sys.BluetoothSink.toObject(includeInstance, f),\n statistics: jspb.Message.getBooleanFieldWithDefault(msg, 9, false),\n telnet: (f = msg.getTelnet()) && proto.sys.Telnet.toObject(includeInstance, f),\n equalizer: (f = msg.getEqualizer()) && Equalizer_pb.Equalizer.toObject(includeInstance, f),\n currentProfile: jspb.Message.getFieldWithDefault(msg, 12, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Services}\n */\nproto.sys.Services.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Services;\n return proto.sys.Services.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Services} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Services}\n */\nproto.sys.Services.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.sys.Metadata;\n reader.readMessage(value,proto.sys.Metadata.deserializeBinaryFromReader);\n msg.setMetadata(value);\n break;\n case 2:\n var value = new proto.sys.SleepService;\n reader.readMessage(value,proto.sys.SleepService.deserializeBinaryFromReader);\n msg.setSleep(value);\n break;\n case 4:\n var value = new Spotify_pb.Spotify;\n reader.readMessage(value,Spotify_pb.Spotify.deserializeBinaryFromReader);\n msg.setCspot(value);\n break;\n case 5:\n var value = new AirPlay_pb.AirPlay;\n reader.readMessage(value,AirPlay_pb.AirPlay.deserializeBinaryFromReader);\n msg.setAirplay(value);\n break;\n case 6:\n var value = new Squeezelite_pb.SqueezeliteProfile;\n reader.readMessage(value,Squeezelite_pb.SqueezeliteProfile.deserializeBinaryFromReader);\n msg.addSqueezeliteProfiles(value);\n break;\n case 7:\n var value = /** @type {string} */ (reader.readString());\n msg.setReleaseUrl(value);\n break;\n case 8:\n var value = new proto.sys.BluetoothSink;\n reader.readMessage(value,proto.sys.BluetoothSink.deserializeBinaryFromReader);\n msg.setBtSink(value);\n break;\n case 9:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setStatistics(value);\n break;\n case 10:\n var value = new proto.sys.Telnet;\n reader.readMessage(value,proto.sys.Telnet.deserializeBinaryFromReader);\n msg.setTelnet(value);\n break;\n case 11:\n var value = new Equalizer_pb.Equalizer;\n reader.readMessage(value,Equalizer_pb.Equalizer.deserializeBinaryFromReader);\n msg.setEqualizer(value);\n break;\n case 12:\n var value = /** @type {string} */ (reader.readString());\n msg.setCurrentProfile(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Services.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Services.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Services} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Services.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMetadata();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.sys.Metadata.serializeBinaryToWriter\n );\n }\n f = message.getSleep();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.SleepService.serializeBinaryToWriter\n );\n }\n f = message.getCspot();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n Spotify_pb.Spotify.serializeBinaryToWriter\n );\n }\n f = message.getAirplay();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n AirPlay_pb.AirPlay.serializeBinaryToWriter\n );\n }\n f = message.getSqueezeliteProfilesList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 6,\n f,\n Squeezelite_pb.SqueezeliteProfile.serializeBinaryToWriter\n );\n }\n f = message.getReleaseUrl();\n if (f.length > 0) {\n writer.writeString(\n 7,\n f\n );\n }\n f = message.getBtSink();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.sys.BluetoothSink.serializeBinaryToWriter\n );\n }\n f = message.getStatistics();\n if (f) {\n writer.writeBool(\n 9,\n f\n );\n }\n f = message.getTelnet();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n proto.sys.Telnet.serializeBinaryToWriter\n );\n }\n f = message.getEqualizer();\n if (f != null) {\n writer.writeMessage(\n 11,\n f,\n Equalizer_pb.Equalizer.serializeBinaryToWriter\n );\n }\n f = message.getCurrentProfile();\n if (f.length > 0) {\n writer.writeString(\n 12,\n f\n );\n }\n};\n\n\n/**\n * optional Metadata metadata = 1;\n * @return {?proto.sys.Metadata}\n */\nproto.sys.Services.prototype.getMetadata = function() {\n return /** @type{?proto.sys.Metadata} */ (\n jspb.Message.getWrapperField(this, proto.sys.Metadata, 1));\n};\n\n\n/**\n * @param {?proto.sys.Metadata|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setMetadata = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearMetadata = function() {\n return this.setMetadata(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasMetadata = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional SleepService sleep = 2;\n * @return {?proto.sys.SleepService}\n */\nproto.sys.Services.prototype.getSleep = function() {\n return /** @type{?proto.sys.SleepService} */ (\n jspb.Message.getWrapperField(this, proto.sys.SleepService, 2));\n};\n\n\n/**\n * @param {?proto.sys.SleepService|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setSleep = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearSleep = function() {\n return this.setSleep(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasSleep = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional Spotify cspot = 4;\n * @return {?proto.sys.Spotify}\n */\nproto.sys.Services.prototype.getCspot = function() {\n return /** @type{?proto.sys.Spotify} */ (\n jspb.Message.getWrapperField(this, Spotify_pb.Spotify, 4));\n};\n\n\n/**\n * @param {?proto.sys.Spotify|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setCspot = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearCspot = function() {\n return this.setCspot(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasCspot = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional AirPlay airplay = 5;\n * @return {?proto.sys.AirPlay}\n */\nproto.sys.Services.prototype.getAirplay = function() {\n return /** @type{?proto.sys.AirPlay} */ (\n jspb.Message.getWrapperField(this, AirPlay_pb.AirPlay, 5));\n};\n\n\n/**\n * @param {?proto.sys.AirPlay|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setAirplay = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearAirplay = function() {\n return this.setAirplay(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasAirplay = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * repeated SqueezeliteProfile squeezelite_profiles = 6;\n * @return {!Array}\n */\nproto.sys.Services.prototype.getSqueezeliteProfilesList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, Squeezelite_pb.SqueezeliteProfile, 6));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setSqueezeliteProfilesList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 6, value);\n};\n\n\n/**\n * @param {!proto.sys.SqueezeliteProfile=} opt_value\n * @param {number=} opt_index\n * @return {!proto.sys.SqueezeliteProfile}\n */\nproto.sys.Services.prototype.addSqueezeliteProfiles = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 6, opt_value, proto.sys.SqueezeliteProfile, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearSqueezeliteProfilesList = function() {\n return this.setSqueezeliteProfilesList([]);\n};\n\n\n/**\n * optional string release_url = 7;\n * @return {string}\n */\nproto.sys.Services.prototype.getReleaseUrl = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.setReleaseUrl = function(value) {\n return jspb.Message.setProto3StringField(this, 7, value);\n};\n\n\n/**\n * optional BluetoothSink bt_sink = 8;\n * @return {?proto.sys.BluetoothSink}\n */\nproto.sys.Services.prototype.getBtSink = function() {\n return /** @type{?proto.sys.BluetoothSink} */ (\n jspb.Message.getWrapperField(this, proto.sys.BluetoothSink, 8));\n};\n\n\n/**\n * @param {?proto.sys.BluetoothSink|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setBtSink = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearBtSink = function() {\n return this.setBtSink(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasBtSink = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional bool statistics = 9;\n * @return {boolean}\n */\nproto.sys.Services.prototype.getStatistics = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.setStatistics = function(value) {\n return jspb.Message.setProto3BooleanField(this, 9, value);\n};\n\n\n/**\n * optional Telnet telnet = 10;\n * @return {?proto.sys.Telnet}\n */\nproto.sys.Services.prototype.getTelnet = function() {\n return /** @type{?proto.sys.Telnet} */ (\n jspb.Message.getWrapperField(this, proto.sys.Telnet, 10));\n};\n\n\n/**\n * @param {?proto.sys.Telnet|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setTelnet = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearTelnet = function() {\n return this.setTelnet(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasTelnet = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional Equalizer equalizer = 11;\n * @return {?proto.sys.Equalizer}\n */\nproto.sys.Services.prototype.getEqualizer = function() {\n return /** @type{?proto.sys.Equalizer} */ (\n jspb.Message.getWrapperField(this, Equalizer_pb.Equalizer, 11));\n};\n\n\n/**\n * @param {?proto.sys.Equalizer|undefined} value\n * @return {!proto.sys.Services} returns this\n*/\nproto.sys.Services.prototype.setEqualizer = function(value) {\n return jspb.Message.setWrapperField(this, 11, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.clearEqualizer = function() {\n return this.setEqualizer(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Services.prototype.hasEqualizer = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n/**\n * optional string current_profile = 12;\n * @return {string}\n */\nproto.sys.Services.prototype.getCurrentProfile = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 12, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Services} returns this\n */\nproto.sys.Services.prototype.setCurrentProfile = function(value) {\n return jspb.Message.setProto3StringField(this, 12, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.TelnetEnableEnum = {\n SERIAL_ONLY: 0,\n TELNET: 1,\n TELNET_SERIAL: 2\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: Spotify.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Spotify', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Spotify = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Spotify, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Spotify.displayName = 'proto.sys.Spotify';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Spotify.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Spotify.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Spotify} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Spotify.toObject = function(includeInstance, msg) {\n var f, obj = {\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n bitrate: jspb.Message.getFieldWithDefault(msg, 2, 0),\n zeroconf: jspb.Message.getBooleanFieldWithDefault(msg, 3, false),\n volume: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Spotify}\n */\nproto.sys.Spotify.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Spotify;\n return proto.sys.Spotify.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Spotify} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Spotify}\n */\nproto.sys.Spotify.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setBitrate(value);\n break;\n case 3:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setZeroconf(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setVolume(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Spotify.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Spotify.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Spotify} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Spotify.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getBitrate();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n f = message.getZeroconf();\n if (f) {\n writer.writeBool(\n 3,\n f\n );\n }\n f = message.getVolume();\n if (f !== 0) {\n writer.writeUint32(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional bool enabled = 1;\n * @return {boolean}\n */\nproto.sys.Spotify.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Spotify} returns this\n */\nproto.sys.Spotify.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional uint32 bitrate = 2;\n * @return {number}\n */\nproto.sys.Spotify.prototype.getBitrate = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Spotify} returns this\n */\nproto.sys.Spotify.prototype.setBitrate = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional bool zeroconf = 3;\n * @return {boolean}\n */\nproto.sys.Spotify.prototype.getZeroconf = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Spotify} returns this\n */\nproto.sys.Spotify.prototype.setZeroconf = function(value) {\n return jspb.Message.setProto3BooleanField(this, 3, value);\n};\n\n\n/**\n * optional uint32 volume = 4;\n * @return {number}\n */\nproto.sys.Spotify.prototype.getVolume = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Spotify} returns this\n */\nproto.sys.Spotify.prototype.setVolume = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: Squeezelite.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.BufferOption', null, global);\ngoog.exportSymbol('proto.sys.CodexEnum', null, global);\ngoog.exportSymbol('proto.sys.DebugLevelEnum', null, global);\ngoog.exportSymbol('proto.sys.DebugOptions', null, global);\ngoog.exportSymbol('proto.sys.OutputBT', null, global);\ngoog.exportSymbol('proto.sys.OutputTypeEnum', null, global);\ngoog.exportSymbol('proto.sys.RatesOption', null, global);\ngoog.exportSymbol('proto.sys.ResampleAlgorithm', null, global);\ngoog.exportSymbol('proto.sys.ResampleOptions', null, global);\ngoog.exportSymbol('proto.sys.SampleRate', null, global);\ngoog.exportSymbol('proto.sys.Squeezelite', null, global);\ngoog.exportSymbol('proto.sys.SqueezeliteProfile', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.OutputBT = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.OutputBT, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.OutputBT.displayName = 'proto.sys.OutputBT';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.ResampleOptions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.ResampleOptions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.ResampleOptions.displayName = 'proto.sys.ResampleOptions';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.RatesOption = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.RatesOption.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.RatesOption, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.RatesOption.displayName = 'proto.sys.RatesOption';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.BufferOption = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.BufferOption, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.BufferOption.displayName = 'proto.sys.BufferOption';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.DebugOptions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.DebugOptions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.DebugOptions.displayName = 'proto.sys.DebugOptions';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Squeezelite = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.sys.Squeezelite.repeatedFields_, null);\n};\ngoog.inherits(proto.sys.Squeezelite, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Squeezelite.displayName = 'proto.sys.Squeezelite';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.SqueezeliteProfile = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.SqueezeliteProfile, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.SqueezeliteProfile.displayName = 'proto.sys.SqueezeliteProfile';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.OutputBT.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.OutputBT.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.OutputBT} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.OutputBT.toObject = function(includeInstance, msg) {\n var f, obj = {\n sinkName: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n pin: jspb.Message.getFieldWithDefault(msg, 2, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.OutputBT}\n */\nproto.sys.OutputBT.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.OutputBT;\n return proto.sys.OutputBT.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.OutputBT} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.OutputBT}\n */\nproto.sys.OutputBT.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setSinkName(value);\n break;\n case 2:\n var value = /** @type {string} */ (reader.readString());\n msg.setPin(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.OutputBT.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.OutputBT.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.OutputBT} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.OutputBT.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getSinkName();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getPin();\n if (f.length > 0) {\n writer.writeString(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional string sink_name = 1;\n * @return {string}\n */\nproto.sys.OutputBT.prototype.getSinkName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.OutputBT} returns this\n */\nproto.sys.OutputBT.prototype.setSinkName = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional string pin = 2;\n * @return {string}\n */\nproto.sys.OutputBT.prototype.getPin = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.OutputBT} returns this\n */\nproto.sys.OutputBT.prototype.setPin = function(value) {\n return jspb.Message.setProto3StringField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.ResampleOptions.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.ResampleOptions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.ResampleOptions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ResampleOptions.toObject = function(includeInstance, msg) {\n var f, obj = {\n algorithm: jspb.Message.getFieldWithDefault(msg, 1, 0),\n interpolateFilterCoefficients: jspb.Message.getBooleanFieldWithDefault(msg, 2, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.ResampleOptions}\n */\nproto.sys.ResampleOptions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.ResampleOptions;\n return proto.sys.ResampleOptions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.ResampleOptions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.ResampleOptions}\n */\nproto.sys.ResampleOptions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.ResampleAlgorithm} */ (reader.readEnum());\n msg.setAlgorithm(value);\n break;\n case 2:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setInterpolateFilterCoefficients(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.ResampleOptions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.ResampleOptions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.ResampleOptions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.ResampleOptions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getAlgorithm();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getInterpolateFilterCoefficients();\n if (f) {\n writer.writeBool(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional ResampleAlgorithm algorithm = 1;\n * @return {!proto.sys.ResampleAlgorithm}\n */\nproto.sys.ResampleOptions.prototype.getAlgorithm = function() {\n return /** @type {!proto.sys.ResampleAlgorithm} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.ResampleAlgorithm} value\n * @return {!proto.sys.ResampleOptions} returns this\n */\nproto.sys.ResampleOptions.prototype.setAlgorithm = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional bool interpolate_filter_coefficients = 2;\n * @return {boolean}\n */\nproto.sys.ResampleOptions.prototype.getInterpolateFilterCoefficients = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.ResampleOptions} returns this\n */\nproto.sys.ResampleOptions.prototype.setInterpolateFilterCoefficients = function(value) {\n return jspb.Message.setProto3BooleanField(this, 2, value);\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.RatesOption.repeatedFields_ = [3];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.RatesOption.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.RatesOption.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.RatesOption} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.RatesOption.toObject = function(includeInstance, msg) {\n var f, obj = {\n min: jspb.Message.getFieldWithDefault(msg, 1, 0),\n max: jspb.Message.getFieldWithDefault(msg, 2, 0),\n listList: (f = jspb.Message.getRepeatedField(msg, 3)) == null ? undefined : f\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.RatesOption}\n */\nproto.sys.RatesOption.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.RatesOption;\n return proto.sys.RatesOption.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.RatesOption} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.RatesOption}\n */\nproto.sys.RatesOption.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.SampleRate} */ (reader.readEnum());\n msg.setMin(value);\n break;\n case 2:\n var value = /** @type {!proto.sys.SampleRate} */ (reader.readEnum());\n msg.setMax(value);\n break;\n case 3:\n var values = /** @type {!Array} */ (reader.isDelimited() ? reader.readPackedEnum() : [reader.readEnum()]);\n for (var i = 0; i < values.length; i++) {\n msg.addList(values[i]);\n }\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.RatesOption.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.RatesOption.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.RatesOption} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.RatesOption.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMin();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getMax();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n f = message.getListList();\n if (f.length > 0) {\n writer.writePackedEnum(\n 3,\n f\n );\n }\n};\n\n\n/**\n * optional SampleRate min = 1;\n * @return {!proto.sys.SampleRate}\n */\nproto.sys.RatesOption.prototype.getMin = function() {\n return /** @type {!proto.sys.SampleRate} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.SampleRate} value\n * @return {!proto.sys.RatesOption} returns this\n */\nproto.sys.RatesOption.prototype.setMin = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional SampleRate max = 2;\n * @return {!proto.sys.SampleRate}\n */\nproto.sys.RatesOption.prototype.getMax = function() {\n return /** @type {!proto.sys.SampleRate} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.sys.SampleRate} value\n * @return {!proto.sys.RatesOption} returns this\n */\nproto.sys.RatesOption.prototype.setMax = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n/**\n * repeated SampleRate list = 3;\n * @return {!Array}\n */\nproto.sys.RatesOption.prototype.getListList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 3));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.RatesOption} returns this\n */\nproto.sys.RatesOption.prototype.setListList = function(value) {\n return jspb.Message.setField(this, 3, value || []);\n};\n\n\n/**\n * @param {!proto.sys.SampleRate} value\n * @param {number=} opt_index\n * @return {!proto.sys.RatesOption} returns this\n */\nproto.sys.RatesOption.prototype.addList = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 3, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.RatesOption} returns this\n */\nproto.sys.RatesOption.prototype.clearListList = function() {\n return this.setListList([]);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.BufferOption.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.BufferOption.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.BufferOption} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.BufferOption.toObject = function(includeInstance, msg) {\n var f, obj = {\n stream: jspb.Message.getFieldWithDefault(msg, 1, 0),\n output: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.BufferOption}\n */\nproto.sys.BufferOption.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.BufferOption;\n return proto.sys.BufferOption.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.BufferOption} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.BufferOption}\n */\nproto.sys.BufferOption.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setStream(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setOutput(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.BufferOption.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.BufferOption.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.BufferOption} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.BufferOption.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getStream();\n if (f !== 0) {\n writer.writeUint32(\n 1,\n f\n );\n }\n f = message.getOutput();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional uint32 stream = 1;\n * @return {number}\n */\nproto.sys.BufferOption.prototype.getStream = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.BufferOption} returns this\n */\nproto.sys.BufferOption.prototype.setStream = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional uint32 output = 2;\n * @return {number}\n */\nproto.sys.BufferOption.prototype.getOutput = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.BufferOption} returns this\n */\nproto.sys.BufferOption.prototype.setOutput = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.DebugOptions.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.DebugOptions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.DebugOptions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DebugOptions.toObject = function(includeInstance, msg) {\n var f, obj = {\n output: jspb.Message.getFieldWithDefault(msg, 1, 0),\n stream: jspb.Message.getFieldWithDefault(msg, 2, 0),\n decode: jspb.Message.getFieldWithDefault(msg, 3, 0),\n slimproto: jspb.Message.getFieldWithDefault(msg, 4, 0),\n ir: jspb.Message.getFieldWithDefault(msg, 5, 0),\n all: jspb.Message.getFieldWithDefault(msg, 6, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.DebugOptions}\n */\nproto.sys.DebugOptions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.DebugOptions;\n return proto.sys.DebugOptions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.DebugOptions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.DebugOptions}\n */\nproto.sys.DebugOptions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setOutput(value);\n break;\n case 2:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setStream(value);\n break;\n case 3:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setDecode(value);\n break;\n case 4:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setSlimproto(value);\n break;\n case 5:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setIr(value);\n break;\n case 6:\n var value = /** @type {!proto.sys.DebugLevelEnum} */ (reader.readEnum());\n msg.setAll(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.DebugOptions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.DebugOptions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.DebugOptions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.DebugOptions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getOutput();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getStream();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n f = message.getDecode();\n if (f !== 0.0) {\n writer.writeEnum(\n 3,\n f\n );\n }\n f = message.getSlimproto();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n f = message.getIr();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n f = message.getAll();\n if (f !== 0.0) {\n writer.writeEnum(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional DebugLevelEnum output = 1;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getOutput = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setOutput = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional DebugLevelEnum stream = 2;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getStream = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setStream = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n/**\n * optional DebugLevelEnum decode = 3;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getDecode = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setDecode = function(value) {\n return jspb.Message.setProto3EnumField(this, 3, value);\n};\n\n\n/**\n * optional DebugLevelEnum slimproto = 4;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getSlimproto = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setSlimproto = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * optional DebugLevelEnum ir = 5;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getIr = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setIr = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n/**\n * optional DebugLevelEnum all = 6;\n * @return {!proto.sys.DebugLevelEnum}\n */\nproto.sys.DebugOptions.prototype.getAll = function() {\n return /** @type {!proto.sys.DebugLevelEnum} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {!proto.sys.DebugLevelEnum} value\n * @return {!proto.sys.DebugOptions} returns this\n */\nproto.sys.DebugOptions.prototype.setAll = function(value) {\n return jspb.Message.setProto3EnumField(this, 6, value);\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.sys.Squeezelite.repeatedFields_ = [13,14];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Squeezelite.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Squeezelite.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Squeezelite} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Squeezelite.toObject = function(includeInstance, msg) {\n var f, obj = {\n outputType: jspb.Message.getFieldWithDefault(msg, 1, 0),\n rates: (f = msg.getRates()) && proto.sys.RatesOption.toObject(includeInstance, f),\n ampGpioTimeout: jspb.Message.getFieldWithDefault(msg, 3, 0),\n wavAiffHeaderParsing: jspb.Message.getBooleanFieldWithDefault(msg, 4, false),\n serverNameIp: jspb.Message.getFieldWithDefault(msg, 5, \"\"),\n serverPort: jspb.Message.getFieldWithDefault(msg, 6, 0),\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 7, false),\n outputBt: (f = msg.getOutputBt()) && proto.sys.OutputBT.toObject(includeInstance, f),\n log: (f = msg.getLog()) && proto.sys.DebugOptions.toObject(includeInstance, f),\n maxRate: jspb.Message.getFieldWithDefault(msg, 10, 0),\n buffers: (f = msg.getBuffers()) && proto.sys.BufferOption.toObject(includeInstance, f),\n resample: jspb.Message.getFieldWithDefault(msg, 12, \"\"),\n includedCodexList: (f = jspb.Message.getRepeatedField(msg, 13)) == null ? undefined : f,\n excludedCodexList: (f = jspb.Message.getRepeatedField(msg, 14)) == null ? undefined : f\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Squeezelite}\n */\nproto.sys.Squeezelite.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Squeezelite;\n return proto.sys.Squeezelite.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Squeezelite} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Squeezelite}\n */\nproto.sys.Squeezelite.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.sys.OutputTypeEnum} */ (reader.readEnum());\n msg.setOutputType(value);\n break;\n case 2:\n var value = new proto.sys.RatesOption;\n reader.readMessage(value,proto.sys.RatesOption.deserializeBinaryFromReader);\n msg.setRates(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setAmpGpioTimeout(value);\n break;\n case 4:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setWavAiffHeaderParsing(value);\n break;\n case 5:\n var value = /** @type {string} */ (reader.readString());\n msg.setServerNameIp(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setServerPort(value);\n break;\n case 7:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 8:\n var value = new proto.sys.OutputBT;\n reader.readMessage(value,proto.sys.OutputBT.deserializeBinaryFromReader);\n msg.setOutputBt(value);\n break;\n case 9:\n var value = new proto.sys.DebugOptions;\n reader.readMessage(value,proto.sys.DebugOptions.deserializeBinaryFromReader);\n msg.setLog(value);\n break;\n case 10:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMaxRate(value);\n break;\n case 11:\n var value = new proto.sys.BufferOption;\n reader.readMessage(value,proto.sys.BufferOption.deserializeBinaryFromReader);\n msg.setBuffers(value);\n break;\n case 12:\n var value = /** @type {string} */ (reader.readString());\n msg.setResample(value);\n break;\n case 13:\n var values = /** @type {!Array} */ (reader.isDelimited() ? reader.readPackedEnum() : [reader.readEnum()]);\n for (var i = 0; i < values.length; i++) {\n msg.addIncludedCodex(values[i]);\n }\n break;\n case 14:\n var values = /** @type {!Array} */ (reader.isDelimited() ? reader.readPackedEnum() : [reader.readEnum()]);\n for (var i = 0; i < values.length; i++) {\n msg.addExcludedCodex(values[i]);\n }\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Squeezelite.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Squeezelite.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Squeezelite} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Squeezelite.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getOutputType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getRates();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.RatesOption.serializeBinaryToWriter\n );\n }\n f = message.getAmpGpioTimeout();\n if (f !== 0) {\n writer.writeInt32(\n 3,\n f\n );\n }\n f = message.getWavAiffHeaderParsing();\n if (f) {\n writer.writeBool(\n 4,\n f\n );\n }\n f = message.getServerNameIp();\n if (f.length > 0) {\n writer.writeString(\n 5,\n f\n );\n }\n f = message.getServerPort();\n if (f !== 0) {\n writer.writeUint32(\n 6,\n f\n );\n }\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 7,\n f\n );\n }\n f = message.getOutputBt();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.sys.OutputBT.serializeBinaryToWriter\n );\n }\n f = message.getLog();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n proto.sys.DebugOptions.serializeBinaryToWriter\n );\n }\n f = message.getMaxRate();\n if (f !== 0) {\n writer.writeUint32(\n 10,\n f\n );\n }\n f = message.getBuffers();\n if (f != null) {\n writer.writeMessage(\n 11,\n f,\n proto.sys.BufferOption.serializeBinaryToWriter\n );\n }\n f = message.getResample();\n if (f.length > 0) {\n writer.writeString(\n 12,\n f\n );\n }\n f = message.getIncludedCodexList();\n if (f.length > 0) {\n writer.writePackedEnum(\n 13,\n f\n );\n }\n f = message.getExcludedCodexList();\n if (f.length > 0) {\n writer.writePackedEnum(\n 14,\n f\n );\n }\n};\n\n\n/**\n * optional OutputTypeEnum output_type = 1;\n * @return {!proto.sys.OutputTypeEnum}\n */\nproto.sys.Squeezelite.prototype.getOutputType = function() {\n return /** @type {!proto.sys.OutputTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.sys.OutputTypeEnum} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setOutputType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional RatesOption rates = 2;\n * @return {?proto.sys.RatesOption}\n */\nproto.sys.Squeezelite.prototype.getRates = function() {\n return /** @type{?proto.sys.RatesOption} */ (\n jspb.Message.getWrapperField(this, proto.sys.RatesOption, 2));\n};\n\n\n/**\n * @param {?proto.sys.RatesOption|undefined} value\n * @return {!proto.sys.Squeezelite} returns this\n*/\nproto.sys.Squeezelite.prototype.setRates = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearRates = function() {\n return this.setRates(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.hasRates = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional int32 amp_gpio_timeout = 3;\n * @return {number}\n */\nproto.sys.Squeezelite.prototype.getAmpGpioTimeout = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setAmpGpioTimeout = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional bool wav_aiff_header_parsing = 4;\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.getWavAiffHeaderParsing = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setWavAiffHeaderParsing = function(value) {\n return jspb.Message.setProto3BooleanField(this, 4, value);\n};\n\n\n/**\n * optional string server_name_ip = 5;\n * @return {string}\n */\nproto.sys.Squeezelite.prototype.getServerNameIp = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setServerNameIp = function(value) {\n return jspb.Message.setProto3StringField(this, 5, value);\n};\n\n\n/**\n * optional uint32 server_port = 6;\n * @return {number}\n */\nproto.sys.Squeezelite.prototype.getServerPort = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setServerPort = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional bool enabled = 7;\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 7, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 7, value);\n};\n\n\n/**\n * optional OutputBT output_bt = 8;\n * @return {?proto.sys.OutputBT}\n */\nproto.sys.Squeezelite.prototype.getOutputBt = function() {\n return /** @type{?proto.sys.OutputBT} */ (\n jspb.Message.getWrapperField(this, proto.sys.OutputBT, 8));\n};\n\n\n/**\n * @param {?proto.sys.OutputBT|undefined} value\n * @return {!proto.sys.Squeezelite} returns this\n*/\nproto.sys.Squeezelite.prototype.setOutputBt = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearOutputBt = function() {\n return this.setOutputBt(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.hasOutputBt = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional DebugOptions log = 9;\n * @return {?proto.sys.DebugOptions}\n */\nproto.sys.Squeezelite.prototype.getLog = function() {\n return /** @type{?proto.sys.DebugOptions} */ (\n jspb.Message.getWrapperField(this, proto.sys.DebugOptions, 9));\n};\n\n\n/**\n * @param {?proto.sys.DebugOptions|undefined} value\n * @return {!proto.sys.Squeezelite} returns this\n*/\nproto.sys.Squeezelite.prototype.setLog = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearLog = function() {\n return this.setLog(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.hasLog = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional uint32 max_rate = 10;\n * @return {number}\n */\nproto.sys.Squeezelite.prototype.getMaxRate = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setMaxRate = function(value) {\n return jspb.Message.setProto3IntField(this, 10, value);\n};\n\n\n/**\n * optional BufferOption buffers = 11;\n * @return {?proto.sys.BufferOption}\n */\nproto.sys.Squeezelite.prototype.getBuffers = function() {\n return /** @type{?proto.sys.BufferOption} */ (\n jspb.Message.getWrapperField(this, proto.sys.BufferOption, 11));\n};\n\n\n/**\n * @param {?proto.sys.BufferOption|undefined} value\n * @return {!proto.sys.Squeezelite} returns this\n*/\nproto.sys.Squeezelite.prototype.setBuffers = function(value) {\n return jspb.Message.setWrapperField(this, 11, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearBuffers = function() {\n return this.setBuffers(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Squeezelite.prototype.hasBuffers = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n/**\n * optional string resample = 12;\n * @return {string}\n */\nproto.sys.Squeezelite.prototype.getResample = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 12, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setResample = function(value) {\n return jspb.Message.setProto3StringField(this, 12, value);\n};\n\n\n/**\n * repeated CodexEnum included_codex = 13;\n * @return {!Array}\n */\nproto.sys.Squeezelite.prototype.getIncludedCodexList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 13));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setIncludedCodexList = function(value) {\n return jspb.Message.setField(this, 13, value || []);\n};\n\n\n/**\n * @param {!proto.sys.CodexEnum} value\n * @param {number=} opt_index\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.addIncludedCodex = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 13, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearIncludedCodexList = function() {\n return this.setIncludedCodexList([]);\n};\n\n\n/**\n * repeated CodexEnum excluded_codex = 14;\n * @return {!Array}\n */\nproto.sys.Squeezelite.prototype.getExcludedCodexList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 14));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.setExcludedCodexList = function(value) {\n return jspb.Message.setField(this, 14, value || []);\n};\n\n\n/**\n * @param {!proto.sys.CodexEnum} value\n * @param {number=} opt_index\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.addExcludedCodex = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 14, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.sys.Squeezelite} returns this\n */\nproto.sys.Squeezelite.prototype.clearExcludedCodexList = function() {\n return this.setExcludedCodexList([]);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.SqueezeliteProfile.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.SqueezeliteProfile.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.SqueezeliteProfile} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SqueezeliteProfile.toObject = function(includeInstance, msg) {\n var f, obj = {\n name: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n profile: (f = msg.getProfile()) && proto.sys.Squeezelite.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.SqueezeliteProfile}\n */\nproto.sys.SqueezeliteProfile.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.SqueezeliteProfile;\n return proto.sys.SqueezeliteProfile.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.SqueezeliteProfile} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.SqueezeliteProfile}\n */\nproto.sys.SqueezeliteProfile.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setName(value);\n break;\n case 2:\n var value = new proto.sys.Squeezelite;\n reader.readMessage(value,proto.sys.Squeezelite.deserializeBinaryFromReader);\n msg.setProfile(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.SqueezeliteProfile.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.SqueezeliteProfile.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.SqueezeliteProfile} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.SqueezeliteProfile.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getName();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getProfile();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.sys.Squeezelite.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional string name = 1;\n * @return {string}\n */\nproto.sys.SqueezeliteProfile.prototype.getName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.SqueezeliteProfile} returns this\n */\nproto.sys.SqueezeliteProfile.prototype.setName = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional Squeezelite profile = 2;\n * @return {?proto.sys.Squeezelite}\n */\nproto.sys.SqueezeliteProfile.prototype.getProfile = function() {\n return /** @type{?proto.sys.Squeezelite} */ (\n jspb.Message.getWrapperField(this, proto.sys.Squeezelite, 2));\n};\n\n\n/**\n * @param {?proto.sys.Squeezelite|undefined} value\n * @return {!proto.sys.SqueezeliteProfile} returns this\n*/\nproto.sys.SqueezeliteProfile.prototype.setProfile = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.SqueezeliteProfile} returns this\n */\nproto.sys.SqueezeliteProfile.prototype.clearProfile = function() {\n return this.setProfile(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.SqueezeliteProfile.prototype.hasProfile = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.sys.OutputTypeEnum = {\n OUTPUT_UNKNOWN: 0,\n OUTPUT_I2S: 1,\n OUTPUT_SPDIF: 2,\n OUTPUT_BLUETOOTH: 3\n};\n\n/**\n * @enum {number}\n */\nproto.sys.ResampleAlgorithm = {\n RA_DISABLED: 0,\n RA_BASIC_LINEAR: 1,\n RA_THIRTEEN_TAPS: 2,\n RA_TWENTY_ONE_TAPS: 3\n};\n\n/**\n * @enum {number}\n */\nproto.sys.SampleRate = {\n SAMPLE_RATE_UNSPECIFIED: 0,\n SAMPLE_RATE_8000: 8000,\n SAMPLE_RATE_11025: 11025,\n SAMPLE_RATE_12000: 12000,\n SAMPLE_RATE_16000: 16000,\n SAMPLE_RATE_22050: 22050,\n SAMPLE_RATE_24000: 24000,\n SAMPLE_RATE_32000: 32000,\n SAMPLE_RATE_44100: 44100,\n SAMPLE_RATE_48000: 48000,\n SAMPLE_RATE_88200: 88200,\n SAMPLE_RATE_96000: 96000,\n SAMPLE_RATE_176400: 176400,\n SAMPLE_RATE_192000: 192000,\n SAMPLE_RATE_352800: 352800,\n SAMPLE_RATE_384000: 384000,\n SAMPLE_RATE_705600: 705600,\n SAMPLE_RATE_768000: 768000\n};\n\n/**\n * @enum {number}\n */\nproto.sys.DebugLevelEnum = {\n DEFAULT: 0,\n ERROR: 1,\n WARN: 2,\n INFO: 3,\n DEBUG: 4,\n SDEBUG: 5\n};\n\n/**\n * @enum {number}\n */\nproto.sys.CodexEnum = {\n C_UNDEFINED: 0,\n C_ALAC: 1,\n C_OGG: 2,\n C_OPS: 3,\n C_FLAC: 4,\n C_PCM: 5,\n C_MP3: 6,\n C_MAD: 7,\n C_MPG: 8\n};\n\ngoog.object.extend(exports, proto.sys);\n","// source: configuration.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar Services_pb = require('./Services_pb.js');\ngoog.object.extend(proto, Services_pb);\nvar GPIO_pb = require('./GPIO_pb.js');\ngoog.object.extend(proto, GPIO_pb);\nvar Devices_pb = require('./Devices_pb.js');\ngoog.object.extend(proto, Devices_pb);\nvar Names_pb = require('./Names_pb.js');\ngoog.object.extend(proto, Names_pb);\nvar Network_pb = require('./Network_pb.js');\ngoog.object.extend(proto, Network_pb);\nvar customoptions_pb = require('./customoptions_pb.js');\ngoog.object.extend(proto, customoptions_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.sys.Config', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.sys.Config = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.sys.Config, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.sys.Config.displayName = 'proto.sys.Config';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.sys.Config.prototype.toObject = function(opt_includeInstance) {\n return proto.sys.Config.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.sys.Config} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Config.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpios: (f = msg.getGpios()) && GPIO_pb.Gpios.toObject(includeInstance, f),\n dev: (f = msg.getDev()) && Devices_pb.Dev.toObject(includeInstance, f),\n services: (f = msg.getServices()) && Services_pb.Services.toObject(includeInstance, f),\n names: (f = msg.getNames()) && Names_pb.Names.toObject(includeInstance, f),\n target: jspb.Message.getFieldWithDefault(msg, 5, \"\"),\n net: (f = msg.getNet()) && Network_pb.NetworkConfig.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.sys.Config}\n */\nproto.sys.Config.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.sys.Config;\n return proto.sys.Config.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.sys.Config} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.sys.Config}\n */\nproto.sys.Config.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new GPIO_pb.Gpios;\n reader.readMessage(value,GPIO_pb.Gpios.deserializeBinaryFromReader);\n msg.setGpios(value);\n break;\n case 2:\n var value = new Devices_pb.Dev;\n reader.readMessage(value,Devices_pb.Dev.deserializeBinaryFromReader);\n msg.setDev(value);\n break;\n case 3:\n var value = new Services_pb.Services;\n reader.readMessage(value,Services_pb.Services.deserializeBinaryFromReader);\n msg.setServices(value);\n break;\n case 4:\n var value = new Names_pb.Names;\n reader.readMessage(value,Names_pb.Names.deserializeBinaryFromReader);\n msg.setNames(value);\n break;\n case 5:\n var value = /** @type {string} */ (reader.readString());\n msg.setTarget(value);\n break;\n case 6:\n var value = new Network_pb.NetworkConfig;\n reader.readMessage(value,Network_pb.NetworkConfig.deserializeBinaryFromReader);\n msg.setNet(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.sys.Config.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.sys.Config.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.sys.Config} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.sys.Config.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpios();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n GPIO_pb.Gpios.serializeBinaryToWriter\n );\n }\n f = message.getDev();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n Devices_pb.Dev.serializeBinaryToWriter\n );\n }\n f = message.getServices();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n Services_pb.Services.serializeBinaryToWriter\n );\n }\n f = message.getNames();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n Names_pb.Names.serializeBinaryToWriter\n );\n }\n f = message.getTarget();\n if (f.length > 0) {\n writer.writeString(\n 5,\n f\n );\n }\n f = message.getNet();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n Network_pb.NetworkConfig.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional Gpios gpios = 1;\n * @return {?proto.sys.Gpios}\n */\nproto.sys.Config.prototype.getGpios = function() {\n return /** @type{?proto.sys.Gpios} */ (\n jspb.Message.getWrapperField(this, GPIO_pb.Gpios, 1));\n};\n\n\n/**\n * @param {?proto.sys.Gpios|undefined} value\n * @return {!proto.sys.Config} returns this\n*/\nproto.sys.Config.prototype.setGpios = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.clearGpios = function() {\n return this.setGpios(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Config.prototype.hasGpios = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional Dev dev = 2;\n * @return {?proto.sys.Dev}\n */\nproto.sys.Config.prototype.getDev = function() {\n return /** @type{?proto.sys.Dev} */ (\n jspb.Message.getWrapperField(this, Devices_pb.Dev, 2));\n};\n\n\n/**\n * @param {?proto.sys.Dev|undefined} value\n * @return {!proto.sys.Config} returns this\n*/\nproto.sys.Config.prototype.setDev = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.clearDev = function() {\n return this.setDev(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Config.prototype.hasDev = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional Services services = 3;\n * @return {?proto.sys.Services}\n */\nproto.sys.Config.prototype.getServices = function() {\n return /** @type{?proto.sys.Services} */ (\n jspb.Message.getWrapperField(this, Services_pb.Services, 3));\n};\n\n\n/**\n * @param {?proto.sys.Services|undefined} value\n * @return {!proto.sys.Config} returns this\n*/\nproto.sys.Config.prototype.setServices = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.clearServices = function() {\n return this.setServices(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Config.prototype.hasServices = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional Names names = 4;\n * @return {?proto.sys.Names}\n */\nproto.sys.Config.prototype.getNames = function() {\n return /** @type{?proto.sys.Names} */ (\n jspb.Message.getWrapperField(this, Names_pb.Names, 4));\n};\n\n\n/**\n * @param {?proto.sys.Names|undefined} value\n * @return {!proto.sys.Config} returns this\n*/\nproto.sys.Config.prototype.setNames = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.clearNames = function() {\n return this.setNames(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Config.prototype.hasNames = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional string target = 5;\n * @return {string}\n */\nproto.sys.Config.prototype.getTarget = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.setTarget = function(value) {\n return jspb.Message.setProto3StringField(this, 5, value);\n};\n\n\n/**\n * optional NetworkConfig net = 6;\n * @return {?proto.sys.NetworkConfig}\n */\nproto.sys.Config.prototype.getNet = function() {\n return /** @type{?proto.sys.NetworkConfig} */ (\n jspb.Message.getWrapperField(this, Network_pb.NetworkConfig, 6));\n};\n\n\n/**\n * @param {?proto.sys.NetworkConfig|undefined} value\n * @return {!proto.sys.Config} returns this\n*/\nproto.sys.Config.prototype.setNet = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.sys.Config} returns this\n */\nproto.sys.Config.prototype.clearNet = function() {\n return this.setNet(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.sys.Config.prototype.hasNet = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\ngoog.object.extend(exports, proto.sys);\n","// source: customoptions.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar google_protobuf_descriptor_pb = require('google-protobuf/google/protobuf/descriptor_pb.js');\ngoog.object.extend(proto, google_protobuf_descriptor_pb);\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.CustomOptions', null, global);\ngoog.exportSymbol('proto.CustomOptions.DefaultValueCase', null, global);\ngoog.exportSymbol('proto.custEnum', null, global);\ngoog.exportSymbol('proto.custField', null, global);\ngoog.exportSymbol('proto.custFile', null, global);\ngoog.exportSymbol('proto.custMsg', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.CustomOptions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, 500, null, proto.CustomOptions.oneofGroups_);\n};\ngoog.inherits(proto.CustomOptions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.CustomOptions.displayName = 'proto.CustomOptions';\n}\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.CustomOptions.oneofGroups_ = [[50050,50051,50052,50053,50054,50055,50056,50057,50058,50059,50060]];\n\n/**\n * @enum {number}\n */\nproto.CustomOptions.DefaultValueCase = {\n DEFAULT_VALUE_NOT_SET: 0,\n V_STRING: 50050,\n V_UINT32: 50051,\n V_INT32: 50052,\n V_UINT64: 50053,\n V_INT64: 50054,\n V_DOUBLE: 50055,\n V_FLOAT: 50056,\n V_BOOL: 50057,\n V_ENUM: 50058,\n V_BYTES: 50059,\n V_MSG: 50060\n};\n\n/**\n * @return {proto.CustomOptions.DefaultValueCase}\n */\nproto.CustomOptions.prototype.getDefaultValueCase = function() {\n return /** @type {proto.CustomOptions.DefaultValueCase} */(jspb.Message.computeOneofCase(this, proto.CustomOptions.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.CustomOptions.prototype.toObject = function(opt_includeInstance) {\n return proto.CustomOptions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.CustomOptions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.CustomOptions.toObject = function(includeInstance, msg) {\n var f, obj = {\n initFromMac: jspb.Message.getBooleanFieldWithDefault(msg, 50001, false),\n constPrefix: jspb.Message.getFieldWithDefault(msg, 50002, \"\"),\n readOnly: jspb.Message.getBooleanFieldWithDefault(msg, 50003, false),\n vString: jspb.Message.getFieldWithDefault(msg, 50050, \"\"),\n vUint32: jspb.Message.getFieldWithDefault(msg, 50051, 0),\n vInt32: jspb.Message.getFieldWithDefault(msg, 50052, 0),\n vUint64: jspb.Message.getFieldWithDefault(msg, 50053, 0),\n vInt64: jspb.Message.getFieldWithDefault(msg, 50054, 0),\n vDouble: jspb.Message.getFloatingPointFieldWithDefault(msg, 50055, 0.0),\n vFloat: jspb.Message.getFloatingPointFieldWithDefault(msg, 50056, 0.0),\n vBool: jspb.Message.getBooleanFieldWithDefault(msg, 50057, false),\n vEnum: jspb.Message.getFieldWithDefault(msg, 50058, \"\"),\n vBytes: msg.getVBytes_asB64(),\n vMsg: msg.getVMsg_asB64(),\n globalName: jspb.Message.getFieldWithDefault(msg, 50005, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.CustomOptions}\n */\nproto.CustomOptions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.CustomOptions;\n return proto.CustomOptions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.CustomOptions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.CustomOptions}\n */\nproto.CustomOptions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 50001:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setInitFromMac(value);\n break;\n case 50002:\n var value = /** @type {string} */ (reader.readString());\n msg.setConstPrefix(value);\n break;\n case 50003:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setReadOnly(value);\n break;\n case 50050:\n var value = /** @type {string} */ (reader.readString());\n msg.setVString(value);\n break;\n case 50051:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setVUint32(value);\n break;\n case 50052:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setVInt32(value);\n break;\n case 50053:\n var value = /** @type {number} */ (reader.readUint64());\n msg.setVUint64(value);\n break;\n case 50054:\n var value = /** @type {number} */ (reader.readInt64());\n msg.setVInt64(value);\n break;\n case 50055:\n var value = /** @type {number} */ (reader.readDouble());\n msg.setVDouble(value);\n break;\n case 50056:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setVFloat(value);\n break;\n case 50057:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setVBool(value);\n break;\n case 50058:\n var value = /** @type {string} */ (reader.readString());\n msg.setVEnum(value);\n break;\n case 50059:\n var value = /** @type {!Uint8Array} */ (reader.readBytes());\n msg.setVBytes(value);\n break;\n case 50060:\n var value = /** @type {!Uint8Array} */ (reader.readBytes());\n msg.setVMsg(value);\n break;\n case 50005:\n var value = /** @type {string} */ (reader.readString());\n msg.setGlobalName(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.CustomOptions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.CustomOptions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.CustomOptions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.CustomOptions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getInitFromMac();\n if (f) {\n writer.writeBool(\n 50001,\n f\n );\n }\n f = message.getConstPrefix();\n if (f.length > 0) {\n writer.writeString(\n 50002,\n f\n );\n }\n f = message.getReadOnly();\n if (f) {\n writer.writeBool(\n 50003,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 50050));\n if (f != null) {\n writer.writeString(\n 50050,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50051));\n if (f != null) {\n writer.writeUint32(\n 50051,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50052));\n if (f != null) {\n writer.writeInt32(\n 50052,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50053));\n if (f != null) {\n writer.writeUint64(\n 50053,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50054));\n if (f != null) {\n writer.writeInt64(\n 50054,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50055));\n if (f != null) {\n writer.writeDouble(\n 50055,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 50056));\n if (f != null) {\n writer.writeFloat(\n 50056,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 50057));\n if (f != null) {\n writer.writeBool(\n 50057,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 50058));\n if (f != null) {\n writer.writeString(\n 50058,\n f\n );\n }\n f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 50059));\n if (f != null) {\n writer.writeBytes(\n 50059,\n f\n );\n }\n f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 50060));\n if (f != null) {\n writer.writeBytes(\n 50060,\n f\n );\n }\n f = message.getGlobalName();\n if (f.length > 0) {\n writer.writeString(\n 50005,\n f\n );\n }\n};\n\n\n/**\n * optional bool init_from_mac = 50001;\n * @return {boolean}\n */\nproto.CustomOptions.prototype.getInitFromMac = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 50001, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setInitFromMac = function(value) {\n return jspb.Message.setProto3BooleanField(this, 50001, value);\n};\n\n\n/**\n * optional string const_prefix = 50002;\n * @return {string}\n */\nproto.CustomOptions.prototype.getConstPrefix = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 50002, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setConstPrefix = function(value) {\n return jspb.Message.setProto3StringField(this, 50002, value);\n};\n\n\n/**\n * optional bool read_only = 50003;\n * @return {boolean}\n */\nproto.CustomOptions.prototype.getReadOnly = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 50003, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setReadOnly = function(value) {\n return jspb.Message.setProto3BooleanField(this, 50003, value);\n};\n\n\n/**\n * optional string v_string = 50050;\n * @return {string}\n */\nproto.CustomOptions.prototype.getVString = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 50050, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVString = function(value) {\n return jspb.Message.setOneofField(this, 50050, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVString = function() {\n return jspb.Message.setOneofField(this, 50050, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVString = function() {\n return jspb.Message.getField(this, 50050) != null;\n};\n\n\n/**\n * optional uint32 v_uint32 = 50051;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVUint32 = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 50051, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVUint32 = function(value) {\n return jspb.Message.setOneofField(this, 50051, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVUint32 = function() {\n return jspb.Message.setOneofField(this, 50051, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVUint32 = function() {\n return jspb.Message.getField(this, 50051) != null;\n};\n\n\n/**\n * optional int32 v_int32 = 50052;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVInt32 = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 50052, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVInt32 = function(value) {\n return jspb.Message.setOneofField(this, 50052, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVInt32 = function() {\n return jspb.Message.setOneofField(this, 50052, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVInt32 = function() {\n return jspb.Message.getField(this, 50052) != null;\n};\n\n\n/**\n * optional uint64 v_uint64 = 50053;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVUint64 = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 50053, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVUint64 = function(value) {\n return jspb.Message.setOneofField(this, 50053, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVUint64 = function() {\n return jspb.Message.setOneofField(this, 50053, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVUint64 = function() {\n return jspb.Message.getField(this, 50053) != null;\n};\n\n\n/**\n * optional int64 v_int64 = 50054;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVInt64 = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 50054, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVInt64 = function(value) {\n return jspb.Message.setOneofField(this, 50054, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVInt64 = function() {\n return jspb.Message.setOneofField(this, 50054, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVInt64 = function() {\n return jspb.Message.getField(this, 50054) != null;\n};\n\n\n/**\n * optional double v_double = 50055;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVDouble = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 50055, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVDouble = function(value) {\n return jspb.Message.setOneofField(this, 50055, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVDouble = function() {\n return jspb.Message.setOneofField(this, 50055, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVDouble = function() {\n return jspb.Message.getField(this, 50055) != null;\n};\n\n\n/**\n * optional float v_float = 50056;\n * @return {number}\n */\nproto.CustomOptions.prototype.getVFloat = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 50056, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVFloat = function(value) {\n return jspb.Message.setOneofField(this, 50056, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVFloat = function() {\n return jspb.Message.setOneofField(this, 50056, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVFloat = function() {\n return jspb.Message.getField(this, 50056) != null;\n};\n\n\n/**\n * optional bool v_bool = 50057;\n * @return {boolean}\n */\nproto.CustomOptions.prototype.getVBool = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 50057, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVBool = function(value) {\n return jspb.Message.setOneofField(this, 50057, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVBool = function() {\n return jspb.Message.setOneofField(this, 50057, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVBool = function() {\n return jspb.Message.getField(this, 50057) != null;\n};\n\n\n/**\n * optional string v_enum = 50058;\n * @return {string}\n */\nproto.CustomOptions.prototype.getVEnum = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 50058, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVEnum = function(value) {\n return jspb.Message.setOneofField(this, 50058, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVEnum = function() {\n return jspb.Message.setOneofField(this, 50058, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVEnum = function() {\n return jspb.Message.getField(this, 50058) != null;\n};\n\n\n/**\n * optional bytes v_bytes = 50059;\n * @return {!(string|Uint8Array)}\n */\nproto.CustomOptions.prototype.getVBytes = function() {\n return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 50059, \"\"));\n};\n\n\n/**\n * optional bytes v_bytes = 50059;\n * This is a type-conversion wrapper around `getVBytes()`\n * @return {string}\n */\nproto.CustomOptions.prototype.getVBytes_asB64 = function() {\n return /** @type {string} */ (jspb.Message.bytesAsB64(\n this.getVBytes()));\n};\n\n\n/**\n * optional bytes v_bytes = 50059;\n * Note that Uint8Array is not supported on all browsers.\n * @see http://caniuse.com/Uint8Array\n * This is a type-conversion wrapper around `getVBytes()`\n * @return {!Uint8Array}\n */\nproto.CustomOptions.prototype.getVBytes_asU8 = function() {\n return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(\n this.getVBytes()));\n};\n\n\n/**\n * @param {!(string|Uint8Array)} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVBytes = function(value) {\n return jspb.Message.setOneofField(this, 50059, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVBytes = function() {\n return jspb.Message.setOneofField(this, 50059, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVBytes = function() {\n return jspb.Message.getField(this, 50059) != null;\n};\n\n\n/**\n * optional bytes v_msg = 50060;\n * @return {!(string|Uint8Array)}\n */\nproto.CustomOptions.prototype.getVMsg = function() {\n return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 50060, \"\"));\n};\n\n\n/**\n * optional bytes v_msg = 50060;\n * This is a type-conversion wrapper around `getVMsg()`\n * @return {string}\n */\nproto.CustomOptions.prototype.getVMsg_asB64 = function() {\n return /** @type {string} */ (jspb.Message.bytesAsB64(\n this.getVMsg()));\n};\n\n\n/**\n * optional bytes v_msg = 50060;\n * Note that Uint8Array is not supported on all browsers.\n * @see http://caniuse.com/Uint8Array\n * This is a type-conversion wrapper around `getVMsg()`\n * @return {!Uint8Array}\n */\nproto.CustomOptions.prototype.getVMsg_asU8 = function() {\n return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(\n this.getVMsg()));\n};\n\n\n/**\n * @param {!(string|Uint8Array)} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setVMsg = function(value) {\n return jspb.Message.setOneofField(this, 50060, proto.CustomOptions.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.clearVMsg = function() {\n return jspb.Message.setOneofField(this, 50060, proto.CustomOptions.oneofGroups_[0], undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.CustomOptions.prototype.hasVMsg = function() {\n return jspb.Message.getField(this, 50060) != null;\n};\n\n\n/**\n * optional string global_name = 50005;\n * @return {string}\n */\nproto.CustomOptions.prototype.getGlobalName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 50005, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.CustomOptions} returns this\n */\nproto.CustomOptions.prototype.setGlobalName = function(value) {\n return jspb.Message.setProto3StringField(this, 50005, value);\n};\n\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `custFile`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.custFile = new jspb.ExtensionFieldInfo(\n 2010,\n {custFile: 0},\n proto.CustomOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.CustomOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FileOptions.extensionsBinary[2010] = new jspb.ExtensionFieldBinaryInfo(\n proto.custFile,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.CustomOptions.serializeBinaryToWriter,\n proto.CustomOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FileOptions.extensions[2010] = proto.custFile;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `custMsg`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.custMsg = new jspb.ExtensionFieldInfo(\n 2010,\n {custMsg: 0},\n proto.CustomOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.CustomOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.MessageOptions.extensionsBinary[2010] = new jspb.ExtensionFieldBinaryInfo(\n proto.custMsg,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.CustomOptions.serializeBinaryToWriter,\n proto.CustomOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.MessageOptions.extensions[2010] = proto.custMsg;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `custEnum`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.custEnum = new jspb.ExtensionFieldInfo(\n 2010,\n {custEnum: 0},\n proto.CustomOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.CustomOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.EnumOptions.extensionsBinary[2010] = new jspb.ExtensionFieldBinaryInfo(\n proto.custEnum,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.CustomOptions.serializeBinaryToWriter,\n proto.CustomOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.EnumOptions.extensions[2010] = proto.custEnum;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `custField`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.custField = new jspb.ExtensionFieldInfo(\n 2010,\n {custField: 0},\n proto.CustomOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.CustomOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FieldOptions.extensionsBinary[2010] = new jspb.ExtensionFieldBinaryInfo(\n proto.custField,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.CustomOptions.serializeBinaryToWriter,\n proto.CustomOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FieldOptions.extensions[2010] = proto.custField;\n\ngoog.object.extend(exports, proto);\n","// source: nanopb.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global =\n (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof window !== 'undefined' && window) ||\n (typeof global !== 'undefined' && global) ||\n (typeof self !== 'undefined' && self) ||\n (function () { return this; }).call(null) ||\n Function('return this')();\n\nvar google_protobuf_descriptor_pb = require('google-protobuf/google/protobuf/descriptor_pb.js');\ngoog.object.extend(proto, google_protobuf_descriptor_pb);\ngoog.exportSymbol('proto.DescriptorSize', null, global);\ngoog.exportSymbol('proto.FieldType', null, global);\ngoog.exportSymbol('proto.IntSize', null, global);\ngoog.exportSymbol('proto.NanoPBOptions', null, global);\ngoog.exportSymbol('proto.TypenameMangling', null, global);\ngoog.exportSymbol('proto.nanopb', null, global);\ngoog.exportSymbol('proto.nanopbEnumopt', null, global);\ngoog.exportSymbol('proto.nanopbFileopt', null, global);\ngoog.exportSymbol('proto.nanopbMsgopt', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.NanoPBOptions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.NanoPBOptions.repeatedFields_, null);\n};\ngoog.inherits(proto.NanoPBOptions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.NanoPBOptions.displayName = 'proto.NanoPBOptions';\n}\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.NanoPBOptions.repeatedFields_ = [24,26];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.NanoPBOptions.prototype.toObject = function(opt_includeInstance) {\n return proto.NanoPBOptions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.NanoPBOptions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.NanoPBOptions.toObject = function(includeInstance, msg) {\n var f, obj = {\n maxSize: (f = jspb.Message.getField(msg, 1)) == null ? undefined : f,\n maxLength: (f = jspb.Message.getField(msg, 14)) == null ? undefined : f,\n maxCount: (f = jspb.Message.getField(msg, 2)) == null ? undefined : f,\n intSize: jspb.Message.getFieldWithDefault(msg, 7, 0),\n type: jspb.Message.getFieldWithDefault(msg, 3, 0),\n longNames: jspb.Message.getBooleanFieldWithDefault(msg, 4, true),\n packedStruct: jspb.Message.getBooleanFieldWithDefault(msg, 5, false),\n packedEnum: jspb.Message.getBooleanFieldWithDefault(msg, 10, false),\n skipMessage: jspb.Message.getBooleanFieldWithDefault(msg, 6, false),\n noUnions: jspb.Message.getBooleanFieldWithDefault(msg, 8, false),\n msgid: (f = jspb.Message.getField(msg, 9)) == null ? undefined : f,\n anonymousOneof: jspb.Message.getBooleanFieldWithDefault(msg, 11, false),\n proto3: jspb.Message.getBooleanFieldWithDefault(msg, 12, false),\n proto3SingularMsgs: jspb.Message.getBooleanFieldWithDefault(msg, 21, false),\n enumToString: jspb.Message.getBooleanFieldWithDefault(msg, 13, false),\n fixedLength: jspb.Message.getBooleanFieldWithDefault(msg, 15, false),\n fixedCount: jspb.Message.getBooleanFieldWithDefault(msg, 16, false),\n submsgCallback: jspb.Message.getBooleanFieldWithDefault(msg, 22, false),\n mangleNames: jspb.Message.getFieldWithDefault(msg, 17, 0),\n callbackDatatype: jspb.Message.getFieldWithDefault(msg, 18, \"pb_callback_t\"),\n callbackFunction: jspb.Message.getFieldWithDefault(msg, 19, \"pb_default_field_callback\"),\n descriptorsize: jspb.Message.getFieldWithDefault(msg, 20, 0),\n defaultHas: jspb.Message.getBooleanFieldWithDefault(msg, 23, false),\n includeList: (f = jspb.Message.getRepeatedField(msg, 24)) == null ? undefined : f,\n excludeList: (f = jspb.Message.getRepeatedField(msg, 26)) == null ? undefined : f,\n pb_package: (f = jspb.Message.getField(msg, 25)) == null ? undefined : f,\n typeOverride: (f = jspb.Message.getField(msg, 27)) == null ? undefined : f,\n sortByTag: jspb.Message.getBooleanFieldWithDefault(msg, 28, true)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.NanoPBOptions}\n */\nproto.NanoPBOptions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.NanoPBOptions;\n return proto.NanoPBOptions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.NanoPBOptions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.NanoPBOptions}\n */\nproto.NanoPBOptions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxSize(value);\n break;\n case 14:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxLength(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxCount(value);\n break;\n case 7:\n var value = /** @type {!proto.IntSize} */ (reader.readEnum());\n msg.setIntSize(value);\n break;\n case 3:\n var value = /** @type {!proto.FieldType} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 4:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setLongNames(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPackedStruct(value);\n break;\n case 10:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPackedEnum(value);\n break;\n case 6:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSkipMessage(value);\n break;\n case 8:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setNoUnions(value);\n break;\n case 9:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMsgid(value);\n break;\n case 11:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setAnonymousOneof(value);\n break;\n case 12:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setProto3(value);\n break;\n case 21:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setProto3SingularMsgs(value);\n break;\n case 13:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnumToString(value);\n break;\n case 15:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setFixedLength(value);\n break;\n case 16:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setFixedCount(value);\n break;\n case 22:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSubmsgCallback(value);\n break;\n case 17:\n var value = /** @type {!proto.TypenameMangling} */ (reader.readEnum());\n msg.setMangleNames(value);\n break;\n case 18:\n var value = /** @type {string} */ (reader.readString());\n msg.setCallbackDatatype(value);\n break;\n case 19:\n var value = /** @type {string} */ (reader.readString());\n msg.setCallbackFunction(value);\n break;\n case 20:\n var value = /** @type {!proto.DescriptorSize} */ (reader.readEnum());\n msg.setDescriptorsize(value);\n break;\n case 23:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setDefaultHas(value);\n break;\n case 24:\n var value = /** @type {string} */ (reader.readString());\n msg.addInclude(value);\n break;\n case 26:\n var value = /** @type {string} */ (reader.readString());\n msg.addExclude(value);\n break;\n case 25:\n var value = /** @type {string} */ (reader.readString());\n msg.setPackage(value);\n break;\n case 27:\n var value = /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (reader.readEnum());\n msg.setTypeOverride(value);\n break;\n case 28:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSortByTag(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.NanoPBOptions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.NanoPBOptions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.NanoPBOptions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.NanoPBOptions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = /** @type {number} */ (jspb.Message.getField(message, 1));\n if (f != null) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 14));\n if (f != null) {\n writer.writeInt32(\n 14,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 2));\n if (f != null) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = /** @type {!proto.IntSize} */ (jspb.Message.getField(message, 7));\n if (f != null) {\n writer.writeEnum(\n 7,\n f\n );\n }\n f = /** @type {!proto.FieldType} */ (jspb.Message.getField(message, 3));\n if (f != null) {\n writer.writeEnum(\n 3,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 4));\n if (f != null) {\n writer.writeBool(\n 4,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 5));\n if (f != null) {\n writer.writeBool(\n 5,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 10));\n if (f != null) {\n writer.writeBool(\n 10,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 6));\n if (f != null) {\n writer.writeBool(\n 6,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 8));\n if (f != null) {\n writer.writeBool(\n 8,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 9));\n if (f != null) {\n writer.writeUint32(\n 9,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 11));\n if (f != null) {\n writer.writeBool(\n 11,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 12));\n if (f != null) {\n writer.writeBool(\n 12,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 21));\n if (f != null) {\n writer.writeBool(\n 21,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 13));\n if (f != null) {\n writer.writeBool(\n 13,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 15));\n if (f != null) {\n writer.writeBool(\n 15,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 16));\n if (f != null) {\n writer.writeBool(\n 16,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 22));\n if (f != null) {\n writer.writeBool(\n 22,\n f\n );\n }\n f = /** @type {!proto.TypenameMangling} */ (jspb.Message.getField(message, 17));\n if (f != null) {\n writer.writeEnum(\n 17,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 18));\n if (f != null) {\n writer.writeString(\n 18,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 19));\n if (f != null) {\n writer.writeString(\n 19,\n f\n );\n }\n f = /** @type {!proto.DescriptorSize} */ (jspb.Message.getField(message, 20));\n if (f != null) {\n writer.writeEnum(\n 20,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 23));\n if (f != null) {\n writer.writeBool(\n 23,\n f\n );\n }\n f = message.getIncludeList();\n if (f.length > 0) {\n writer.writeRepeatedString(\n 24,\n f\n );\n }\n f = message.getExcludeList();\n if (f.length > 0) {\n writer.writeRepeatedString(\n 26,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 25));\n if (f != null) {\n writer.writeString(\n 25,\n f\n );\n }\n f = /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (jspb.Message.getField(message, 27));\n if (f != null) {\n writer.writeEnum(\n 27,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 28));\n if (f != null) {\n writer.writeBool(\n 28,\n f\n );\n }\n};\n\n\n/**\n * optional int32 max_size = 1;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxSize = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxSize = function(value) {\n return jspb.Message.setField(this, 1, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxSize = function() {\n return jspb.Message.setField(this, 1, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxSize = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 max_length = 14;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxLength = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxLength = function(value) {\n return jspb.Message.setField(this, 14, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxLength = function() {\n return jspb.Message.setField(this, 14, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxLength = function() {\n return jspb.Message.getField(this, 14) != null;\n};\n\n\n/**\n * optional int32 max_count = 2;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxCount = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxCount = function(value) {\n return jspb.Message.setField(this, 2, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxCount = function() {\n return jspb.Message.setField(this, 2, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxCount = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional IntSize int_size = 7;\n * @return {!proto.IntSize}\n */\nproto.NanoPBOptions.prototype.getIntSize = function() {\n return /** @type {!proto.IntSize} */ (jspb.Message.getFieldWithDefault(this, 7, 0));\n};\n\n\n/**\n * @param {!proto.IntSize} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setIntSize = function(value) {\n return jspb.Message.setField(this, 7, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearIntSize = function() {\n return jspb.Message.setField(this, 7, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasIntSize = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional FieldType type = 3;\n * @return {!proto.FieldType}\n */\nproto.NanoPBOptions.prototype.getType = function() {\n return /** @type {!proto.FieldType} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.FieldType} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setType = function(value) {\n return jspb.Message.setField(this, 3, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearType = function() {\n return jspb.Message.setField(this, 3, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasType = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional bool long_names = 4;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getLongNames = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, true));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setLongNames = function(value) {\n return jspb.Message.setField(this, 4, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearLongNames = function() {\n return jspb.Message.setField(this, 4, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasLongNames = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional bool packed_struct = 5;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getPackedStruct = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackedStruct = function(value) {\n return jspb.Message.setField(this, 5, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackedStruct = function() {\n return jspb.Message.setField(this, 5, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackedStruct = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional bool packed_enum = 10;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getPackedEnum = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 10, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackedEnum = function(value) {\n return jspb.Message.setField(this, 10, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackedEnum = function() {\n return jspb.Message.setField(this, 10, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackedEnum = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional bool skip_message = 6;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSkipMessage = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSkipMessage = function(value) {\n return jspb.Message.setField(this, 6, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSkipMessage = function() {\n return jspb.Message.setField(this, 6, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSkipMessage = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional bool no_unions = 8;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getNoUnions = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 8, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setNoUnions = function(value) {\n return jspb.Message.setField(this, 8, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearNoUnions = function() {\n return jspb.Message.setField(this, 8, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasNoUnions = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional uint32 msgid = 9;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMsgid = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 9, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMsgid = function(value) {\n return jspb.Message.setField(this, 9, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMsgid = function() {\n return jspb.Message.setField(this, 9, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMsgid = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional bool anonymous_oneof = 11;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getAnonymousOneof = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 11, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setAnonymousOneof = function(value) {\n return jspb.Message.setField(this, 11, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearAnonymousOneof = function() {\n return jspb.Message.setField(this, 11, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasAnonymousOneof = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n/**\n * optional bool proto3 = 12;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getProto3 = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 12, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setProto3 = function(value) {\n return jspb.Message.setField(this, 12, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearProto3 = function() {\n return jspb.Message.setField(this, 12, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasProto3 = function() {\n return jspb.Message.getField(this, 12) != null;\n};\n\n\n/**\n * optional bool proto3_singular_msgs = 21;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getProto3SingularMsgs = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 21, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setProto3SingularMsgs = function(value) {\n return jspb.Message.setField(this, 21, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearProto3SingularMsgs = function() {\n return jspb.Message.setField(this, 21, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasProto3SingularMsgs = function() {\n return jspb.Message.getField(this, 21) != null;\n};\n\n\n/**\n * optional bool enum_to_string = 13;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getEnumToString = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 13, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setEnumToString = function(value) {\n return jspb.Message.setField(this, 13, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearEnumToString = function() {\n return jspb.Message.setField(this, 13, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasEnumToString = function() {\n return jspb.Message.getField(this, 13) != null;\n};\n\n\n/**\n * optional bool fixed_length = 15;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getFixedLength = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 15, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setFixedLength = function(value) {\n return jspb.Message.setField(this, 15, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearFixedLength = function() {\n return jspb.Message.setField(this, 15, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasFixedLength = function() {\n return jspb.Message.getField(this, 15) != null;\n};\n\n\n/**\n * optional bool fixed_count = 16;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getFixedCount = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 16, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setFixedCount = function(value) {\n return jspb.Message.setField(this, 16, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearFixedCount = function() {\n return jspb.Message.setField(this, 16, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasFixedCount = function() {\n return jspb.Message.getField(this, 16) != null;\n};\n\n\n/**\n * optional bool submsg_callback = 22;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSubmsgCallback = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 22, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSubmsgCallback = function(value) {\n return jspb.Message.setField(this, 22, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSubmsgCallback = function() {\n return jspb.Message.setField(this, 22, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSubmsgCallback = function() {\n return jspb.Message.getField(this, 22) != null;\n};\n\n\n/**\n * optional TypenameMangling mangle_names = 17;\n * @return {!proto.TypenameMangling}\n */\nproto.NanoPBOptions.prototype.getMangleNames = function() {\n return /** @type {!proto.TypenameMangling} */ (jspb.Message.getFieldWithDefault(this, 17, 0));\n};\n\n\n/**\n * @param {!proto.TypenameMangling} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMangleNames = function(value) {\n return jspb.Message.setField(this, 17, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMangleNames = function() {\n return jspb.Message.setField(this, 17, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMangleNames = function() {\n return jspb.Message.getField(this, 17) != null;\n};\n\n\n/**\n * optional string callback_datatype = 18;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getCallbackDatatype = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 18, \"pb_callback_t\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setCallbackDatatype = function(value) {\n return jspb.Message.setField(this, 18, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearCallbackDatatype = function() {\n return jspb.Message.setField(this, 18, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasCallbackDatatype = function() {\n return jspb.Message.getField(this, 18) != null;\n};\n\n\n/**\n * optional string callback_function = 19;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getCallbackFunction = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 19, \"pb_default_field_callback\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setCallbackFunction = function(value) {\n return jspb.Message.setField(this, 19, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearCallbackFunction = function() {\n return jspb.Message.setField(this, 19, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasCallbackFunction = function() {\n return jspb.Message.getField(this, 19) != null;\n};\n\n\n/**\n * optional DescriptorSize descriptorsize = 20;\n * @return {!proto.DescriptorSize}\n */\nproto.NanoPBOptions.prototype.getDescriptorsize = function() {\n return /** @type {!proto.DescriptorSize} */ (jspb.Message.getFieldWithDefault(this, 20, 0));\n};\n\n\n/**\n * @param {!proto.DescriptorSize} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setDescriptorsize = function(value) {\n return jspb.Message.setField(this, 20, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearDescriptorsize = function() {\n return jspb.Message.setField(this, 20, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasDescriptorsize = function() {\n return jspb.Message.getField(this, 20) != null;\n};\n\n\n/**\n * optional bool default_has = 23;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getDefaultHas = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 23, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setDefaultHas = function(value) {\n return jspb.Message.setField(this, 23, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearDefaultHas = function() {\n return jspb.Message.setField(this, 23, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasDefaultHas = function() {\n return jspb.Message.getField(this, 23) != null;\n};\n\n\n/**\n * repeated string include = 24;\n * @return {!Array}\n */\nproto.NanoPBOptions.prototype.getIncludeList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 24));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setIncludeList = function(value) {\n return jspb.Message.setField(this, 24, value || []);\n};\n\n\n/**\n * @param {string} value\n * @param {number=} opt_index\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.addInclude = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 24, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearIncludeList = function() {\n return this.setIncludeList([]);\n};\n\n\n/**\n * repeated string exclude = 26;\n * @return {!Array}\n */\nproto.NanoPBOptions.prototype.getExcludeList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 26));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setExcludeList = function(value) {\n return jspb.Message.setField(this, 26, value || []);\n};\n\n\n/**\n * @param {string} value\n * @param {number=} opt_index\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.addExclude = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 26, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearExcludeList = function() {\n return this.setExcludeList([]);\n};\n\n\n/**\n * optional string package = 25;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getPackage = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 25, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackage = function(value) {\n return jspb.Message.setField(this, 25, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackage = function() {\n return jspb.Message.setField(this, 25, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackage = function() {\n return jspb.Message.getField(this, 25) != null;\n};\n\n\n/**\n * optional google.protobuf.FieldDescriptorProto.Type type_override = 27;\n * @return {!proto.google.protobuf.FieldDescriptorProto.Type}\n */\nproto.NanoPBOptions.prototype.getTypeOverride = function() {\n return /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (jspb.Message.getFieldWithDefault(this, 27, 1));\n};\n\n\n/**\n * @param {!proto.google.protobuf.FieldDescriptorProto.Type} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setTypeOverride = function(value) {\n return jspb.Message.setField(this, 27, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearTypeOverride = function() {\n return jspb.Message.setField(this, 27, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasTypeOverride = function() {\n return jspb.Message.getField(this, 27) != null;\n};\n\n\n/**\n * optional bool sort_by_tag = 28;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSortByTag = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 28, true));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSortByTag = function(value) {\n return jspb.Message.setField(this, 28, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSortByTag = function() {\n return jspb.Message.setField(this, 28, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSortByTag = function() {\n return jspb.Message.getField(this, 28) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.FieldType = {\n FT_DEFAULT: 0,\n FT_CALLBACK: 1,\n FT_POINTER: 4,\n FT_STATIC: 2,\n FT_IGNORE: 3,\n FT_INLINE: 5\n};\n\n/**\n * @enum {number}\n */\nproto.IntSize = {\n IS_DEFAULT: 0,\n IS_8: 8,\n IS_16: 16,\n IS_32: 32,\n IS_64: 64\n};\n\n/**\n * @enum {number}\n */\nproto.TypenameMangling = {\n M_NONE: 0,\n M_STRIP_PACKAGE: 1,\n M_FLATTEN: 2,\n M_PACKAGE_INITIALS: 3\n};\n\n/**\n * @enum {number}\n */\nproto.DescriptorSize = {\n DS_AUTO: 0,\n DS_1: 1,\n DS_2: 2,\n DS_4: 4,\n DS_8: 8\n};\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbFileopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbFileopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbFileopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FileOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbFileopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FileOptions.extensions[1010] = proto.nanopbFileopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbMsgopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbMsgopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbMsgopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.MessageOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbMsgopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.MessageOptions.extensions[1010] = proto.nanopbMsgopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbEnumopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbEnumopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbEnumopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.EnumOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbEnumopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.EnumOptions.extensions[1010] = proto.nanopbEnumopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopb`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopb = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopb: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FieldOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopb,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FieldOptions.extensions[1010] = proto.nanopb;\n\ngoog.object.extend(exports, proto);\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nrequire(\"bootstrap\");\r\nrequire(\"./sass/main.scss\");\r\nrequire(\"./assets/images/favicon-32x32.png\");\r\nrequire(\"./js/custom.ts\");\r\nrequire(\"./js/proto/configuration_pb.js\");\r\n","\"use strict\";\r\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n}));\r\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n});\r\nvar __importStar = (this && this.__importStar) || function (mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n};\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar he = require('he');\r\n// var Promise = require('es6-promise').Promise;\r\n// @ts-ignore\r\nconst js_cookie_1 = __importDefault(require(\"js-cookie\"));\r\nvar protobuf = require(\"protobufjs\");\r\nconst bootstrap = __importStar(require(\"bootstrap\"));\r\n// Function to reset a StatusObject\r\nfunction resetStatusObject() {\r\n return {\r\n netmask: undefined,\r\n ip: undefined,\r\n ssid: undefined,\r\n urc: undefined,\r\n rssi: undefined,\r\n gw: undefined,\r\n bt_status: undefined,\r\n bt_sub_status: undefined,\r\n loaded: undefined,\r\n total: undefined,\r\n ota_pct: undefined,\r\n ota_dsc: undefined,\r\n recovery: undefined\r\n };\r\n}\r\nfunction resetNetworkConnection() {\r\n return {\r\n auth: undefined,\r\n pwd: undefined,\r\n dhcpname: undefined,\r\n Action: undefined,\r\n ip: undefined,\r\n ssid: undefined,\r\n rssi: undefined,\r\n gw: undefined,\r\n netmask: undefined,\r\n urc: 0\r\n };\r\n}\r\nwindow.hideSurrounding = function (obj) {\r\n $(obj).parent().parent().hide();\r\n};\r\nfunction hFlash() {\r\n // reset file upload selection if any;\r\n $('#flashfilename').val = null;\r\n flashState.StartOTA();\r\n}\r\nwindow.hFlash = function () {\r\n hFlash();\r\n};\r\nfunction handleReboot(link) {\r\n if (link == 'reboot_ota') {\r\n $('#reboot_ota_nav').removeClass('active').prop(\"disabled\", true);\r\n delayReboot(500, '', 'reboot_ota');\r\n }\r\n else {\r\n $('#reboot_nav').removeClass('active');\r\n delayReboot(500, '', link);\r\n }\r\n}\r\nwindow.handleReboot = function (link) {\r\n handleReboot(link);\r\n};\r\nObject.assign(String.prototype, {\r\n format(...args) {\r\n return this.replace(/{(\\d+)}/g, function (match, number) {\r\n const index = parseInt(number, 10); // Convert string to number\r\n return typeof args[index] !== 'undefined' ? args[index] : match;\r\n });\r\n },\r\n});\r\nObject.assign(String.prototype, {\r\n encodeHTML() {\r\n return he.encode(this).replace(/\\n/g, '
');\r\n },\r\n});\r\nObject.assign(Date.prototype, {\r\n toLocalShort() {\r\n const opt = { dateStyle: 'short', timeStyle: 'short' };\r\n return this.toLocaleString(undefined, opt);\r\n },\r\n});\r\nfunction get_control_option_value(obj) {\r\n let ctrl, id, val, opt;\r\n if (typeof (obj) === 'string') {\r\n id = obj;\r\n ctrl = $(`#${id}`);\r\n }\r\n else {\r\n id = $(obj).attr('id');\r\n ctrl = $(obj);\r\n }\r\n if (ctrl.attr('type') === 'checkbox') {\r\n opt = ctrl.prop('checked') ? id.replace('cmd_opt_', '') : '';\r\n val = true;\r\n }\r\n else {\r\n opt = id.replace('cmd_opt_', '');\r\n val = ctrl.val();\r\n if (typeof val === 'string') {\r\n val = `${val.includes(\" \") ? '\"' : ''}${val}${val.includes(\" \") ? '\"' : ''}`;\r\n }\r\n else if (typeof val !== 'number') {\r\n val = val.toString();\r\n }\r\n }\r\n return { opt, val };\r\n}\r\nfunction handleNVSVisible() {\r\n let nvs_previous_checked = isEnabled(js_cookie_1.default.get(\"show-nvs\"));\r\n const checkBoxElement = $('input#show-nvs')[0];\r\n checkBoxElement.checked = nvs_previous_checked;\r\n if (checkBoxElement.checked || recovery) {\r\n $('*[href*=\"-nvs\"]').show();\r\n }\r\n else {\r\n $('*[href*=\"-nvs\"]').hide();\r\n }\r\n}\r\nfunction concatenateOptions(options) {\r\n let commandLine = ' ';\r\n for (const [option, value] of Object.entries(options)) {\r\n if (option !== 'n' && option !== 'o') {\r\n commandLine += `-${option} `;\r\n if (value !== true) {\r\n commandLine += `${value} `;\r\n }\r\n }\r\n }\r\n return commandLine;\r\n}\r\nfunction isEnabled(val) {\r\n const matchResult = val && typeof val === 'string' && val.match(\"[Yy1]\");\r\n return matchResult && matchResult !== null && matchResult.length > 0;\r\n}\r\nvar NVSType;\r\n(function (NVSType) {\r\n NVSType[NVSType[\"NVS_TYPE_U8\"] = 1] = \"NVS_TYPE_U8\";\r\n NVSType[NVSType[\"NVS_TYPE_I8\"] = 17] = \"NVS_TYPE_I8\";\r\n NVSType[NVSType[\"NVS_TYPE_U16\"] = 2] = \"NVS_TYPE_U16\";\r\n NVSType[NVSType[\"NVS_TYPE_I16\"] = 18] = \"NVS_TYPE_I16\";\r\n NVSType[NVSType[\"NVS_TYPE_U32\"] = 4] = \"NVS_TYPE_U32\";\r\n NVSType[NVSType[\"NVS_TYPE_I32\"] = 20] = \"NVS_TYPE_I32\";\r\n NVSType[NVSType[\"NVS_TYPE_U64\"] = 8] = \"NVS_TYPE_U64\";\r\n NVSType[NVSType[\"NVS_TYPE_I64\"] = 24] = \"NVS_TYPE_I64\";\r\n NVSType[NVSType[\"NVS_TYPE_STR\"] = 33] = \"NVS_TYPE_STR\";\r\n NVSType[NVSType[\"NVS_TYPE_BLOB\"] = 66] = \"NVS_TYPE_BLOB\";\r\n NVSType[NVSType[\"NVS_TYPE_ANY\"] = 255] = \"NVS_TYPE_ANY\";\r\n})(NVSType || (NVSType = {}));\r\n;\r\nconst btIcons = {\r\n bt_playing: { label: '', icon: 'media_bluetooth_on' },\r\n bt_disconnected: { label: '', icon: 'media_bluetooth_off' },\r\n bt_neutral: { label: '', icon: 'bluetooth' },\r\n bt_connecting: { label: '', icon: 'bluetooth_searching' },\r\n bt_connected: { label: '', icon: 'bluetooth_connected' },\r\n bt_disabled: { label: '', icon: 'bluetooth_disabled' },\r\n play_arrow: { label: '', icon: 'play_circle_filled' },\r\n pause: { label: '', icon: 'pause_circle' },\r\n stop: { label: '', icon: 'stop_circle' },\r\n '': { label: '', icon: '' }\r\n};\r\nconst batIcons = [\r\n { icon: \"battery_0_bar\", label: '▪', ranges: [{ f: 5.8, t: 6.8 }, { f: 8.8, t: 10.2 }] },\r\n { icon: \"battery_2_bar\", label: '▪▪', ranges: [{ f: 6.8, t: 7.4 }, { f: 10.2, t: 11.1 }] },\r\n { icon: \"battery_3_bar\", label: '▪▪▪', ranges: [{ f: 7.4, t: 7.5 }, { f: 11.1, t: 11.25 }] },\r\n { icon: \"battery_4_bar\", label: '▪▪▪▪', ranges: [{ f: 7.5, t: 7.8 }, { f: 11.25, t: 11.7 }] }\r\n];\r\nconst btStateIcons = [\r\n { desc: 'Idle', sub: ['bt_neutral'] },\r\n { desc: 'Discovering', sub: ['bt_connecting'] },\r\n { desc: 'Discovered', sub: ['bt_connecting'] },\r\n { desc: 'Unconnected', sub: ['bt_disconnected'] },\r\n { desc: 'Connecting', sub: ['bt_connecting'] },\r\n {\r\n desc: 'Connected',\r\n sub: ['bt_connected', 'play_arrow', 'bt_playing', 'pause', 'stop'],\r\n },\r\n { desc: 'Disconnecting', sub: ['bt_disconnected'] },\r\n];\r\nconst connectReturnCode = {\r\n OK: 0,\r\n FAIL: 1,\r\n DISC: 2,\r\n LOST: 3,\r\n RESTORE: 4,\r\n ETH: 5\r\n};\r\nconst taskStates = [\r\n 'eRunning',\r\n /*! < A task is querying the state of itself, so must be running. */\r\n 'eReady',\r\n /*! < The task being queried is in a read or pending ready list. */\r\n 'eBlocked',\r\n /*! < The task being queried is in the Blocked state. */\r\n 'eSuspended',\r\n /*! < The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */\r\n 'eDeleted'\r\n];\r\nlet flashState = {\r\n NONE: 0,\r\n REBOOT_TO_RECOVERY: 2,\r\n SET_FWURL: 5,\r\n FLASHING: 6,\r\n DONE: 7,\r\n UPLOADING: 8,\r\n ERROR: 9,\r\n UPLOADCOMPLETE: 10,\r\n _state: -1,\r\n olderRecovery: false,\r\n statusText: '',\r\n flashURL: '',\r\n flashFileName: '',\r\n statusPercent: 0,\r\n Completed: false,\r\n recovery: false,\r\n prevRecovery: false,\r\n updateModal: new bootstrap.Modal(document.getElementById('otadiv'), {}),\r\n reset: function () {\r\n this.olderRecovery = false;\r\n this.statusText = '';\r\n this.statusPercent = -1;\r\n this.flashURL = '';\r\n this.flashFileName = undefined;\r\n this.UpdateProgress();\r\n $('#rTable tr.release').removeClass('table-success table-warning');\r\n $('.flact').prop('disabled', false);\r\n $('#flashfilename')[0].value = null;\r\n $('#fw-url-input')[0].value = null;\r\n if (!this.isStateError()) {\r\n $('span#flash-status').html('');\r\n $('#fwProgressLabel').parent().removeClass('bg-danger');\r\n }\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n isStateUploadComplete: function () {\r\n return this._state == this.UPLOADCOMPLETE;\r\n },\r\n isStateError: function () {\r\n return this._state == this.ERROR;\r\n },\r\n isStateNone: function () {\r\n return this._state == this.NONE;\r\n },\r\n isStateRebootRecovery: function () {\r\n return this._state == this.REBOOT_TO_RECOVERY;\r\n },\r\n isStateSetUrl: function () {\r\n return this._state == this.SET_FWURL;\r\n },\r\n isStateFlashing: function () {\r\n return this._state == this.FLASHING;\r\n },\r\n isStateDone: function () {\r\n return this._state == this.DONE;\r\n },\r\n isStateUploading: function () {\r\n return this._state == this.UPLOADING;\r\n },\r\n init: function () {\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n SetStateError: function () {\r\n this._state = this.ERROR;\r\n $('#fwProgressLabel').parent().addClass('bg-danger');\r\n return this;\r\n },\r\n SetStateNone: function () {\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n SetStateRebootRecovery: function () {\r\n this._state = this.REBOOT_TO_RECOVERY;\r\n // Reboot system to recovery mode\r\n this.SetStatusText('Starting recovery mode.');\r\n $.ajax({\r\n url: '/recovery.zzz',\r\n context: this,\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n var _a;\r\n this.setOTAError(`Unexpected error while trying to restart to recovery. (status=${(_a = xhr.status) !== null && _a !== void 0 ? _a : ''}, error=${thrownError !== null && thrownError !== void 0 ? thrownError : ''} ) `);\r\n },\r\n complete: function (response) {\r\n this.SetStatusText('Waiting for system to boot.');\r\n },\r\n });\r\n return this;\r\n },\r\n SetStateSetUrl: function () {\r\n this._state = this.SET_FWURL;\r\n this.statusText = 'Sending firmware download location.';\r\n let confData = {\r\n fwurl: {\r\n value: this.flashURL,\r\n type: 33,\r\n }\r\n };\r\n post_config(confData);\r\n return this;\r\n },\r\n SetStateFlashing: function () {\r\n this._state = this.FLASHING;\r\n return this;\r\n },\r\n SetStateDone: function () {\r\n this._state = this.DONE;\r\n this.reset();\r\n return this;\r\n },\r\n SetStateUploading: function () {\r\n this._state = this.UPLOADING;\r\n return this.SetStatusText('Sending file to device.');\r\n },\r\n SetStateUploadComplete: function () {\r\n this._state = this.UPLOADCOMPLETE;\r\n return this;\r\n },\r\n isFlashExecuting: function () {\r\n return true === (this._state != this.UPLOADING && (this.statusText !== '' || this.statusPercent >= 0));\r\n },\r\n toString: function () {\r\n let keys = Object.keys(this);\r\n return keys.find(x => this[x] === this._state);\r\n },\r\n setOTATargets: function () {\r\n this.flashURL = '';\r\n this.flashFileName = '';\r\n this.flashURL = $('#fw-url-input').val();\r\n let fileInputctrl = $('#flashfilename')[0];\r\n let fileInput = fileInputctrl.files;\r\n if (fileInput.length > 0) {\r\n this.flashFileName = fileInput[0];\r\n }\r\n if (this.flashFileName.length == 0 && this.flashURL.length == 0) {\r\n this.setOTAError('Invalid url or file. Cannot start OTA');\r\n }\r\n return this;\r\n },\r\n setOTAError: function (message) {\r\n this.SetStateError().SetStatusPercent(0).SetStatusText(message).reset();\r\n return this;\r\n },\r\n ShowDialog: function () {\r\n if (!this.isStateNone()) {\r\n this.updateModal.show();\r\n $('.flact').prop('disabled', true);\r\n }\r\n return this;\r\n },\r\n SetStatusPercent: function (pct) {\r\n var pctChanged = (this.statusPercent != pct);\r\n this.statusPercent = pct;\r\n if (pctChanged) {\r\n if (!this.isStateUploading() && !this.isStateFlashing()) {\r\n this.SetStateFlashing();\r\n }\r\n if (pct == 100) {\r\n if (this.isStateFlashing()) {\r\n this.SetStateDone();\r\n }\r\n else if (this.isStateUploading()) {\r\n this.statusPercent = 0;\r\n this.SetStateFlashing();\r\n }\r\n }\r\n this.UpdateProgress().ShowDialog();\r\n }\r\n return this;\r\n },\r\n SetStatusText: function (txt) {\r\n var changed = (this.statusText != txt);\r\n this.statusText = txt;\r\n if (changed) {\r\n $('span#flash-status').html(this.statusText);\r\n this.ShowDialog();\r\n }\r\n return this;\r\n },\r\n UpdateProgress: function () {\r\n $('.progress-bar')\r\n .css('width', this.statusPercent + '%')\r\n .attr('aria-valuenow', this.statusPercent)\r\n .text(this.statusPercent + '%');\r\n $('.progress-bar').html((this.isStateDone() ? 100 : this.statusPercent) + '%');\r\n return this;\r\n },\r\n StartOTA: function () {\r\n this.logEvent(this.StartOTA.name);\r\n $('#fwProgressLabel').parent().removeClass('bg-danger');\r\n this.setOTATargets();\r\n if (this.isStateError()) {\r\n return this;\r\n }\r\n if (!recovery) {\r\n this.SetStateRebootRecovery();\r\n }\r\n else {\r\n this.SetStateFlashing().TargetReadyStartOTA();\r\n }\r\n return this;\r\n },\r\n UploadLocalFile: function () {\r\n this.SetStateUploading();\r\n const xhttp = new XMLHttpRequest();\r\n var boundHandleUploadProgressEvent = this.HandleUploadProgressEvent.bind(this);\r\n var boundsetOTAError = this.setOTAError.bind(this);\r\n xhttp.upload.addEventListener(\"progress\", boundHandleUploadProgressEvent, false);\r\n xhttp.onreadystatechange = function () {\r\n if (xhttp.readyState === 4) {\r\n if (xhttp.status === 0 || xhttp.status === 404) {\r\n boundsetOTAError(`Upload Failed. Recovery version might not support uploading. Please use web update instead.`);\r\n }\r\n }\r\n };\r\n xhttp.open('POST', '/flash.zzz', true);\r\n xhttp.send(this.flashFileName);\r\n },\r\n TargetReadyStartOTA: function () {\r\n if (recovery && this.prevRecovery && !this.isStateRebootRecovery() && !this.isStateFlashing()) {\r\n // this should only execute once, while being in a valid state\r\n return this;\r\n }\r\n this.logEvent(this.TargetReadyStartOTA.name);\r\n if (!recovery) {\r\n console.error('Event TargetReadyStartOTA fired in the wrong mode ');\r\n return this;\r\n }\r\n this.prevRecovery = true;\r\n if (this.flashFileName !== '') {\r\n this.UploadLocalFile();\r\n }\r\n else if (this.flashURL != '') {\r\n this.SetStateSetUrl();\r\n }\r\n else {\r\n this.setOTAError('Invalid URL or file name while trying to start the OTa process');\r\n }\r\n },\r\n HandleUploadProgressEvent: function (data) {\r\n this.logEvent(this.HandleUploadProgressEvent.name);\r\n this.SetStateUploading().SetStatusPercent(Math.round(data.loaded / data.total * 100)).SetStatusText('Uploading file to device');\r\n },\r\n EventTargetStatus: function (data) {\r\n var _a, _b;\r\n if (!this.isStateNone()) {\r\n this.logEvent(this.EventTargetStatus.name);\r\n }\r\n if ((_a = data.ota_pct) !== null && _a !== void 0 ? _a : -1 >= 0) {\r\n this.olderRecovery = true;\r\n this.SetStatusPercent(data.ota_pct);\r\n }\r\n if (((_b = data.ota_dsc) !== null && _b !== void 0 ? _b : '') != '') {\r\n this.olderRecovery = true;\r\n this.SetStatusText(data.ota_dsc);\r\n }\r\n if (data.recovery != undefined) {\r\n this.recovery = data.recovery === 1 ? true : false;\r\n }\r\n if (this.isStateRebootRecovery() && this.recovery) {\r\n this.TargetReadyStartOTA();\r\n }\r\n },\r\n EventOTAMessageClass: function (data) {\r\n this.logEvent(this.EventOTAMessageClass.name);\r\n var otaData = JSON.parse(data);\r\n this.SetStatusPercent(otaData.ota_pct).SetStatusText(otaData.ota_dsc);\r\n },\r\n logEvent: function (fun) {\r\n console.log(`${fun}, flash state ${this.toString()}, recovery: ${this.recovery}, ota pct: ${this.statusPercent}, ota desc: ${this.statusText}`);\r\n }\r\n};\r\nlet presetsloaded = false;\r\nlet is_i2c_locked = false;\r\nlet statusInterval = 2000;\r\nlet messageInterval = 2500;\r\nfunction post_config(data) {\r\n let confPayload = {\r\n timestamp: Date.now(),\r\n config: data\r\n };\r\n $.ajax({\r\n url: '/config.zzz',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(confPayload),\r\n error: handleExceptionResponse,\r\n });\r\n}\r\nfunction parseSqueezeliteCommandLine(commandLine) {\r\n const options = {};\r\n let output, name;\r\n let otherValues = '';\r\n const argRegex = /(\"[^\"]+\"|'[^']+'|\\S+)/g;\r\n const args = commandLine.match(argRegex) || [];\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n if (arg.startsWith('-')) {\r\n const option = arg.slice(1);\r\n if (option === '') {\r\n otherValues += args.slice(i).join(' ');\r\n break;\r\n }\r\n let value = \"\";\r\n if (i + 1 < args.length && !args[i + 1].startsWith('-')) {\r\n value = args[i + 1].replace(/\"/g, '').replace(/'/g, '');\r\n i++;\r\n }\r\n options[option] = value;\r\n }\r\n else {\r\n otherValues += arg + ' ';\r\n }\r\n i++;\r\n }\r\n otherValues = otherValues.trim();\r\n output = getOutput(options);\r\n name = getName(options);\r\n let otherOptions = { btname: null, n: null };\r\n // Assign 'o' and 'n' options to otherOptions if present\r\n if (options.o && output.toUpperCase() === 'BT') {\r\n let temp = parseSqueezeliteCommandLine(options.o);\r\n if (temp.name) {\r\n otherOptions.btname = temp.name;\r\n }\r\n delete options.o;\r\n }\r\n if (options.n) {\r\n otherOptions.n = options.n;\r\n delete options.n;\r\n }\r\n return { name, output, options, otherValues, otherOptions };\r\n}\r\nfunction getOutput(options) {\r\n let output;\r\n if (options.o) {\r\n output = options.o.replace(/\"/g, '').replace(/'/g, '');\r\n /* set output as the first alphanumerical word in the command line */\r\n if (output.indexOf(' ') > 0) {\r\n output = output.substring(0, output.indexOf(' '));\r\n }\r\n }\r\n return output;\r\n}\r\nfunction getName(options) {\r\n let name;\r\n /* if n option present, assign to name variable */\r\n if (options.n) {\r\n name = options.n.replace(/\"/g, '').replace(/'/g, '');\r\n }\r\n return name;\r\n}\r\nfunction isConnected() {\r\n return ConnectedTo != undefined && ConnectedTo.hasOwnProperty('ip') && ConnectedTo.ip != '0.0.0.0' && ConnectedTo.ip != '';\r\n}\r\nfunction getIcon(icons) {\r\n return isConnected() ? icons.icon : icons.label;\r\n}\r\nfunction handlebtstate(data) {\r\n var _a;\r\n let icon = { label: '', icon: '' };\r\n let tt = '';\r\n if (data.bt_status !== undefined && data.bt_sub_status !== undefined) {\r\n const iconIndex = (_a = btStateIcons[data.bt_status]) === null || _a === void 0 ? void 0 : _a.sub[data.bt_sub_status];\r\n if (iconIndex) {\r\n icon = btIcons[iconIndex];\r\n tt = btStateIcons[data.bt_status].desc;\r\n }\r\n else {\r\n icon = btIcons.bt_connected;\r\n tt = 'Output status';\r\n }\r\n }\r\n $('#o_type').attr('title', tt);\r\n $('#o_bt').html(isConnected() ? icon.label : icon.icon); // Note: Assuming `isConnected()` is defined elsewhere.\r\n}\r\nfunction handleTemplateTypeRadio(outtype) {\r\n $('#o_type').children('span').css({ display: 'none' });\r\n let changed = false;\r\n if (outtype !== output) {\r\n changed = true;\r\n output = outtype;\r\n }\r\n $('#' + output).prop('checked', true);\r\n $('#o_' + output).css({ display: 'inline' });\r\n if (changed) {\r\n Object.entries(commandDefaults[output]).forEach(([key, value]) => {\r\n $(`#cmd_opt_${key}`).val(value);\r\n });\r\n }\r\n}\r\nfunction handleExceptionResponse(xhr, _ajaxOptions, thrownError) {\r\n console.log(xhr.status);\r\n console.log(thrownError);\r\n if (thrownError !== '') {\r\n showLocalMessage(thrownError, 'MESSAGING_ERROR');\r\n }\r\n}\r\nfunction HideCmdMessage(cmdname) {\r\n $('#toast_' + cmdname)\r\n .removeClass('table-success')\r\n .removeClass('table-warning')\r\n .removeClass('table-danger')\r\n .addClass('table-success')\r\n .removeClass('show');\r\n $('#msg_' + cmdname).html('');\r\n}\r\nfunction showCmdMessage(cmdname, msgtype, msgtext, append = false) {\r\n let color = 'table-success';\r\n if (msgtype === 'MESSAGING_WARNING') {\r\n color = 'table-warning';\r\n }\r\n else if (msgtype === 'MESSAGING_ERROR') {\r\n color = 'table-danger';\r\n }\r\n $('#toast_' + cmdname)\r\n .removeClass('table-success')\r\n .removeClass('table-warning')\r\n .removeClass('table-danger')\r\n .addClass(color)\r\n .addClass('show');\r\n let escapedtext = msgtext\r\n .substring(0, msgtext.length - 1)\r\n .encodeHTML()\r\n .replace(/\\n/g, '
');\r\n escapedtext =\r\n ($('#msg_' + cmdname).html().length > 0 && append\r\n ? $('#msg_' + cmdname).html() + '
'\r\n : '') + escapedtext;\r\n $('#msg_' + cmdname).html(escapedtext);\r\n}\r\nlet releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';\r\nlet recovery = false;\r\nlet messagesHeld = false;\r\nlet commandBTSinkName = '';\r\nconst commandHeader = 'squeezelite ';\r\nconst commandDefaults = {\r\n i2s: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"96000\", o: \"I2S\" },\r\n spdif: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"48000\", o: \"SPDIF\" },\r\n bt: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"44100\", o: \"BT\" },\r\n};\r\nlet validOptions = {\r\n codecs: ['flac', 'pcm', 'mp3', 'ogg', 'aac', 'wma', 'alac', 'dsd', 'mad', 'mpg']\r\n};\r\n//let blockFlashButton = false;\r\nlet apList = null;\r\n//let selectedSSID = '';\r\n//let checkStatusInterval = null;\r\nlet messagecount = 0;\r\nlet messageseverity = 'MESSAGING_INFO';\r\nlet SystemConfig;\r\nlet LastCommandsState = NaN;\r\nvar output = '';\r\nlet hostName = '';\r\nlet versionName = 'Squeezelite-ESP32';\r\nlet prevmessage = '';\r\nlet project_name = versionName;\r\nlet depth = 16;\r\nlet board_model = '';\r\nlet platform_name = versionName;\r\nlet preset_name = '';\r\nlet ConnectedTo;\r\nlet ConnectingToSSID;\r\nlet lmsBaseUrl = \"\";\r\nlet prevLMSIP = '';\r\nconst ConnectingToActions = {\r\n 'CONN': 0, 'MAN': 1, 'STS': 2,\r\n};\r\nfunction delay(promise, duration) {\r\n return new Promise((resolve, reject) => {\r\n promise.then(value => setTimeout(() => resolve(value), duration), reason => setTimeout(() => reject(reason), duration));\r\n });\r\n}\r\nfunction getConfigJson(slimMode) {\r\n const config = {};\r\n $('input.nvs').each(function (_index, element) {\r\n const entry = element;\r\n const nvsTypeAttr = entry.attributes.getNamedItem('nvs_type');\r\n if (!slimMode && nvsTypeAttr) {\r\n const nvsType = parseInt(nvsTypeAttr.value, 10);\r\n if (entry.id !== '') {\r\n const value = (nvsType <= NVSType.NVS_TYPE_I64) ? parseInt(entry.value, 10) : entry.value;\r\n config[entry.id] = {\r\n value: value,\r\n type: nvsType,\r\n };\r\n }\r\n }\r\n else {\r\n if (entry.id !== '') {\r\n config[entry.id] = entry.value;\r\n }\r\n }\r\n });\r\n // In the following, we assume that `#nvs-new-key` and `#nvs-new-value`\r\n // correspond to input elements and thus their values are always strings.\r\n const key = $('#nvs-new-key').val();\r\n const val = $('#nvs-new-value').val();\r\n if (key && key !== '') {\r\n if (!slimMode) {\r\n config[key] = {\r\n value: val,\r\n type: NVSType.NVS_TYPE_I8, // Assuming a default type here\r\n };\r\n }\r\n else {\r\n config[key] = val;\r\n }\r\n }\r\n return config;\r\n}\r\nfunction handleHWPreset(allfields, reboot) {\r\n const selJson = JSON.parse(allfields[0].value);\r\n const cmd = allfields[0].getAttribute(\"cmdname\");\r\n console.log(`selected model: ${selJson.name}`);\r\n let confPayload = {\r\n timestamp: Date.now(),\r\n config: { model_config: { value: selJson.name, type: 33 } } // Assuming 33 is some sort of default type\r\n };\r\n for (const [name, value] of Object.entries(selJson.config)) {\r\n const storedval = (typeof value === 'string' || value instanceof String) ? value : JSON.stringify(value);\r\n confPayload.config[name] = {\r\n value: storedval.toString(),\r\n type: NVSType.NVS_TYPE_STR,\r\n };\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Setting ${name}=${storedval} `, true);\r\n }\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Committing `, true);\r\n $.ajax({\r\n url: '/config.zzz',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(confPayload),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, _ajaxOptions, thrownError);\r\n showCmdMessage(cmd, 'MESSAGING_ERROR', `Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status} `, true);\r\n },\r\n success: function (response) {\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Saving complete `, true);\r\n console.log(response);\r\n if (reboot) {\r\n delayReboot(2500, cmd);\r\n }\r\n },\r\n });\r\n}\r\n// pull json file from https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/b462691f69e2ad31ac95c547af6ec97afb0f53db/squeezelite-esp32-presets.json and\r\nfunction loadPresets() {\r\n if ($(\"#cfg-hw-preset-model_config\").length == 0)\r\n return;\r\n if (presetsloaded)\r\n return;\r\n presetsloaded = true;\r\n $('#cfg-hw-preset-model_config').html('');\r\n $.getJSON('https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/', { _: new Date().getTime() }, function (data) {\r\n $.each(data, function (key, val) {\r\n $('#cfg-hw-preset-model_config').append(``);\r\n if (preset_name !== '' && preset_name == val.name) {\r\n $('#cfg-hw-preset-model_config').val(preset_name);\r\n }\r\n });\r\n if (preset_name !== '') {\r\n $('#prev_preset').show().val(preset_name);\r\n }\r\n }).fail(function (jqxhr, textStatus, error) {\r\n const err = textStatus + ', ' + error;\r\n console.log('Request Failed: ' + err);\r\n });\r\n}\r\nfunction delayReboot(duration, cmdname, ota = 'reboot') {\r\n const url = `/${ota}.json`;\r\n $('tbody#tasks').empty();\r\n $('#tasks_sect').css('visibility', 'collapse');\r\n delay(Promise.resolve({ cmdname: cmdname, url: url }), duration)\r\n .then(function (data) {\r\n // Your existing logic here\r\n console.log('now triggering reboot');\r\n $(\"button[onclick*='handleReboot']\").addClass('rebooting');\r\n $.ajax({\r\n // Your existing AJAX call setup here\r\n complete: function () {\r\n console.log('reboot call completed');\r\n delay(Promise.resolve(data), 6000)\r\n .then(function (rdata) {\r\n // Your existing logic here\r\n });\r\n },\r\n });\r\n });\r\n}\r\nfunction saveAutoexec1(apply) {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Saving.\\n', false);\r\n let commandLine = `${commandHeader} -o ${output} `;\r\n $('.sqcmd').each(function () {\r\n let { opt, val } = get_control_option_value($(this));\r\n if ((opt && opt.length > 0) && typeof (val) == 'boolean' || typeof (val) === 'string' && val.length > 0) {\r\n const optStr = opt === ':' ? opt : (` -${opt} `);\r\n val = typeof (val) == 'boolean' ? '' : val;\r\n commandLine += `${optStr} ${val}`;\r\n }\r\n });\r\n const resample = $('#cmd_opt_R input[name=resample]:checked');\r\n if (resample.length > 0 && resample.attr('suffix') !== '') {\r\n commandLine += resample.attr('suffix');\r\n // now check resample_i option and if checked, add suffix to command line\r\n if ($('#resample_i').is(\":checked\") && resample.attr('aint') == 'true') {\r\n commandLine += $('#resample_i').attr('suffix');\r\n }\r\n }\r\n if (output === 'bt') {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Remember to configure the Bluetooth audio device name.\\n', true);\r\n }\r\n // commandLine += concatenateOptions(options);\r\n const data = {\r\n timestamp: Date.now(),\r\n config: {\r\n autoexec1: { value: commandLine, type: NVSType.NVS_TYPE_STR }\r\n }\r\n };\r\n $.ajax({\r\n url: '/config.zzz',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(data),\r\n error: handleExceptionResponse,\r\n complete: function (response) {\r\n if (response.responseText &&\r\n JSON.parse(response.responseText).result === 'OK') {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Done.\\n', true);\r\n if (apply) {\r\n delayReboot(1500, 'cfg-audio-tmpl');\r\n }\r\n }\r\n else if (JSON.parse(response.responseText).result) {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_WARNING', JSON.parse(response.responseText).Result + '\\n', true);\r\n }\r\n else {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_ERROR', response.statusText + '\\n');\r\n }\r\n console.log(response.responseText);\r\n },\r\n });\r\n console.log('sent data:', JSON.stringify(data));\r\n}\r\nfunction handleDisconnect() {\r\n $.ajax({\r\n url: '/connect.zzz',\r\n dataType: 'text',\r\n method: 'DELETE',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n });\r\n}\r\nfunction setPlatformFilter(val) {\r\n if ($('.upf').filter(function () { return $(this).text().toUpperCase() === val.toUpperCase(); }).length > 0) {\r\n $('#splf').val(val).trigger('input');\r\n return true;\r\n }\r\n return false;\r\n}\r\nfunction handleConnect() {\r\n ConnectingToSSID.ssid = $('#manual_ssid').val().toString();\r\n ConnectingToSSID.pwd = $('#manual_pwd').val().toString();\r\n ConnectingToSSID.dhcpname = $('#dhcp-name2').val().toString();\r\n $(\"*[class*='connecting']\").hide();\r\n $('#ssid-wait').text(ConnectingToSSID.ssid);\r\n $('.connecting').show();\r\n $.ajax({\r\n url: '/connect.zzz',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n ssid: ConnectingToSSID.ssid,\r\n pwd: ConnectingToSSID.pwd\r\n }),\r\n error: handleExceptionResponse,\r\n });\r\n // now we can re-set the intervals regardless of result\r\n}\r\nfunction renderError(opt, error) {\r\n const fieldname = `cmd_opt_${opt}`;\r\n let errorFieldName = `${fieldname}-error`;\r\n let errorField = $(`#${errorFieldName}`);\r\n let field = $(`#${fieldname}`);\r\n if (!errorField || errorField.length == 0) {\r\n field.after(`
`);\r\n errorField = $(`#${errorFieldName}`);\r\n }\r\n if (error.length == 0) {\r\n errorField.hide();\r\n field.removeClass('is-invalid');\r\n field.addClass('is-valid');\r\n errorField.text('');\r\n }\r\n else {\r\n errorField.show();\r\n errorField.text(error);\r\n field.removeClass('is-valid');\r\n field.addClass('is-invalid');\r\n }\r\n return errorField;\r\n}\r\n$(function () {\r\n $('.material-icons').each(function (_index, entry) {\r\n entry.setAttribute('data-icon', entry.textContent || '');\r\n });\r\n setIcons(true);\r\n handleNVSVisible();\r\n flashState.init();\r\n $('#fw-url-input').on('input', function () {\r\n const stringVal = $(this).val().toString();\r\n if (stringVal.length > 8 && (stringVal.startsWith('http://') || stringVal.startsWith('https://'))) {\r\n $('#start-flash').show();\r\n }\r\n else {\r\n $('#start-flash').hide();\r\n }\r\n });\r\n $('.upSrch').on('input', function () {\r\n const inputField = this;\r\n const val = inputField.value;\r\n $(\"#rTable tr\").removeClass(inputField.id + '_hide');\r\n if (val.length > 0) {\r\n $(`#rTable td:nth-child(${$(inputField).parent().index() + 1})`).filter(function () {\r\n return !$(this).text().toUpperCase().includes(val.toUpperCase());\r\n }).parent().addClass(this.id + '_hide');\r\n }\r\n $('[class*=\"_hide\"]').hide();\r\n $('#rTable tr').not('[class*=\"_hide\"]').show();\r\n });\r\n setTimeout(refreshAP, 1500);\r\n /* add validation for cmd_opt_c, which accepts a comma separated list.\r\n getting known codecs from validOptions.codecs array\r\n use bootstrap classes to highlight the error with an overlay message */\r\n $('#options input').on('input', function () {\r\n const inputField = this;\r\n const { opt, val } = get_control_option_value(this);\r\n if (opt === 'c' || opt === 'e') {\r\n const fieldname = `cmd_opt_${opt}_codec-error`;\r\n const values = val.toString().split(',').map(function (item) {\r\n return item.trim();\r\n });\r\n /* get a list of invalid codecs */\r\n const invalid = values.filter(function (item) {\r\n return !validOptions.codecs.includes(item);\r\n });\r\n renderError(opt, invalid.length > 0 ? `Invalid codec(s) ${invalid.join(', ')}` : '');\r\n }\r\n /* add validation for cmd_opt_m, which accepts a mac_address */\r\n if (opt === 'm') {\r\n const mac_regex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;\r\n renderError(opt, mac_regex.test(val.toString()) ? '' : 'Invalid MAC address');\r\n }\r\n if (opt === 'r') {\r\n const rateRegex = /^(\\d+\\.?\\d*|\\.\\d+)-(\\d+\\.?\\d*|\\.\\d+)$|^(\\d+\\.?\\d*)$|^(\\d+\\.?\\d*,)+\\d+\\.?\\d*$/;\r\n renderError(opt, rateRegex.test(val.toString()) ? '' : `Invalid rate(s) ${val}. Acceptable format: |-|,,`);\r\n }\r\n });\r\n $('#WifiConnectDialog')[0].addEventListener('shown.bs.modal', function (event) {\r\n $(\"*[class*='connecting']\").hide();\r\n if (event === null || event === void 0 ? void 0 : event.relatedTarget) {\r\n ConnectingToSSID.Action = ConnectingToActions.CONN;\r\n if ($(event.relatedTarget).children('td:eq(1)').text() == ConnectedTo.ssid) {\r\n ConnectingToSSID.Action = ConnectingToActions.STS;\r\n }\r\n else {\r\n if (!$(event.relatedTarget).is(':last-child')) {\r\n ConnectingToSSID.ssid = $(event.relatedTarget).children('td:eq(1)').text();\r\n $('#manual_ssid').val(ConnectingToSSID.ssid);\r\n }\r\n else {\r\n ConnectingToSSID.Action = ConnectingToActions.MAN;\r\n ConnectingToSSID.ssid = '';\r\n $('#manual_ssid').val(ConnectingToSSID.ssid);\r\n }\r\n }\r\n }\r\n if (ConnectingToSSID.Action !== ConnectingToActions.STS) {\r\n $('.connecting-init').show();\r\n $('#manual_ssid').trigger('focus');\r\n }\r\n else {\r\n handleWifiDialog();\r\n }\r\n });\r\n $('#WifiConnectDialog')[0].addEventListener('hidden.bs.modal', function () {\r\n $('#WifiConnectDialog input').val('');\r\n });\r\n $('#uCnfrm')[0].addEventListener('shown.bs.modal', function () {\r\n $('#selectedFWURL').text($('#fw-url-input').val().toString());\r\n });\r\n $('input#show-commands')[0].checked = LastCommandsState === 1;\r\n $('a[href^=\"#tab-commands\"]').hide();\r\n $('#load-nvs').on('click', function () {\r\n $('#nvsfilename').trigger('click');\r\n });\r\n $('#nvsfilename').on('change', function () {\r\n const _this = this;\r\n if (typeof window.FileReader !== 'function') {\r\n throw \"The file API isn't supported on this browser.\";\r\n }\r\n if (!_this.files) {\r\n throw 'This browser does not support the `files` property of the file input.';\r\n }\r\n if (!_this.files[0]) {\r\n return undefined;\r\n }\r\n const file = _this.files[0];\r\n let fr = new FileReader();\r\n fr.onload = function (e) {\r\n let data;\r\n try {\r\n data = JSON.parse(e.target.result.toString());\r\n }\r\n catch (ex) {\r\n alert('Parsing failed!\\r\\n ' + ex);\r\n }\r\n $('input.nvs').each(function (_index, entry) {\r\n $(this).parent().removeClass('bg-warning').removeClass('bg-success');\r\n if (data[entry.id]) {\r\n if (data[entry.id] !== entry.value) {\r\n console.log('Changed ' + entry.id + ' ' + entry.value + '==>' + data[entry.id]);\r\n $(this).parent().addClass('bg-warning');\r\n $(this).val(data[entry.id]);\r\n }\r\n else {\r\n $(this).parent().addClass('bg-success');\r\n }\r\n }\r\n });\r\n var changed = $(\"input.nvs\").children('.bg-warning');\r\n if (changed) {\r\n alert('Highlighted values were changed. Press Commit to change on the device');\r\n }\r\n };\r\n fr.readAsText(file);\r\n _this.value = null;\r\n });\r\n $('#clear-syslog').on('click', function () {\r\n messagecount = 0;\r\n messageseverity = 'MESSAGING_INFO';\r\n $('#msgcnt').text('');\r\n $('#syslogTable').html('');\r\n });\r\n $('#ok-credits').on('click', function () {\r\n $('#credits').slideUp('fast', function () { });\r\n $('#app').slideDown('fast', function () { });\r\n });\r\n $('#acredits').on('click', function (event) {\r\n event.preventDefault();\r\n $('#app').slideUp('fast', function () { });\r\n $('#credits').slideDown('fast', function () { });\r\n });\r\n $('input#show-commands').on('click', function () {\r\n const _this = this;\r\n _this.checked = _this.checked ? true : false;\r\n if (_this.checked) {\r\n $('a[href^=\"#tab-commands\"]').show();\r\n LastCommandsState = 1;\r\n }\r\n else {\r\n LastCommandsState = 0;\r\n $('a[href^=\"#tab-commands\"]').hide();\r\n }\r\n });\r\n $('#disable-squeezelite').on('click', function () {\r\n // this.checked = this.checked ? 1 : 0;\r\n // $('#disable-squeezelite').prop('checked')\r\n const _this = this;\r\n if (_this.checked) {\r\n // Store the current value before overwriting it\r\n const currentValue = $('#cmd_opt_s').val();\r\n $('#cmd_opt_s').data('originalValue', currentValue);\r\n // Overwrite the value with '-disable'\r\n $('#cmd_opt_s').val('-disable');\r\n }\r\n else {\r\n // Retrieve the original value\r\n const originalValue = $('#cmd_opt_s').data('originalValue');\r\n // Restore the original value if it exists, otherwise set it to an empty string\r\n $('#cmd_opt_s').val(originalValue ? originalValue : '');\r\n }\r\n });\r\n $('input#show-nvs').on('click', function () {\r\n const _this = this;\r\n _this.checked = _this.checked ? true : false;\r\n js_cookie_1.default.set(\"show-nvs\", _this.checked ? 'Y' : 'N');\r\n handleNVSVisible();\r\n });\r\n $('#btn_reboot_recovery').on('click', function () {\r\n handleReboot('recovery');\r\n });\r\n $('#btn_reboot').on('click', function () {\r\n handleReboot('reboot');\r\n });\r\n $('#btn_flash').on('click', function () {\r\n hFlash();\r\n });\r\n $('#save-autoexec1').on('click', function () {\r\n saveAutoexec1(false);\r\n });\r\n $('#commit-autoexec1').on('click', function () {\r\n saveAutoexec1(true);\r\n });\r\n $('#btn_disconnect').on('click', function () {\r\n ConnectedTo = resetNetworkConnection();\r\n refreshAPHTML2();\r\n $.ajax({\r\n url: '/connect.zzz',\r\n dataType: 'text',\r\n method: 'DELETE',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n });\r\n });\r\n $('#btnJoin').on('click', function () {\r\n handleConnect();\r\n });\r\n $('#reboot_nav').on('click', function () {\r\n handleReboot('reboot');\r\n });\r\n $('#reboot_ota_nav').on('click', function () {\r\n handleReboot('reboot_ota');\r\n });\r\n $('#save-as-nvs').on('click', function () {\r\n const config = getConfigJson(true);\r\n const a = document.createElement('a');\r\n a.href = URL.createObjectURL(new Blob([JSON.stringify(config, null, 2)], {\r\n type: 'text/plain',\r\n }));\r\n a.setAttribute('download', 'nvs_config_' + hostName + '_' + Date.now() + 'json');\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n });\r\n $('#save-nvs').on('click', function () {\r\n post_config(getConfigJson(false));\r\n });\r\n $('#fwUpload').on('click', function () {\r\n const fileInput = document.getElementById('flashfilename').files;\r\n if (fileInput.length === 0) {\r\n alert('No file selected!');\r\n }\r\n else {\r\n $('#fw-url-input').value = null;\r\n flashState.StartOTA();\r\n }\r\n });\r\n $('[name=output-tmpl]').on('click', function () {\r\n const outputType = this.id;\r\n handleTemplateTypeRadio(outputType);\r\n });\r\n $('#chkUpdates').on('click', function () {\r\n $('#rTable').html('');\r\n $.getJSON(releaseURL, function (data) {\r\n let i = 0;\r\n const branches = [];\r\n data.forEach(function (release) {\r\n const namecomponents = release.name.split('#');\r\n const branch = namecomponents[3];\r\n if (!branches.includes(branch)) {\r\n branches.push(branch);\r\n }\r\n });\r\n let fwb = '';\r\n branches.forEach(function (branch) {\r\n fwb += '';\r\n });\r\n $('#fwbranch').append(fwb);\r\n data.forEach(function (release) {\r\n let url = '';\r\n release.assets.forEach(function (asset) {\r\n if (asset.name.match(/\\.bin$/)) {\r\n url = asset.browser_download_url;\r\n }\r\n });\r\n const namecomponents = release.name.split('#');\r\n const ver = namecomponents[0];\r\n const cfg = namecomponents[2];\r\n const branch = namecomponents[3];\r\n var bits = ver.substr(ver.lastIndexOf('-') + 1);\r\n bits = (bits == '32' || bits == '16') ? bits : '';\r\n let body = release.body;\r\n body = body.replace(/'/gi, '\"');\r\n body = body.replace(/[\\s\\S]+(### Revision Log[\\s\\S]+)### ESP-IDF Version Used[\\s\\S]+/, '$1');\r\n body = body.replace(/- \\(.+?\\) /g, '- ').encodeHTML();\r\n $('#rTable').append(`\n ${ver}${new Date(release.created_at).toLocalShort()}\n ${cfg}${branch}${bits}`);\r\n });\r\n if (i > 7) {\r\n $('#releaseTable').append(\"\" +\r\n \"\" +\r\n \"\" +\r\n '' +\r\n '');\r\n $('#showallbutton').on('click', function () {\r\n $('tr.hide').removeClass('hide');\r\n $('tr#showall').addClass('hide');\r\n });\r\n }\r\n $('#searchfw').css('display', 'inline');\r\n if (!setPlatformFilter(platform_name)) {\r\n setPlatformFilter(project_name);\r\n }\r\n $('#rTable tr.release').on('click', function () {\r\n var url = this.getAttribute('fwurl');\r\n if (lmsBaseUrl) {\r\n url = url.replace(/.*\\/download\\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');\r\n }\r\n $('#fw-url-input').val(url);\r\n $('#start-flash').show();\r\n $('#rTable tr.release').removeClass('table-success table-warning');\r\n $(this).addClass('table-success table-warning');\r\n });\r\n }).fail(function () {\r\n alert('failed to fetch release history!');\r\n });\r\n });\r\n $('#fwcheck').on('click', function () {\r\n $('#releaseTable').html('');\r\n $('#fwbranch').empty();\r\n $.getJSON(releaseURL, function (data) {\r\n let i = 0;\r\n const branches = [];\r\n data.forEach(function (release) {\r\n const namecomponents = release.name.split('#');\r\n const branch = namecomponents[3];\r\n if (!branches.includes(branch)) {\r\n branches.push(branch);\r\n }\r\n });\r\n let fwb;\r\n branches.forEach(function (branch) {\r\n fwb += ``;\r\n });\r\n $('#fwbranch').append(fwb);\r\n data.forEach(function (release) {\r\n let url = '';\r\n release.assets.forEach(function (asset) {\r\n if (asset.name.match(/\\.bin$/)) {\r\n url = asset.browser_download_url;\r\n }\r\n });\r\n const namecomponents = release.name.split('#');\r\n const ver = namecomponents[0];\r\n const idf = namecomponents[1];\r\n const cfg = namecomponents[2];\r\n const branch = namecomponents[3];\r\n let body = release.body;\r\n body = body.replace(/'/gi, '\"');\r\n body = body.replace(/[\\s\\S]+(### Revision Log[\\s\\S]+)### ESP-IDF Version Used[\\s\\S]+/, '$1');\r\n body = body.replace(/- \\(.+?\\) /g, '- ');\r\n const trclass = i++ > 6 ? ' hide' : '';\r\n $('#releaseTable').append(`${ver}${new Date(release.created_at).toLocalShort()}${cfg}${idf}${branch}`);\r\n });\r\n if (i > 7) {\r\n $('#releaseTable').append(``);\r\n $('#showallbutton').on('click', function () {\r\n $('tr.hide').removeClass('hide');\r\n $('tr#showall').addClass('hide');\r\n });\r\n }\r\n $('#searchfw').css('display', 'inline');\r\n }).fail(function () {\r\n alert('failed to fetch release history!');\r\n });\r\n });\r\n $('#updateAP').on('click', function () {\r\n refreshAP();\r\n console.log('refresh AP');\r\n });\r\n // first time the page loads: attempt to get the connection status and start the wifi scan\r\n getConfig();\r\n getCommands();\r\n getMessages();\r\n checkStatus();\r\n});\r\n// eslint-disable-next-line no-unused-vars\r\nwindow.setURL = function (button) {\r\n let url = button.dataset.url;\r\n $('[data-bs-url^=\"http\"]')\r\n .addClass('btn-success')\r\n .removeClass('btn-danger');\r\n $('[data-bs-url=\"' + url + '\"]')\r\n .addClass('btn-danger')\r\n .removeClass('btn-success');\r\n // if user can proxy download through LMS, modify the URL\r\n if (lmsBaseUrl) {\r\n url = url.replace(/.*\\/download\\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');\r\n }\r\n $('#fwurl').val(url);\r\n};\r\nfunction rssiToIcon(rssi) {\r\n if (rssi >= -55) {\r\n return { label: '****', icon: `signal_wifi_statusbar_4_bar` };\r\n }\r\n else if (rssi >= -60) {\r\n return { label: '***', icon: `network_wifi_3_bar` };\r\n }\r\n else if (rssi >= -65) {\r\n return { label: '**', icon: `network_wifi_2_bar` };\r\n }\r\n else if (rssi >= -70) {\r\n return { label: '*', icon: `network_wifi_1_bar` };\r\n }\r\n else {\r\n return { label: '.', icon: `signal_wifi_statusbar_null` };\r\n }\r\n}\r\nfunction refreshAP() {\r\n if ((ConnectedTo === null || ConnectedTo === void 0 ? void 0 : ConnectedTo.urc) === connectReturnCode.ETH)\r\n return;\r\n $.ajaxSetup({\r\n timeout: 3000 //Time in milliseconds\r\n });\r\n $.getJSON('/scan.zzz', function () {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n yield sleep(2000);\r\n $.getJSON('/ap.zzz', function (data) {\r\n if (data.length > 0) {\r\n // sort by signal strength\r\n data.sort(function (a, b) {\r\n const x = a.rssi;\r\n const y = b.rssi;\r\n // eslint-disable-next-line no-nested-ternary\r\n return x < y ? 1 : x > y ? -1 : 0;\r\n });\r\n apList = data;\r\n refreshAPHTML2(apList);\r\n }\r\n });\r\n });\r\n });\r\n}\r\nfunction formatAP(ssid, rssi, auth) {\r\n const rssi_icon = rssiToIcon(rssi);\r\n const auth_icon = { label: auth == 0 ? '🔓' : '🔒', icon: auth == 0 ? 'no_encryption' : 'lock' };\r\n return `${ssid}\n ${getIcon(rssi_icon)}\n \t\n ${getIcon(auth_icon)}\n `;\r\n}\r\nfunction refreshAPHTML2(data) {\r\n var _a;\r\n let h = '';\r\n $('#wifiTable tr td:first-of-type').text('');\r\n $('#wifiTable tr').removeClass('table-success table-warning');\r\n if (data) {\r\n data.forEach(function (e) {\r\n h += formatAP(e.ssid, e.rssi, e.auth);\r\n });\r\n $('#wifiTable').html(h);\r\n }\r\n if ($('.manual_add').length == 0) {\r\n $('#wifiTable').append(formatAP('Manual add', 0, 0));\r\n $('#wifiTable tr:last').addClass('table-light text-dark').addClass('manual_add');\r\n }\r\n if (ConnectedTo && ConnectedTo.ssid && (ConnectedTo.urc === connectReturnCode.OK || ConnectedTo.urc === connectReturnCode.RESTORE)) {\r\n const wifiSelector = `#wifiTable td:contains(\"${ConnectedTo.ssid}\")`;\r\n if ($(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).length == 0) {\r\n $('#wifiTable').prepend(`${formatAP(ConnectedTo.ssid, (_a = ConnectedTo.rssi) !== null && _a !== void 0 ? _a : 0, 0)}`);\r\n }\r\n $(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).siblings().first().html('✓').parent().addClass((ConnectedTo.urc === connectReturnCode.OK ? 'table-success' : 'table-warning'));\r\n $('span#foot-if').html(`SSID: ${ConnectedTo.ssid}, IP: ${ConnectedTo.ip}`);\r\n const rssiIconObj = rssiToIcon(ConnectedTo.rssi); // Assume this returns an object like { label: 'some_label', icon: 'some_icon_name' }\r\n const iconTextContent = getIcon(rssiIconObj); // Function to get the text content for the material icon\r\n // Set the icon text content\r\n $('#wifiStsIcon').text(iconTextContent);\r\n // Update the aria-label and custom icon attribute\r\n $('#wifiStsIcon').attr('aria-label', rssiIconObj.label);\r\n $('#wifiStsIcon').attr('icon', rssiIconObj.icon);\r\n }\r\n else if ((ConnectedTo === null || ConnectedTo === void 0 ? void 0 : ConnectedTo.urc) !== connectReturnCode.ETH) {\r\n $('span#foot-if').html('');\r\n }\r\n}\r\nfunction refreshETH() {\r\n if (ConnectedTo.urc === connectReturnCode.ETH) {\r\n $('span#foot-if').html(`Network: Ethernet, IP: ${ConnectedTo.ip}`);\r\n }\r\n}\r\nfunction showTask(task) {\r\n console.debug(`${this.toLocaleString()}\\t${task.nme}\\t${task.cpu}\\t${taskStates[task.st]}\\t${task.minstk}\\t${task.bprio}\\t${task.cprio}\\t${task.num}`);\r\n $('tbody#tasks').append(`${task.num}${task.nme}${task.cpu}${taskStates[task.st]}${task.minstk}${task.bprio}${task.cprio}`);\r\n}\r\nfunction btExists(name) {\r\n return getBTSinkOpt(name).length > 0;\r\n}\r\nfunction getBTSinkOpt(name) {\r\n // return $(`${btSinkNamesOptSel} option:contains('${name}')`);\r\n return \"\";\r\n}\r\nfunction getMessages() {\r\n $.ajaxSetup({\r\n timeout: messageInterval //Time in milliseconds\r\n });\r\n $.getJSON('/messages.zzz', function (data) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n for (const msg of data) {\r\n const msgAge = msg.current_time - msg.sent_time;\r\n var msgTime = new Date();\r\n msgTime.setTime(msgTime.getTime() - msgAge);\r\n switch (msg.class) {\r\n case 'MESSAGING_CLASS_OTA':\r\n flashState.EventOTAMessageClass(msg.message);\r\n break;\r\n case 'MESSAGING_CLASS_STATS':\r\n // for task states, check structure : task_state_t\r\n var statsData = JSON.parse(msg.message);\r\n console.debug(msgTime.toLocalShort() +\r\n ' - Number of running tasks: ' +\r\n statsData.ntasks);\r\n console.debug(`${msgTime.toLocalShort()}\\tname\\tcpu\\tstate\\tminstk\\tbprio\\tcprio\\tnum`);\r\n if (statsData.tasks) {\r\n const taskList = statsData.tasks;\r\n if ($('#tasks_sect').css('visibility') === 'collapse') {\r\n $('#tasks_sect').css('visibility', 'visible');\r\n }\r\n $('tbody#tasks').html('');\r\n statsData.taskList\r\n .sort(function (a, b) {\r\n return b.cpu - a.cpu;\r\n })\r\n .forEach(showTask, msgTime);\r\n }\r\n else if ($('#tasks_sect').css('visibility') === 'visible') {\r\n $('tbody#tasks').empty();\r\n $('#tasks_sect').css('visibility', 'collapse');\r\n }\r\n break;\r\n case 'MESSAGING_CLASS_SYSTEM':\r\n showMessage(msg, msgTime);\r\n break;\r\n case 'MESSAGING_CLASS_CFGCMD':\r\n var msgparts = msg.message.split(/([^\\n]*)\\n(.*)/gs);\r\n showCmdMessage(msgparts[1], msg.type, msgparts[2], true);\r\n break;\r\n case 'MESSAGING_CLASS_BT':\r\n // if ($(btSinkNamesOptSel).is('input')) {\r\n // const sinkNameCtrl = $(btSinkNamesOptSel)[0] as HTMLInputElement;\r\n // var attr = sinkNameCtrl.attributes;\r\n // var attrs = '';\r\n // for (var j = 0; j < attr.length; j++) {\r\n // if (attr.item(j).name != \"type\") {\r\n // attrs += `${attr.item(j).name} = \"${attr.item(j).value}\" `;\r\n // }\r\n // }\r\n // var curOpt = sinkNameCtrl.value;\r\n // $(btSinkNamesOptSel).replaceWith(` `);\r\n // }\r\n // JSON.parse(msg.message).forEach(function (btEntry: BTDevice) {\r\n // // if (!btExists(btEntry.name)) {\r\n // // $(btSinkNamesOptSel).append(``);\r\n // // showMessage({\r\n // // type: msg.type,\r\n // // message: `BT Audio device found: ${btEntry.name} RSSI: ${btEntry.rssi} `,\r\n // // class: '',\r\n // // sent_time: 0,\r\n // // current_time: 0\r\n // // }, msgTime);\r\n // // }\r\n // getBTSinkOpt(btEntry.name).attr('data-bs-description', `${btEntry.name} (${btEntry.rssi}dB)`)\r\n // .attr('rssi', btEntry.rssi)\r\n // .attr('value', btEntry.name)\r\n // .text(`${btEntry.name} [${btEntry.rssi}dB]`).trigger('change');\r\n // });\r\n // Get the options as an array\r\n // const btEntries = Array.from($(btSinkNamesOptSel).find('option'));\r\n // Sort the options based on the 'rssi' attribute\r\n // btEntries.sort(function (a, b) {\r\n // const rssiA = parseInt($(a).attr('rssi'), 10);\r\n // const rssiB = parseInt($(b).attr('rssi'), 10);\r\n // console.log(`${rssiA} < ${rssiB} ? `);\r\n // return rssiB - rssiA; // Sort by descending RSSI values\r\n // });\r\n // // Clear the select element and append the sorted options\r\n // $(btSinkNamesOptSel).empty().append(btEntries);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n setTimeout(getMessages, messageInterval);\r\n });\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n if (xhr.status == 404) {\r\n $('.orec').hide(); // system commands won't be available either\r\n messagesHeld = true;\r\n }\r\n else {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n }\r\n if (xhr.status == 0 && xhr.readyState == 0) {\r\n // probably a timeout. Target is rebooting? \r\n setTimeout(getMessages, messageInterval * 2); // increase duration if a failure happens\r\n }\r\n else if (!messagesHeld) {\r\n // 404 here means we rebooted to an old recovery\r\n setTimeout(getMessages, messageInterval); // increase duration if a failure happens\r\n }\r\n });\r\n /*\r\n Minstk is minimum stack space left\r\n Bprio is base priority\r\n cprio is current priority\r\n nme is name\r\n st is task state. I provided a \"typedef\" that you can use to convert to text\r\n cpu is cpu percent used\r\n */\r\n}\r\nfunction handleRecoveryMode(data) {\r\n var _a;\r\n const locRecovery = (_a = data.recovery) !== null && _a !== void 0 ? _a : 0;\r\n if (locRecovery === 1) {\r\n recovery = true;\r\n $('.recovery_element').show();\r\n $('.ota_element').hide();\r\n $('#boot-button').html('Reboot');\r\n $('#boot-form').attr('action', '/reboot_ota.zzz');\r\n }\r\n else {\r\n if (!recovery && messagesHeld) {\r\n messagesHeld = false;\r\n setTimeout(getMessages, messageInterval); // increase duration if a failure happens\r\n }\r\n recovery = false;\r\n $('.recovery_element').hide();\r\n $('.ota_element').show();\r\n $('#boot-button').html('Recovery');\r\n $('#boot-form').attr('action', '/recovery.zzz');\r\n }\r\n}\r\nfunction hasConnectionChanged(data) {\r\n // gw: \"192.168.10.1\"\r\n // ip: \"192.168.10.225\"\r\n // netmask: \"255.255.255.0\"\r\n // ssid: \"MyTestSSID\"\r\n return (ConnectedTo && (data.urc !== ConnectedTo.urc ||\r\n data.ssid !== ConnectedTo.ssid ||\r\n data.gw !== ConnectedTo.gw ||\r\n data.netmask !== ConnectedTo.netmask ||\r\n data.ip !== ConnectedTo.ip || data.rssi !== ConnectedTo.rssi));\r\n}\r\nfunction handleWifiDialog(data) {\r\n if ($('#WifiConnectDialog').is(':visible')) {\r\n if (ConnectedTo.ip) {\r\n $('#ipAddress').text(ConnectedTo.ip);\r\n }\r\n if (ConnectedTo.ssid) {\r\n $('#connectedToSSID').text(ConnectedTo.ssid);\r\n }\r\n if (ConnectedTo.gw) {\r\n $('#gateway').text(ConnectedTo.gw);\r\n }\r\n if (ConnectedTo.netmask) {\r\n $('#netmask').text(ConnectedTo.netmask);\r\n }\r\n if (ConnectingToSSID.Action === undefined || (ConnectingToSSID.Action && ConnectingToSSID.Action == ConnectingToActions.STS)) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-status').show();\r\n }\r\n if (SystemConfig.ap_ssid) {\r\n $('#apName').text(SystemConfig.ap_ssid.value);\r\n }\r\n if (SystemConfig.ap_pwd) {\r\n $('#apPass').text(SystemConfig.ap_pwd.value);\r\n }\r\n if (!data) {\r\n return;\r\n }\r\n else {\r\n switch (data.urc) {\r\n case connectReturnCode.OK:\r\n if (data.ssid && data.ssid === ConnectingToSSID.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-success').show();\r\n ConnectingToSSID.Action = ConnectingToActions.STS;\r\n }\r\n break;\r\n case connectReturnCode.FAIL:\r\n // \r\n if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid == data.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-fail').show();\r\n }\r\n break;\r\n case connectReturnCode.LOST:\r\n break;\r\n case connectReturnCode.RESTORE:\r\n if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid != data.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-fail').show();\r\n }\r\n break;\r\n case connectReturnCode.DISC:\r\n // that's a manual disconnect\r\n // if ($('#wifi-status').is(':visible')) {\r\n // $('#wifi-status').slideUp('fast', function() {});\r\n // $('span#foot-wifi').html('');\r\n // } \r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n}\r\nfunction setIcons(offline) {\r\n $('.material-icons').each(function (_index, entry) {\r\n const htmlEntry = entry;\r\n htmlEntry.textContent = htmlEntry.getAttribute(offline ? 'aria-label' : 'data-icon') || '';\r\n });\r\n}\r\nfunction assignStatusToNetworkConnection(data) {\r\n var _a;\r\n const connection = {\r\n urc: (_a = data.urc) !== null && _a !== void 0 ? _a : 0,\r\n auth: undefined,\r\n pwd: undefined,\r\n dhcpname: undefined,\r\n Action: undefined,\r\n ip: data.ip,\r\n ssid: data.ssid,\r\n rssi: data.rssi,\r\n gw: data.gw,\r\n netmask: data.netmask\r\n };\r\n return connection;\r\n}\r\nfunction handleNetworkStatus(data) {\r\n setIcons(!isConnected());\r\n if (hasConnectionChanged(data) || !data.urc) {\r\n ConnectedTo = assignStatusToNetworkConnection(data);\r\n $(\".if_eth\").hide();\r\n $('.if_wifi').hide();\r\n if (!data.urc || ConnectedTo.urc != connectReturnCode.ETH) {\r\n $('.if_wifi').show();\r\n refreshAPHTML2();\r\n }\r\n else {\r\n $(\".if_eth\").show();\r\n refreshETH();\r\n }\r\n }\r\n handleWifiDialog(data);\r\n}\r\nfunction batteryToIcon(voltage) {\r\n /* Assuming Li-ion 18650s as a power source, 3.9V per cell, or above is treated\r\n as full charge (>75% of capacity). 3.4V is empty. The gauge is loosely\r\n following the graph here:\r\n https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages\r\n using the 0.2C discharge profile for the rest of the values.\r\n */\r\n for (const iconEntry of batIcons) {\r\n for (const entryRanges of iconEntry.ranges) {\r\n if (inRange(voltage, entryRanges.f, entryRanges.t)) {\r\n return { label: iconEntry.label, icon: iconEntry.icon };\r\n }\r\n }\r\n }\r\n return { label: '▪▪▪▪', icon: \"battery_full\" };\r\n}\r\nfunction checkStatus() {\r\n $.ajaxSetup({\r\n timeout: statusInterval //Time in milliseconds\r\n });\r\n $.getJSON('/status.zzz', function (data) {\r\n var _a;\r\n handleRecoveryMode(data);\r\n handleNVSVisible();\r\n handleNetworkStatus(data);\r\n handlebtstate(data);\r\n flashState.EventTargetStatus(data);\r\n if (data.depth) {\r\n depth = data.depth;\r\n if (depth == 16) {\r\n $('#cmd_opt_R').show();\r\n }\r\n else {\r\n $('#cmd_opt_R').hide();\r\n }\r\n }\r\n if (data.project_name && data.project_name !== '') {\r\n project_name = data.project_name;\r\n }\r\n if (data.platform_name && data.platform_name !== '') {\r\n platform_name = data.platform_name;\r\n }\r\n if (board_model === '')\r\n board_model = project_name;\r\n if (board_model === '')\r\n board_model = 'Squeezelite-ESP32';\r\n if (data.version && data.version !== '') {\r\n versionName = data.version;\r\n $(\"#navtitle\").html(`${board_model}${recovery ? '
[recovery]' : ''}`);\r\n $('span#foot-fw').html(`fw: ${versionName}, mode: ${recovery ? \"Recovery\" : project_name}`);\r\n }\r\n else {\r\n $('span#flash-status').html('');\r\n }\r\n if (data.Voltage) {\r\n const bat_icon = batteryToIcon(data.Voltage);\r\n $('#battery').html(`${getIcon(bat_icon)}`);\r\n $('#battery').attr(\"aria-label\", bat_icon.label);\r\n $('#battery').attr(\"data-icon\", bat_icon.icon);\r\n $('#battery').show();\r\n }\r\n else {\r\n $('#battery').hide();\r\n }\r\n if (((_a = data.message) !== null && _a !== void 0 ? _a : '') != '' && prevmessage != data.message) {\r\n // supporting older recovery firmwares - messages will come from the status.json structure\r\n prevmessage = data.message;\r\n showLocalMessage(data.message, 'MESSAGING_INFO');\r\n }\r\n is_i2c_locked = data.is_i2c_locked;\r\n if (is_i2c_locked) {\r\n $('flds-cfg-hw-preset').hide();\r\n }\r\n else {\r\n $('flds-cfg-hw-preset').show();\r\n }\r\n $(\"button[onclick*='handleReboot']\").removeClass('rebooting');\r\n if (typeof lmsBaseUrl == \"undefined\" || data.lms_ip != prevLMSIP && data.lms_ip && data.lms_port) {\r\n const baseUrl = 'http://' + data.lms_ip + ':' + data.lms_port;\r\n prevLMSIP = data.lms_ip;\r\n $.ajax({\r\n url: baseUrl + '/plugins/SqueezeESP32/firmware/-check.bin',\r\n type: 'HEAD',\r\n dataType: 'text',\r\n cache: false,\r\n error: function () {\r\n // define the value, so we don't check it any more.\r\n lmsBaseUrl = '';\r\n },\r\n success: function () {\r\n lmsBaseUrl = baseUrl;\r\n }\r\n });\r\n }\r\n $('#o_jack').css({ display: Number(data.Jack) ? 'inline' : 'none' });\r\n setTimeout(checkStatus, statusInterval);\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n if (xhr.status == 0 && xhr.readyState == 0) {\r\n // probably a timeout. Target is rebooting? \r\n setTimeout(checkStatus, messageInterval * 2); // increase duration if a failure happens\r\n }\r\n else {\r\n setTimeout(checkStatus, messageInterval); // increase duration if a failure happens\r\n }\r\n });\r\n}\r\n// eslint-disable-next-line no-unused-vars\r\nwindow.runCommand = function (button, reboot) {\r\n let cmdstring = button.getAttribute('cmdname');\r\n showCmdMessage(cmdstring, 'MESSAGING_INFO', 'Executing.', false);\r\n const fields = document.getElementById('flds-' + cmdstring);\r\n const allfields = fields === null || fields === void 0 ? void 0 : fields.querySelectorAll('select,input');\r\n if (cmdstring === 'cfg-hw-preset')\r\n return handleHWPreset(allfields, reboot);\r\n cmdstring += ' ';\r\n if (fields) {\r\n for (const field of allfields) {\r\n let qts = '';\r\n let opt = '';\r\n const isSelect = field.tagName === 'SELECT';\r\n const hasValue = field.getAttribute('hasvalue') === 'true';\r\n const validVal = (isSelect && field.value !== '--') || (!isSelect && field.value !== '');\r\n if (!hasValue || (hasValue && validVal)) {\r\n const longopts = field.getAttribute('longopts');\r\n const shortopts = field.getAttribute('shortopts');\r\n if (longopts !== null && longopts !== 'undefined') {\r\n opt += '--' + longopts;\r\n }\r\n else if (shortopts !== null && shortopts !== 'undefined') {\r\n opt = '-' + shortopts;\r\n }\r\n if (hasValue) {\r\n qts = /\\s/.test(field.value) ? '\"' : '';\r\n cmdstring += `${opt} ${qts}${field.value}${qts} `;\r\n }\r\n else {\r\n // this is a checkbox\r\n if (field.checked) {\r\n cmdstring += `${opt} `;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n console.log(cmdstring);\r\n const data = {\r\n timestamp: Date.now(),\r\n command: cmdstring\r\n };\r\n $.ajax({\r\n url: '/commands.zzz',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(data),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n var cmd = JSON.parse(this.data).command;\r\n if (xhr.status == 404) {\r\n showCmdMessage(cmd.substr(0, cmd.indexOf(' ')), 'MESSAGING_ERROR', `${recovery ? 'Limited recovery mode active. Unsupported action ' : 'Unexpected error while processing command'}`, true);\r\n }\r\n else {\r\n handleExceptionResponse(xhr, _ajaxOptions, thrownError);\r\n showCmdMessage(cmd.substr(0, cmd.indexOf(' ') - 1), 'MESSAGING_ERROR', `Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status}`, true);\r\n }\r\n },\r\n success: function (response) {\r\n $('.orec').show();\r\n console.log(response);\r\n if (JSON.parse(response).Result === 'Success' &&\r\n reboot) {\r\n delayReboot(2500, button.getAttribute('cmdname'));\r\n }\r\n },\r\n });\r\n};\r\nfunction getLongOps(data, name, longopts) {\r\n return data[name] !== undefined ? data[name][longopts] : \"\";\r\n}\r\nfunction getCommands() {\r\n $.ajaxSetup({\r\n timeout: 7000 //Time in milliseconds\r\n });\r\n $.getJSON('/commands.zzz', function (data) {\r\n console.log(data);\r\n $('.orec').show();\r\n data.commands.forEach(function (command) {\r\n if ($('#flds-' + command.name).length === 0) {\r\n const cmdParts = command.name.split('-');\r\n const isConfig = cmdParts[0] === 'cfg';\r\n const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1];\r\n let innerhtml = '';\r\n innerhtml += `
${command.help.encodeHTML().replace(/\\n/g, '
')}
`;\r\n if (command.argtable) {\r\n command.argtable.forEach(function (arg) {\r\n let placeholder = arg.datatype || '';\r\n const ctrlname = command.name + '-' + arg.longopts;\r\n const curvalue = getLongOps(data.values, command.name, arg.longopts);\r\n let attributes = `hasvalue=${arg.hasvalue} `;\r\n attributes += 'longopts=\"' + arg.longopts + '\" ';\r\n attributes += 'shortopts=\"' + arg.shortopts + '\" ';\r\n attributes += 'checkbox=' + arg.checkbox + ' ';\r\n attributes += 'cmdname=\"' + command.name + '\" ';\r\n attributes +=\r\n `id=\"${ctrlname}\" name=\"${ctrlname}\" hasvalue=\"${arg.hasvalue}\" `;\r\n let extraclass = arg.mincount > 0 ? 'bg-success' : '';\r\n if (arg.glossary === 'hidden') {\r\n attributes += ' style=\"visibility: hidden;\"';\r\n }\r\n if (arg.checkbox) {\r\n innerhtml += `
`;\r\n }\r\n else {\r\n innerhtml += `
`;\r\n if (placeholder.includes('|')) {\r\n extraclass = placeholder.startsWith('+') ? ' multiple ' : '';\r\n placeholder = placeholder\r\n .replace('<', '')\r\n .replace('=', '')\r\n .replace('>', '');\r\n innerhtml += `';\r\n }\r\n else {\r\n innerhtml += ``;\r\n }\r\n }\r\n innerhtml += `${arg.checkbox ? '
' : ''}Previous value: ${arg.checkbox ? (curvalue ? 'Checked' : 'Unchecked') : (curvalue || '')}${arg.checkbox ? '' : '
'}`;\r\n });\r\n }\r\n innerhtml += `
\n
\n
\n Result\n
\n
\n
`;\r\n if (isConfig) {\r\n innerhtml +=\r\n `\n`;\r\n }\r\n else {\r\n innerhtml += ``;\r\n }\r\n innerhtml += '
';\r\n if (isConfig) {\r\n $(targetDiv).append(innerhtml);\r\n }\r\n else {\r\n $('#commands-list').append(innerhtml);\r\n }\r\n }\r\n });\r\n $(\".sclk\").off('click').on('click', function () { window.runCommand(this, false); });\r\n $(\".cclk\").off('click').on('click', function () { window.runCommand(this, true); });\r\n data.commands.forEach(function (command) {\r\n $('[cmdname=' + command.name + ']:input').val('');\r\n $('[cmdname=' + command.name + ']:checkbox').prop('checked', false);\r\n if (command.argtable) {\r\n command.argtable.forEach(function (arg) {\r\n const ctrlselector = '#' + command.name + '-' + arg.longopts;\r\n if (arg.checkbox) {\r\n $(ctrlselector)[0].checked = getLongOps(data, command.name, arg.longopts);\r\n }\r\n else {\r\n let ctrlValue = getLongOps(data, command.name, arg.longopts);\r\n if (ctrlValue !== undefined) {\r\n $(ctrlselector)\r\n .val(ctrlValue.toString())\r\n .trigger('change');\r\n }\r\n if ($(ctrlselector)[0].value.length === 0 &&\r\n (arg.datatype || '').includes('|')) {\r\n $(ctrlselector)[0].value = '--';\r\n }\r\n }\r\n });\r\n }\r\n });\r\n loadPresets();\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n if (xhr.status == 404) {\r\n $('.orec').hide();\r\n }\r\n else {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n }\r\n $('#commands-list').empty();\r\n });\r\n}\r\nfunction getConfig() {\r\n $.ajaxSetup({\r\n timeout: 7000 //Time in milliseconds\r\n });\r\n // Create an instance of Payload and set values\r\n var payload = new proto.sys.request.Payload();\r\n payload.setType(proto.sys.request.Type.CONFIG); // Example: Setting the type field\r\n payload.setAction(proto.sys.request.Action.GET);\r\n // Serialize the Payload to binary\r\n var serializedPayload = payload.serializeBinary();\r\n $.ajax({\r\n url: '/data.bin',\r\n method: 'POST',\r\n contentType: 'application/octet-stream',\r\n processData: false,\r\n data: serializedPayload,\r\n success: function (data) {\r\n console.log('Response received:', data);\r\n try {\r\n // Assuming 'proto.sys.Config.decode' is the method to deserialize your data\r\n var ConfigMessage = proto.sys.Config; // Replace with your actual message class\r\n var config = ConfigMessage.deserializeBinary(new Uint8Array(data));\r\n console.log('Config received:', config);\r\n document.title = config.getNames().getDevice();\r\n hostName = config.getNames().getDevice();\r\n releaseURL = config.getServices().getReleaseUrl();\r\n $(\"#s_airplay\").css({ display: config.getServices().getAirplay().getEnabled() ? 'inline' : 'none' });\r\n $(\"#s_cspot\").css({ display: config.getServices().getCspot().getEnabled() ? 'inline' : 'none' });\r\n }\r\n catch (error) {\r\n console.error('Error decoding protobuf message:', error);\r\n }\r\n },\r\n error: function (jqXHR, textStatus, errorThrown) {\r\n console.error('Error sending config:', textStatus, errorThrown);\r\n }\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n });\r\n // $.getJSON('/config.zzz', function (entries) {\r\n // $('#nvsTable tr').remove();\r\n // const data = (entries.config ? entries.config : entries);\r\n // SystemConfig = data;\r\n // commandBTSinkName = '';\r\n // Object.keys(data)\r\n // .sort()\r\n // .forEach(function (key) {\r\n // let val = data[key].value;\r\n // if (key === 'autoexec1') {\r\n // /* call new function to parse the squeezelite options */\r\n // processSqueezeliteCommandLine(val);\r\n // } else if (key === 'host_name') {\r\n // val = val.replaceAll('\"', '');\r\n // $('input#dhcp-name1').val(val);\r\n // $('input#dhcp-name2').val(val);\r\n // if ($('#cmd_opt_n').length == 0) {\r\n // $('#cmd_opt_n').val(val);\r\n // }\r\n // document.title = val;\r\n // hostName = val;\r\n // } else if (key === 'rel_api') {\r\n // releaseURL = val;\r\n // }\r\n // else if (key === 'enable_airplay') {\r\n // $(\"#s_airplay\").css({ display: isEnabled(val) ? 'inline' : 'none' })\r\n // }\r\n // else if (key === 'enable_cspot') {\r\n // $(\"#s_cspot\").css({ display: isEnabled(val) ? 'inline' : 'none' })\r\n // }\r\n // else if (key == 'preset_name') {\r\n // preset_name = val;\r\n // }\r\n // else if (key == 'board_model') {\r\n // board_model = val;\r\n // }\r\n // $('tbody#nvsTable').append(\r\n // `${key}`\r\n // );\r\n // $('input#' + key).val(data[key].value);\r\n // });\r\n // if (commandBTSinkName.length > 0) {\r\n // // persist the sink name found in the autoexec1 command line\r\n // $('#cfg-audio-bt_source-sink_name').val(commandBTSinkName);\r\n // }\r\n // $('tbody#nvsTable').append(\r\n // \"\"\r\n // );\r\n // if (entries.gpio) {\r\n // $('#pins').show();\r\n // $('tbody#gpiotable tr').remove();\r\n // entries.gpio.forEach(function (gpioEntry: GPIOEntry) {\r\n // $('tbody#gpiotable').append(\r\n // `${gpioEntry.group}${gpioEntry.name}${gpioEntry.gpio}${gpioEntry.fixed ? 'Fixed' : 'Configuration'}`\r\n // );\r\n // });\r\n // }\r\n // else {\r\n // $('#pins').hide();\r\n // }\r\n}\r\nfunction processSqueezeliteCommandLine(val) {\r\n const parsed = parseSqueezeliteCommandLine(val);\r\n if (parsed.output.toUpperCase().startsWith('I2S')) {\r\n handleTemplateTypeRadio('i2s');\r\n }\r\n else if (parsed.output.toUpperCase().startsWith('SPDIF')) {\r\n handleTemplateTypeRadio('spdif');\r\n }\r\n else if (parsed.output.toUpperCase().startsWith('BT')) {\r\n if (parsed.otherOptions.btname) {\r\n commandBTSinkName = parsed.otherOptions.btname;\r\n }\r\n handleTemplateTypeRadio('bt');\r\n }\r\n Object.keys(parsed.options).forEach(function (key) {\r\n const option = parsed.options[key];\r\n if (!$(`#cmd_opt_${key}`).hasOwnProperty('checked')) {\r\n $(`#cmd_opt_${key}`).val(option);\r\n }\r\n else {\r\n if (typeof option === 'boolean') {\r\n $(`#cmd_opt_${key}`)[0].checked = option;\r\n }\r\n }\r\n });\r\n if (parsed.options.hasOwnProperty('u')) {\r\n // parse -u v[:i] and check the appropriate radio button with id #resample_v\r\n const [resampleValue, resampleInterpolation] = parsed.options.u.split(':');\r\n $(`#resample_${resampleValue}`).prop('checked', true);\r\n // if resampleinterpolation is set, check resample_i checkbox\r\n if (resampleInterpolation) {\r\n $('#resample_i').prop('checked', true);\r\n }\r\n }\r\n if (parsed.options.hasOwnProperty('s')) {\r\n // parse -u v[:i] and check the appropriate radio button with id #resample_v\r\n if (parsed.options.s === '-disable') {\r\n $('#disable-squeezelite')[0].checked = true;\r\n }\r\n else {\r\n $('#disable-squeezelite')[0].checked = false;\r\n }\r\n }\r\n}\r\nfunction showLocalMessage(message, severity) {\r\n const msg = {\r\n message: message,\r\n type: severity,\r\n class: '',\r\n sent_time: 0,\r\n current_time: 0\r\n };\r\n showMessage(msg, new Date());\r\n}\r\nfunction showMessage(msg, msgTime) {\r\n let color = 'table-success';\r\n if (msg.type === 'MESSAGING_WARNING') {\r\n color = 'table-warning';\r\n if (messageseverity === 'MESSAGING_INFO') {\r\n messageseverity = 'MESSAGING_WARNING';\r\n }\r\n }\r\n else if (msg.type === 'MESSAGING_ERROR') {\r\n if (messageseverity === 'MESSAGING_INFO' ||\r\n messageseverity === 'MESSAGING_WARNING') {\r\n messageseverity = 'MESSAGING_ERROR';\r\n }\r\n color = 'table-danger';\r\n }\r\n if (++messagecount > 0) {\r\n $('#msgcnt').removeClass('badge-success');\r\n $('#msgcnt').removeClass('badge-warning');\r\n $('#msgcnt').removeClass('badge-danger');\r\n $('#msgcnt').addClass({\r\n MESSAGING_INFO: 'badge-success',\r\n MESSAGING_WARNING: 'badge-warning',\r\n MESSAGING_ERROR: 'badge-danger',\r\n }[messageseverity]);\r\n $('#msgcnt').text(messagecount);\r\n }\r\n $('#syslogTable').append(`${msgTime.toLocalShort()}${msg.message.encodeHTML()}`);\r\n}\r\nfunction inRange(x, min, max) {\r\n return (x - min) * (x - max) <= 0;\r\n}\r\nfunction sleep(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t826: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunksqueezelite_esp32\"] = self[\"webpackChunksqueezelite_esp32\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [987], () => (__webpack_require__(3607)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","jspb","require","goog","global","globalThis","window","self","this","call","Function","nanopb_pb","object","extend","proto","customoptions_pb","exportSymbol","sys","AirPlay","opt_data","Message","initialize","inherits","DEBUG","COMPILED","displayName","GENERATE_TO_OBJECT","prototype","toObject","opt_includeInstance","includeInstance","msg","obj","enabled","getBooleanFieldWithDefault","port","getFieldWithDefault","$jspbMessageInstance","deserializeBinary","bytes","reader","BinaryReader","deserializeBinaryFromReader","nextField","isEndGroup","getFieldNumber","value","readBool","setEnabled","readUint32","setPort","skipField","serializeBinary","writer","BinaryWriter","serializeBinaryToWriter","getResultBuffer","message","f","undefined","getEnabled","writeBool","getPort","writeUint32","setProto3BooleanField","setProto3IntField","exports","Artwork","resize","setResize","getResize","Battery","channel","scale","getFloatingPointFieldWithDefault","cells","atten","readEnum","setChannel","readFloat","setScale","readInt32","setCells","setAtten","getChannel","writeEnum","getScale","writeFloat","getCells","writeInt32","getAtten","setProto3EnumField","setProto3FloatField","BatteryChannelEnum","UNSPECIFIED_CH","CH0","CH1","CH2","CH3","CH4","CH5","CH6","CH7","BatteryAttenEnum","UNSPECIFIED_ATT","ATT_0","ATT_1","ATT_2","ATT_3","GPIO_pb","ButtonActionChoice","oneofGroups_","ButtonActions","Button","ButtonProfile","repeatedFields_","KnobOnly","Rotary","ActiontypeCase","ACTIONTYPE_NOT_SET","ACTION","PROFILE_NAME","getActiontypeCase","computeOneofCase","action","profileName","setAction","readString","setProfileName","getField","writeString","getAction","setOneofField","clearAction","hasAction","getProfileName","clearProfileName","hasProfileName","normal","getNormal","longpress","getLongpress","shifted","getShifted","longshifted","getLongshifted","readMessage","setNormal","setLongpress","setShifted","setLongshifted","writeMessage","getWrapperField","setWrapperField","clearNormal","hasNormal","clearLongpress","hasLongpress","clearShifted","hasShifted","clearLongshifted","hasLongshifted","gpio","getGpio","GPIO","pull","debounce","shifter","getShifter","longduration","pressed","getPressed","released","getReleased","setGpio","setPull","setDebounce","setShifter","setLongduration","setPressed","setReleased","getPull","getDebounce","getLongduration","clearGpio","hasGpio","clearShifter","hasShifter","clearPressed","hasPressed","clearReleased","hasReleased","buttonList","toObjectList","getButtonList","addButton","length","writeRepeatedMessage","setProto3StringField","getRepeatedWrapperField","setButtonList","setRepeatedWrapperField","opt_value","opt_index","addToRepeatedWrapperField","clearButtonList","enable","delayMs","setEnable","setDelayMs","getEnable","getDelayMs","a","getA","b","getB","sw","getSw","knobonly","getKnobonly","volume","setA","setB","setSw","setKnobonly","setVolume","getVolume","clearA","hasA","clearB","hasB","clearSw","hasSw","clearKnobonly","hasKnobonly","ButtonAction","ACTRLS_NONE","ACTRLS_POWER","ACTRLS_VOLUP","ACTRLS_VOLDOWN","ACTRLS_TOGGLE","ACTRLS_PLAY","ACTRLS_PAUSE","ACTRLS_STOP","ACTRLS_REW","ACTRLS_FWD","ACTRLS_PREV","ACTRLS_NEXT","BCTRLS_UP","BCTRLS_DOWN","BCTRLS_LEFT","BCTRLS_RIGHT","BCTRLS_PS1","BCTRLS_PS2","BCTRLS_PS3","BCTRLS_PS4","BCTRLS_PS5","BCTRLS_PS6","BCTRLS_PS7","BCTRLS_PS8","BCTRLS_PS9","BCTRLS_PS10","KNOB_LEFT","KNOB_RIGHT","KNOB_PUSH","ACTRLS_SLEEP","DeviceTypeEnum","UNSPECIFIED_TYPE","DEVTYPE_SPI","DEVTYPE_I2C","DEVTYPE__RMII","PortEnum","UNSPECIFIED_SYSTPORT","SYSTEM","DAC_PORT","HostEnum","UNSPECIFIED_HOST","HOST0","HOST1","DacControlSet_pb","I2CBus_pb","DAC","bck","getBck","ws","getWs","dout","getDout","mck","mute","getMute","model","i2c","getI2c","I2CBus","daccontrolset","getDaccontrolset","DacControlSet","jackMutesAmp","setBck","setWs","setDout","setMck","setMute","setModel","setI2c","setDaccontrolset","setJackMutesAmp","getMck","getModel","getJackMutesAmp","clearBck","hasBck","clearWs","hasWs","clearDout","hasDout","clearMute","hasMute","clearI2c","hasI2c","clearDaccontrolset","hasDaccontrolset","DACModelEnum","UNSPECIFIED_MODEL","TAS57XX","TAS5713","AC101","WM8978","ES8388","I2S","CS4265","MCKEnum","UNSPECIFIED_MCK","MCK0","MCK1","MCK2","ControlCommand","ControlItem","RegisterAction","GpioAction","DelayAction","commandsList","getCommandsList","addCommands","setCommandsList","clearCommandsList","type","itemsList","getItemsList","setType","addItems","getType","setItemsList","clearItemsList","ItemTypeCase","ITEM_TYPE_NOT_SET","REG_ACTION","GPIO_ACTION","DELAY_ACTION","getItemTypeCase","regAction","getRegAction","gpioAction","getGpioAction","delayAction","getDelayAction","setRegAction","setGpioAction","setDelayAction","setOneofWrapperField","clearRegAction","hasRegAction","clearGpioAction","hasGpioAction","clearDelayAction","hasDelayAction","reg","val","mode","setReg","setVal","setMode","getReg","getVal","getMode","level","setLevel","getLevel","delay","setDelay","getDelay","ControlCommandType","INIT","POWER_ON","POWER_OFF","SPEAKER_ON","SPEAKER_OFF","HEADSET_ON","HEADSET_OFF","GpioActionLevel","ACTION_LEVEL_UNDEFINED","ACTION_LEVEL_1","ACTION_LEVEL_0","Mode","REG_MODE_NOTHING","REG_MODE_OR","REG_MODE_AND","Common_pb","DAC_pb","Display_pb","Buttons_pb","Battery_pb","Ethernet_pb","SPDIF","SPIBus","LEDStrip","Infrared","Dev","data","getData","clk","getClk","setData","setClk","clearData","hasData","clearClk","hasClk","mosi","getMosi","miso","getMiso","dc","getDc","host","setMosi","setMiso","setDc","setHost","getHost","clearMosi","hasMosi","clearMiso","hasMiso","clearDc","hasDc","stripType","setLength","setStripType","getLength","getStripType","spi","getSpi","dac","getDac","spdif","getSpdif","display","getDisplay","Display","gpioExpList","getGpioExpList","GPIOExp","ledStrip","getLedStrip","rotary","getRotary","buttonsList","getButtonsList","eth","getEth","Eth","battery","getBattery","ir","getIr","setSpi","setDac","setSpdif","setDisplay","addGpioExp","setLedStrip","setRotary","addButtons","setEth","setBattery","setIr","clearSpi","hasSpi","clearDac","hasDac","clearSpdif","hasSpdif","clearDisplay","hasDisplay","setGpioExpList","clearGpioExpList","clearLedStrip","hasLedStrip","clearRotary","hasRotary","setButtonsList","clearButtonsList","clearEth","hasEth","clearBattery","hasBattery","clearIr","hasIr","LEDStripType","LS_UNKNOWN","LS_WS2812","LS_SK6812","LS_APA106","InfraredType","IR_UNKNOWN","IR_RC5","IR_NEC","DispOffsets","I2CDisplay","SPIDisplay","DispCommon","height","width","setHeight","setWidth","getHeight","getWidth","address","setAddress","getAddress","cs","getCs","speed","setCs","setSpeed","getSpeed","clearCs","hasCs","hflip","vflip","driver","bitdepth","back","getBack","reset","getReset","ready","getReady","offsets","getOffsets","rotate","invert","colowSwap","setHflip","setVflip","setDriver","setBitdepth","setBack","setReset","setReady","setOffsets","setRotate","setInvert","setColowSwap","getHflip","getVflip","getDriver","getBitdepth","getRotate","getInvert","getColowSwap","clearBack","hasBack","clearReset","hasReset","clearReady","hasReady","clearOffsets","hasOffsets","DisptypeCase","DISPTYPE_NOT_SET","I2C","SPI","getDisptypeCase","common","getCommon","setCommon","clearCommon","hasCommon","DisplayDriverEnum","UNSPECIFIED_DRIVER","SSD1306","SSD1322","SSD1326","SSD1327","SH1106","SSD1675","ST7735","ST7789","ILI9341","ILI9341_24","SSD1351","Equalizer","gainsList","getRepeatedFloatingPointField","loudness","values","isDelimited","readPackedFloat","i","addGains","setLoudness","getGainsList","writePackedFloat","getLoudness","setGainsList","setField","addToRepeatedField","clearGainsList","EthCommon","EthSPI","EthRMII","rst","getRst","ethtmoutS","setRst","setEthtmoutS","getEthtmoutS","clearRst","hasRst","intr","getIntr","setIntr","clearIntr","hasIntr","mdc","getMdc","mdio","getMdio","setMdc","setMdio","clearMdc","hasMdc","clearMdio","hasMdio","EthtypeCase","ETHTYPE_NOT_SET","RMII","getEthtypeCase","rmii","getRmii","setRmii","clearRmii","hasRmii","EthModelEnum","UNSPECIFIED_ETHMODEL","LAN8720","DM9051","W5500","EthType","UNSPECIFIED_ETH","LED","Gpios","GPIOExpI2C","GPIOExpSPI","pin","setPin","getPin","brightness","ledType","setBrightness","setLedType","getBrightness","getLedType","greenled","getGreenled","redled","getRedled","audiojack","getAudiojack","amp","getAmp","power","getPower","jack","getJack","spkfault","getSpkfault","vcc","getVcc","gnd","getGnd","setGreenled","setRedled","setAudiojack","setAmp","setPower","setJack","setSpkfault","setVcc","setGnd","clearGreenled","hasGreenled","clearRedled","hasRedled","clearAudiojack","hasAudiojack","clearAmp","hasAmp","clearPower","hasPower","clearJack","hasJack","clearSpkfault","hasSpkfault","clearVcc","hasVcc","clearGnd","hasGnd","ExptypeCase","EXPTYPE_NOT_SET","getExptypeCase","addr","base","count","setAddr","setBase","setCount","getAddr","getBase","getCount","LevelsEnum","L_LOW","L_HIGH","LedTypesEnum","UNKNOWN","LED_TYPE_GPIO","LED_TYPE_WS2812","GPIOExpModelEnum","UNSPECIFIED_EXP","PCA9535","PCA85XX","MCP23017","MCP23S17","sda","getSda","scl","getScl","setSda","setScl","clearSda","hasSda","clearScl","hasScl","I2CPortEnum","UNSPECIFIED_PORT","I2CPORT0","I2CPORT1","Names","device","airplay","spotify","bluetooth","squeezelite","wifiApName","setDevice","setAirplay","setSpotify","setBluetooth","setSqueezelite","setWifiApName","getDevice","getAirplay","getSpotify","getBluetooth","getSqueezelite","getWifiApName","google_protobuf_timestamp_pb","IP","WifiSTAEntry","WifiAP","Server","NetworkConfig","ip","netmask","gw","setIp","setNetmask","setGw","getIp","getNetmask","getGw","ssid","bssid","authType","radioType","lastTry","getLastTry","Timestamp","lastSeen","getLastSeen","connected","password","rssi","setSsid","setBssid","setAuthType","setRadioType","setLastTry","setLastSeen","setConnected","setPassword","setRssi","getSsid","getBssid","getAuthType","getRadioType","getConnected","getPassword","getRssi","clearLastTry","hasLastTry","clearLastSeen","hasLastSeen","authMode","hidden","maxConnection","beaconInterval","setAuthMode","setHidden","setMaxConnection","setBeaconInterval","getAuthMode","getHidden","getMaxConnection","getBeaconInterval","clearIp","hasIp","cport","setCport","getCport","disableDhcp","manualIp","getManualIp","credentialsList","getCredentialsList","ap","getAp","staPollingMaxS","apDurationS","staPollingMinS","dhcpTmoutS","ethBoot","maxWifiRetry","maxApNum","maxSsidSize","maxPasswordSize","taskPriority","powerSaveMode","maxInitialWifiAttempt","setDisableDhcp","setManualIp","addCredentials","setAp","setStaPollingMaxS","setApDurationS","setStaPollingMinS","setDhcpTmoutS","setEthBoot","setMaxWifiRetry","setMaxApNum","setMaxSsidSize","setMaxPasswordSize","setTaskPriority","setPowerSaveMode","setMaxInitialWifiAttempt","getDisableDhcp","getStaPollingMaxS","getApDurationS","getStaPollingMinS","getDhcpTmoutS","getEthBoot","getMaxWifiRetry","getMaxApNum","getMaxSsidSize","getMaxPasswordSize","getTaskPriority","getPowerSaveMode","getMaxInitialWifiAttempt","PowerSaveTypeEnum","WIFI_PS_NONE","WIFI_PS_MIN_MODEM","WIFI_PS_MAX_MODEM","clearManualIp","hasManualIp","setCredentialsList","clearCredentialsList","clearAp","hasAp","WifiAuthTypeEnum","AUTH_UNKNOWN","AUTH_OPEN","AUTH_WEP","AUTH_WPA_PSK","AUTH_WPA2_PSK","AUTH_WPA_WPA2_PSK","AUTH_WPA2_ENTERPRISE","AUTH_WPA3_PSK","AUTH_WPA2_WPA3_PSK","AUTH_WAPI_PSK","WifiRadioTypesEnum","PHY_UNKNOWN","PHY_11B","PHY_11G","PHY_11N","PHY_LR","PHY_WPS","PHY_FTM_RESPONDER","PHY_FTM_INITIATOR","Artwork_pb","Spotify_pb","AirPlay_pb","Squeezelite_pb","Equalizer_pb","SleepService","Telnet","Metadata","BluetoothSink","Services","spurious","sleep","getSleep","wakeList","getWakeList","rtcList","getRtcList","batt","setSpurious","setSleep","addWake","addRtc","setBatt","getSpurious","getBatt","clearSleep","hasSleep","setWakeList","clearWakeList","setRtcList","clearRtcList","block","buffer","setBlock","setBuffer","getBlock","getBuffer","format","pause","artwork","getArtwork","setFormat","setPause","setArtwork","getFormat","getPause","clearArtwork","hasArtwork","metadata","getMetadata","cspot","getCspot","Spotify","squeezeliteProfilesList","getSqueezeliteProfilesList","SqueezeliteProfile","releaseUrl","btSink","getBtSink","statistics","telnet","getTelnet","equalizer","getEqualizer","currentProfile","setMetadata","setCspot","addSqueezeliteProfiles","setReleaseUrl","setBtSink","setStatistics","setTelnet","setEqualizer","setCurrentProfile","getReleaseUrl","getStatistics","getCurrentProfile","clearMetadata","hasMetadata","clearCspot","hasCspot","clearAirplay","hasAirplay","setSqueezeliteProfilesList","clearSqueezeliteProfilesList","clearBtSink","hasBtSink","clearTelnet","hasTelnet","clearEqualizer","hasEqualizer","TelnetEnableEnum","SERIAL_ONLY","TELNET","TELNET_SERIAL","bitrate","zeroconf","setBitrate","setZeroconf","getBitrate","getZeroconf","OutputBT","ResampleOptions","RatesOption","BufferOption","DebugOptions","Squeezelite","sinkName","setSinkName","getSinkName","algorithm","interpolateFilterCoefficients","setAlgorithm","setInterpolateFilterCoefficients","getAlgorithm","getInterpolateFilterCoefficients","min","max","listList","getRepeatedField","setMin","setMax","readPackedEnum","addList","getMin","getMax","getListList","writePackedEnum","setListList","clearListList","stream","output","setStream","setOutput","getStream","getOutput","decode","slimproto","all","setDecode","setSlimproto","setAll","getDecode","getSlimproto","getAll","outputType","rates","getRates","ampGpioTimeout","wavAiffHeaderParsing","serverNameIp","serverPort","outputBt","getOutputBt","log","getLog","maxRate","buffers","getBuffers","resample","includedCodexList","excludedCodexList","setOutputType","setRates","setAmpGpioTimeout","setWavAiffHeaderParsing","setServerNameIp","setServerPort","setOutputBt","setLog","setMaxRate","setBuffers","setResample","addIncludedCodex","addExcludedCodex","getOutputType","getAmpGpioTimeout","getWavAiffHeaderParsing","getServerNameIp","getServerPort","getMaxRate","getResample","getIncludedCodexList","getExcludedCodexList","clearRates","hasRates","clearOutputBt","hasOutputBt","clearLog","hasLog","clearBuffers","hasBuffers","setIncludedCodexList","clearIncludedCodexList","setExcludedCodexList","clearExcludedCodexList","name","profile","getProfile","setName","setProfile","getName","clearProfile","hasProfile","OutputTypeEnum","OUTPUT_UNKNOWN","OUTPUT_I2S","OUTPUT_SPDIF","OUTPUT_BLUETOOTH","ResampleAlgorithm","RA_DISABLED","RA_BASIC_LINEAR","RA_THIRTEEN_TAPS","RA_TWENTY_ONE_TAPS","SampleRate","SAMPLE_RATE_UNSPECIFIED","SAMPLE_RATE_8000","SAMPLE_RATE_11025","SAMPLE_RATE_12000","SAMPLE_RATE_16000","SAMPLE_RATE_22050","SAMPLE_RATE_24000","SAMPLE_RATE_32000","SAMPLE_RATE_44100","SAMPLE_RATE_48000","SAMPLE_RATE_88200","SAMPLE_RATE_96000","SAMPLE_RATE_176400","SAMPLE_RATE_192000","SAMPLE_RATE_352800","SAMPLE_RATE_384000","SAMPLE_RATE_705600","SAMPLE_RATE_768000","DebugLevelEnum","DEFAULT","ERROR","WARN","INFO","SDEBUG","CodexEnum","C_UNDEFINED","C_ALAC","C_OGG","C_OPS","C_FLAC","C_PCM","C_MP3","C_MAD","C_MPG","Services_pb","Devices_pb","Names_pb","Network_pb","Config","gpios","getGpios","dev","getDev","services","getServices","names","getNames","target","net","getNet","setGpios","setDev","setServices","setNames","setTarget","setNet","getTarget","clearGpios","hasGpios","clearDev","hasDev","clearServices","hasServices","clearNames","hasNames","clearNet","hasNet","google_protobuf_descriptor_pb","CustomOptions","DefaultValueCase","DEFAULT_VALUE_NOT_SET","V_STRING","V_UINT32","V_INT32","V_UINT64","V_INT64","V_DOUBLE","V_FLOAT","V_BOOL","V_ENUM","V_BYTES","V_MSG","getDefaultValueCase","initFromMac","constPrefix","readOnly","vString","vUint32","vInt32","vUint64","vInt64","vDouble","vFloat","vBool","vEnum","vBytes","getVBytes_asB64","vMsg","getVMsg_asB64","globalName","setInitFromMac","setConstPrefix","setReadOnly","setVString","setVUint32","setVInt32","readUint64","setVUint64","readInt64","setVInt64","readDouble","setVDouble","setVFloat","setVBool","setVEnum","readBytes","setVBytes","setVMsg","setGlobalName","getInitFromMac","getConstPrefix","getReadOnly","writeUint64","writeInt64","writeDouble","writeBytes","getGlobalName","getVString","clearVString","hasVString","getVUint32","clearVUint32","hasVUint32","getVInt32","clearVInt32","hasVInt32","getVUint64","clearVUint64","hasVUint64","getVInt64","clearVInt64","hasVInt64","getVDouble","clearVDouble","hasVDouble","getVFloat","clearVFloat","hasVFloat","getVBool","clearVBool","hasVBool","getVEnum","clearVEnum","hasVEnum","getVBytes","bytesAsB64","getVBytes_asU8","bytesAsU8","clearVBytes","hasVBytes","getVMsg","getVMsg_asU8","clearVMsg","hasVMsg","custFile","ExtensionFieldInfo","FileOptions","extensionsBinary","ExtensionFieldBinaryInfo","extensions","custMsg","MessageOptions","custEnum","EnumOptions","custField","FieldOptions","NanoPBOptions","maxSize","maxLength","maxCount","intSize","longNames","packedStruct","packedEnum","skipMessage","noUnions","msgid","anonymousOneof","proto3","proto3SingularMsgs","enumToString","fixedLength","fixedCount","submsgCallback","mangleNames","callbackDatatype","callbackFunction","descriptorsize","defaultHas","includeList","excludeList","pb_package","typeOverride","sortByTag","setMaxSize","setMaxLength","setMaxCount","setIntSize","setLongNames","setPackedStruct","setPackedEnum","setSkipMessage","setNoUnions","setMsgid","setAnonymousOneof","setProto3","setProto3SingularMsgs","setEnumToString","setFixedLength","setFixedCount","setSubmsgCallback","setMangleNames","setCallbackDatatype","setCallbackFunction","setDescriptorsize","setDefaultHas","addInclude","addExclude","setPackage","setTypeOverride","setSortByTag","getIncludeList","writeRepeatedString","getExcludeList","getMaxSize","clearMaxSize","hasMaxSize","getMaxLength","clearMaxLength","hasMaxLength","getMaxCount","clearMaxCount","hasMaxCount","getIntSize","clearIntSize","hasIntSize","clearType","hasType","getLongNames","clearLongNames","hasLongNames","getPackedStruct","clearPackedStruct","hasPackedStruct","getPackedEnum","clearPackedEnum","hasPackedEnum","getSkipMessage","clearSkipMessage","hasSkipMessage","getNoUnions","clearNoUnions","hasNoUnions","getMsgid","clearMsgid","hasMsgid","getAnonymousOneof","clearAnonymousOneof","hasAnonymousOneof","getProto3","clearProto3","hasProto3","getProto3SingularMsgs","clearProto3SingularMsgs","hasProto3SingularMsgs","getEnumToString","clearEnumToString","hasEnumToString","getFixedLength","clearFixedLength","hasFixedLength","getFixedCount","clearFixedCount","hasFixedCount","getSubmsgCallback","clearSubmsgCallback","hasSubmsgCallback","getMangleNames","clearMangleNames","hasMangleNames","getCallbackDatatype","clearCallbackDatatype","hasCallbackDatatype","getCallbackFunction","clearCallbackFunction","hasCallbackFunction","getDescriptorsize","clearDescriptorsize","hasDescriptorsize","getDefaultHas","clearDefaultHas","hasDefaultHas","setIncludeList","clearIncludeList","setExcludeList","clearExcludeList","getPackage","clearPackage","hasPackage","getTypeOverride","clearTypeOverride","hasTypeOverride","getSortByTag","clearSortByTag","hasSortByTag","FieldType","FT_DEFAULT","FT_CALLBACK","FT_POINTER","FT_STATIC","FT_IGNORE","FT_INLINE","IntSize","IS_DEFAULT","IS_8","IS_16","IS_32","IS_64","TypenameMangling","M_NONE","M_STRIP_PACKAGE","M_FLATTEN","M_PACKAGE_INITIALS","DescriptorSize","DS_AUTO","DS_1","DS_2","DS_4","DS_8","nanopbFileopt","nanopbMsgopt","nanopbEnumopt","nanopb","__createBinding","Object","create","o","m","k","k2","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__setModuleDefault","v","__importStar","mod","result","hasOwnProperty","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","next","e","rejected","done","then","apply","__importDefault","he","js_cookie_1","bootstrap","hFlash","$","flashState","StartOTA","handleReboot","link","removeClass","prop","delayReboot","get_control_option_value","ctrl","id","opt","attr","replace","includes","toString","handleNVSVisible","nvs_previous_checked","matchResult","match","isEnabled","default","checkBoxElement","checked","recovery","show","hide","NVSType","hideSurrounding","parent","assign","String","args","number","index","parseInt","encodeHTML","encode","Date","toLocalShort","toLocaleString","dateStyle","timeStyle","btIcons","bt_playing","label","icon","bt_disconnected","bt_neutral","bt_connecting","bt_connected","bt_disabled","play_arrow","stop","batIcons","ranges","t","btStateIcons","sub","connectReturnCode","OK","FAIL","DISC","LOST","RESTORE","ETH","taskStates","NONE","REBOOT_TO_RECOVERY","SET_FWURL","FLASHING","DONE","UPLOADING","UPLOADCOMPLETE","_state","olderRecovery","statusText","flashURL","flashFileName","statusPercent","Completed","prevRecovery","updateModal","Modal","document","getElementById","UpdateProgress","isStateError","html","isStateUploadComplete","isStateNone","isStateRebootRecovery","isStateSetUrl","isStateFlashing","isStateDone","isStateUploading","init","SetStateError","addClass","SetStateNone","SetStateRebootRecovery","SetStatusText","ajax","url","context","dataType","method","cache","contentType","JSON","stringify","timestamp","now","error","xhr","_ajaxOptions","thrownError","_a","setOTAError","status","complete","response","SetStateSetUrl","post_config","fwurl","SetStateFlashing","SetStateDone","SetStateUploading","SetStateUploadComplete","isFlashExecuting","keys","find","x","setOTATargets","fileInput","files","SetStatusPercent","ShowDialog","pct","pctChanged","txt","changed","css","text","logEvent","TargetReadyStartOTA","UploadLocalFile","xhttp","XMLHttpRequest","boundHandleUploadProgressEvent","HandleUploadProgressEvent","bind","boundsetOTAError","upload","addEventListener","onreadystatechange","readyState","open","send","console","Math","round","loaded","total","EventTargetStatus","_b","ota_pct","ota_dsc","EventOTAMessageClass","otaData","parse","fun","presetsloaded","is_i2c_locked","messageInterval","confPayload","config","handleExceptionResponse","isConnected","ConnectedTo","getIcon","icons","handleTemplateTypeRadio","outtype","children","entries","commandDefaults","forEach","key","showLocalMessage","showCmdMessage","cmdname","msgtype","msgtext","append","color","escapedtext","substring","releaseURL","messagesHeld","i2s","C","W","Z","bt","SystemConfig","validOptions","codecs","apList","messagecount","messageseverity","LastCommandsState","NaN","ConnectingToSSID","hostName","versionName","prevmessage","project_name","depth","board_model","platform_name","preset_name","lmsBaseUrl","prevLMSIP","ConnectingToActions","promise","duration","setTimeout","reason","getConfigJson","slimMode","each","_index","element","entry","nvsTypeAttr","attributes","getNamedItem","nvsType","NVS_TYPE_I64","NVS_TYPE_I8","ota","empty","rdata","saveAutoexec1","commandLine","is","autoexec1","NVS_TYPE_STR","responseText","Result","setPlatformFilter","filter","toUpperCase","trigger","renderError","fieldname","errorFieldName","errorField","field","after","rssiToIcon","refreshAP","urc","ajaxSetup","timeout","getJSON","ms","sort","y","refreshAPHTML2","formatAP","auth","rssi_icon","auth_icon","h","wifiSelector","prepend","siblings","first","rssiIconObj","iconTextContent","showTask","task","debug","nme","cpu","st","minstk","bprio","cprio","num","getMessages","msgAge","current_time","sent_time","msgTime","setTime","getTime","class","statsData","ntasks","tasks","taskList","showMessage","msgparts","split","fail","ajaxOptions","handleWifiDialog","Action","STS","ap_ssid","ap_pwd","setIcons","offline","htmlEntry","textContent","getAttribute","handleNetworkStatus","hasConnectionChanged","pwd","dhcpname","assignStatusToNetworkConnection","checkStatus","handleRecoveryMode","tt","bt_status","bt_sub_status","iconIndex","handlebtstate","version","Voltage","bat_icon","voltage","iconEntry","entryRanges","batteryToIcon","lms_ip","lms_port","baseUrl","success","Number","Jack","getLongOps","longopts","severity","MESSAGING_INFO","MESSAGING_WARNING","MESSAGING_ERROR","setAttribute","on","stringVal","startsWith","inputField","not","invalid","map","item","trim","join","test","event","relatedTarget","CONN","MAN","_this","FileReader","file","fr","onload","ex","alert","readAsText","slideUp","slideDown","preventDefault","currentValue","originalValue","set","createElement","href","URL","createObjectURL","Blob","body","appendChild","click","removeChild","branches","release","branch","push","fwb","assets","asset","browser_download_url","namecomponents","ver","cfg","bits","substr","lastIndexOf","created_at","idf","trclass","payload","request","Payload","Type","CONFIG","GET","serializedPayload","processData","Uint8Array","title","jqXHR","textStatus","errorThrown","getConfig","commands","command","cmdParts","isConfig","targetDiv","innerhtml","help","argtable","arg","placeholder","datatype","ctrlname","curvalue","hasvalue","shortopts","checkbox","extraclass","mincount","glossary","choice","off","runCommand","ctrlselector","ctrlValue","_","jqxhr","err","setURL","button","dataset","reboot","cmdstring","fields","allfields","querySelectorAll","selJson","cmd","model_config","storedval","handleHWPreset","qts","isSelect","tagName","hasValue","validVal","indexOf","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","O","chunkIds","fn","priority","notFulfilled","Infinity","j","every","splice","r","d","definition","g","Symbol","toStringTag","nmd","paths","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js b/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js deleted file mode 100644 index d33a8508..00000000 --- a/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js +++ /dev/null @@ -1,2 +0,0 @@ -(()=>{var e,t={874:(e,t,o)=>{var r=o(19),n=r,i=function(){return this?this:"undefined"!=typeof window?window:void 0!==i?i:"undefined"!=typeof self?self:Function("return this")()}.call(null),s=o(21);n.object.extend(proto,s),n.exportSymbol("proto.Conf.Artwork",null,i),n.exportSymbol("proto.Conf.Battery",null,i),n.exportSymbol("proto.Conf.BatteryAttenEnum",null,i),n.exportSymbol("proto.Conf.BatteryChannelEnum",null,i),n.exportSymbol("proto.Conf.Button",null,i),n.exportSymbol("proto.Conf.ButtonAction",null,i),n.exportSymbol("proto.Conf.ButtonActions",null,i),n.exportSymbol("proto.Conf.Config",null,i),n.exportSymbol("proto.Conf.DACDev",null,i),n.exportSymbol("proto.Conf.DACModelEnum",null,i),n.exportSymbol("proto.Conf.Dev",null,i),n.exportSymbol("proto.Conf.DeviceTypeEnum",null,i),n.exportSymbol("proto.Conf.DispCommon",null,i),n.exportSymbol("proto.Conf.DispOffsets",null,i),n.exportSymbol("proto.Conf.DisplayDev",null,i),n.exportSymbol("proto.Conf.DisplayDev.DisptypeCase",null,i),n.exportSymbol("proto.Conf.DisplayDriverEnum",null,i),n.exportSymbol("proto.Conf.Eth",null,i),n.exportSymbol("proto.Conf.Eth.EthtypeCase",null,i),n.exportSymbol("proto.Conf.EthCommon",null,i),n.exportSymbol("proto.Conf.EthModelEnum",null,i),n.exportSymbol("proto.Conf.EthRMII",null,i),n.exportSymbol("proto.Conf.EthSPI",null,i),n.exportSymbol("proto.Conf.EthType",null,i),n.exportSymbol("proto.Conf.GPIO",null,i),n.exportSymbol("proto.Conf.GPIOExp",null,i),n.exportSymbol("proto.Conf.GPIOExpModelEnum",null,i),n.exportSymbol("proto.Conf.Gpios",null,i),n.exportSymbol("proto.Conf.HostEnum",null,i),n.exportSymbol("proto.Conf.I2CBus",null,i),n.exportSymbol("proto.Conf.I2CDisplay",null,i),n.exportSymbol("proto.Conf.I2CPortEnum",null,i),n.exportSymbol("proto.Conf.LEDStrip",null,i),n.exportSymbol("proto.Conf.MCKEnum",null,i),n.exportSymbol("proto.Conf.Metadata",null,i),n.exportSymbol("proto.Conf.PortEnum",null,i),n.exportSymbol("proto.Conf.Rotary",null,i),n.exportSymbol("proto.Conf.SPDIFDev",null,i),n.exportSymbol("proto.Conf.SPIBus",null,i),n.exportSymbol("proto.Conf.SPIDisplay",null,i),n.exportSymbol("proto.Conf.Services",null,i),n.exportSymbol("proto.Conf.SleepService",null,i),n.exportSymbol("proto.Conf.WS2812",null,i),proto.Conf.GPIO=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.GPIO,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.GPIO.displayName="proto.Conf.GPIO"),proto.Conf.I2CBus=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.I2CBus,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.I2CBus.displayName="proto.Conf.I2CBus"),proto.Conf.DACDev=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.DACDev,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.DACDev.displayName="proto.Conf.DACDev"),proto.Conf.SPDIFDev=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.SPDIFDev,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.SPDIFDev.displayName="proto.Conf.SPDIFDev"),proto.Conf.DispOffsets=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.DispOffsets,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.DispOffsets.displayName="proto.Conf.DispOffsets"),proto.Conf.DispCommon=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.DispCommon,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.DispCommon.displayName="proto.Conf.DispCommon"),proto.Conf.I2CDisplay=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.I2CDisplay,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.I2CDisplay.displayName="proto.Conf.I2CDisplay"),proto.Conf.SPIDisplay=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.SPIDisplay,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.SPIDisplay.displayName="proto.Conf.SPIDisplay"),proto.Conf.SPIBus=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.SPIBus,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.SPIBus.displayName="proto.Conf.SPIBus"),proto.Conf.DisplayDev=function(e){r.Message.initialize(this,e,0,-1,null,proto.Conf.DisplayDev.oneofGroups_)},n.inherits(proto.Conf.DisplayDev,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.DisplayDev.displayName="proto.Conf.DisplayDev"),proto.Conf.GPIOExp=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.GPIOExp,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.GPIOExp.displayName="proto.Conf.GPIOExp"),proto.Conf.WS2812=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.WS2812,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.WS2812.displayName="proto.Conf.WS2812"),proto.Conf.LEDStrip=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.LEDStrip,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.LEDStrip.displayName="proto.Conf.LEDStrip"),proto.Conf.Rotary=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Rotary,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Rotary.displayName="proto.Conf.Rotary"),proto.Conf.ButtonActions=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.ButtonActions,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.ButtonActions.displayName="proto.Conf.ButtonActions"),proto.Conf.Button=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Button,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Button.displayName="proto.Conf.Button"),proto.Conf.EthCommon=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.EthCommon,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.EthCommon.displayName="proto.Conf.EthCommon"),proto.Conf.EthSPI=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.EthSPI,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.EthSPI.displayName="proto.Conf.EthSPI"),proto.Conf.EthRMII=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.EthRMII,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.EthRMII.displayName="proto.Conf.EthRMII"),proto.Conf.Eth=function(e){r.Message.initialize(this,e,0,-1,null,proto.Conf.Eth.oneofGroups_)},n.inherits(proto.Conf.Eth,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Eth.displayName="proto.Conf.Eth"),proto.Conf.Battery=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Battery,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Battery.displayName="proto.Conf.Battery"),proto.Conf.Gpios=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Gpios,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Gpios.displayName="proto.Conf.Gpios"),proto.Conf.Dev=function(e){r.Message.initialize(this,e,0,-1,proto.Conf.Dev.repeatedFields_,null)},n.inherits(proto.Conf.Dev,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Dev.displayName="proto.Conf.Dev"),proto.Conf.SleepService=function(e){r.Message.initialize(this,e,0,-1,proto.Conf.SleepService.repeatedFields_,null)},n.inherits(proto.Conf.SleepService,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.SleepService.displayName="proto.Conf.SleepService"),proto.Conf.Artwork=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Artwork,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Artwork.displayName="proto.Conf.Artwork"),proto.Conf.Metadata=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Metadata,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Metadata.displayName="proto.Conf.Metadata"),proto.Conf.Services=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Services,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Services.displayName="proto.Conf.Services"),proto.Conf.Config=function(e){r.Message.initialize(this,e,0,-1,null,null)},n.inherits(proto.Conf.Config,r.Message),n.DEBUG&&!COMPILED&&(proto.Conf.Config.displayName="proto.Conf.Config"),r.Message.GENERATE_TO_OBJECT&&(proto.Conf.GPIO.prototype.toObject=function(e){return proto.Conf.GPIO.toObject(e,this)},proto.Conf.GPIO.toObject=function(e,t){var o={pin:r.Message.getFieldWithDefault(t,1,0),level:r.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.GPIO.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.GPIO;return proto.Conf.GPIO.deserializeBinaryFromReader(o,t)},proto.Conf.GPIO.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setPin(o);break;case 2:o=t.readInt32();e.setLevel(o);break;default:t.skipField()}}return e},proto.Conf.GPIO.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.GPIO.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.GPIO.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getPin())&&t.writeInt32(1,o),null!=(o=r.Message.getField(e,2))&&t.writeInt32(2,o)},proto.Conf.GPIO.prototype.getPin=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.GPIO.prototype.setPin=function(e){return r.Message.setProto3IntField(this,1,e)},proto.Conf.GPIO.prototype.getLevel=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.GPIO.prototype.setLevel=function(e){return r.Message.setField(this,2,e)},proto.Conf.GPIO.prototype.clearLevel=function(){return r.Message.setField(this,2,void 0)},proto.Conf.GPIO.prototype.hasLevel=function(){return null!=r.Message.getField(this,2)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.I2CBus.prototype.toObject=function(e){return proto.Conf.I2CBus.toObject(e,this)},proto.Conf.I2CBus.toObject=function(e,t){var o,n={port:r.Message.getFieldWithDefault(t,1,0),speed:r.Message.getFieldWithDefault(t,2,0),sda:(o=t.getSda())&&proto.Conf.GPIO.toObject(e,o),scl:(o=t.getScl())&&proto.Conf.GPIO.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.I2CBus.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.I2CBus;return proto.Conf.I2CBus.deserializeBinaryFromReader(o,t)},proto.Conf.I2CBus.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setPort(o);break;case 2:o=t.readInt32();e.setSpeed(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setSda(o);break;case 4:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setScl(o);break;default:t.skipField()}}return e},proto.Conf.I2CBus.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.I2CBus.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.I2CBus.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getPort())&&t.writeEnum(1,o),0!==(o=e.getSpeed())&&t.writeInt32(2,o),null!=(o=e.getSda())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getScl())&&t.writeMessage(4,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.I2CBus.prototype.getPort=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.I2CBus.prototype.setPort=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.I2CBus.prototype.getSpeed=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.I2CBus.prototype.setSpeed=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.I2CBus.prototype.getSda=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.I2CBus.prototype.setSda=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.I2CBus.prototype.clearSda=function(){return this.setSda(void 0)},proto.Conf.I2CBus.prototype.hasSda=function(){return null!=r.Message.getField(this,3)},proto.Conf.I2CBus.prototype.getScl=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,4)},proto.Conf.I2CBus.prototype.setScl=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.I2CBus.prototype.clearScl=function(){return this.setScl(void 0)},proto.Conf.I2CBus.prototype.hasScl=function(){return null!=r.Message.getField(this,4)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.DACDev.prototype.toObject=function(e){return proto.Conf.DACDev.toObject(e,this)},proto.Conf.DACDev.toObject=function(e,t){var o,n={bck:(o=t.getBck())&&proto.Conf.GPIO.toObject(e,o),ws:(o=t.getWs())&&proto.Conf.GPIO.toObject(e,o),dout:(o=t.getDout())&&proto.Conf.GPIO.toObject(e,o),mck:r.Message.getFieldWithDefault(t,4,0),mute:(o=t.getMute())&&proto.Conf.GPIO.toObject(e,o),model:r.Message.getFieldWithDefault(t,6,0),i2c:(o=t.getI2c())&&proto.Conf.I2CBus.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.DACDev.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.DACDev;return proto.Conf.DACDev.deserializeBinaryFromReader(o,t)},proto.Conf.DACDev.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setBck(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setWs(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setDout(o);break;case 4:o=t.readEnum();e.setMck(o);break;case 5:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setMute(o);break;case 6:o=t.readEnum();e.setModel(o);break;case 7:o=new proto.Conf.I2CBus;t.readMessage(o,proto.Conf.I2CBus.deserializeBinaryFromReader),e.setI2c(o);break;default:t.skipField()}}return e},proto.Conf.DACDev.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.DACDev.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.DACDev.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getBck())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getWs())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getDout())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getMck())&&t.writeEnum(4,o),null!=(o=e.getMute())&&t.writeMessage(5,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getModel())&&t.writeEnum(6,o),null!=(o=e.getI2c())&&t.writeMessage(7,o,proto.Conf.I2CBus.serializeBinaryToWriter)},proto.Conf.DACDev.prototype.getBck=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.DACDev.prototype.setBck=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.DACDev.prototype.clearBck=function(){return this.setBck(void 0)},proto.Conf.DACDev.prototype.hasBck=function(){return null!=r.Message.getField(this,1)},proto.Conf.DACDev.prototype.getWs=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.DACDev.prototype.setWs=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.DACDev.prototype.clearWs=function(){return this.setWs(void 0)},proto.Conf.DACDev.prototype.hasWs=function(){return null!=r.Message.getField(this,2)},proto.Conf.DACDev.prototype.getDout=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.DACDev.prototype.setDout=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.DACDev.prototype.clearDout=function(){return this.setDout(void 0)},proto.Conf.DACDev.prototype.hasDout=function(){return null!=r.Message.getField(this,3)},proto.Conf.DACDev.prototype.getMck=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.DACDev.prototype.setMck=function(e){return r.Message.setProto3EnumField(this,4,e)},proto.Conf.DACDev.prototype.getMute=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,5)},proto.Conf.DACDev.prototype.setMute=function(e){return r.Message.setWrapperField(this,5,e)},proto.Conf.DACDev.prototype.clearMute=function(){return this.setMute(void 0)},proto.Conf.DACDev.prototype.hasMute=function(){return null!=r.Message.getField(this,5)},proto.Conf.DACDev.prototype.getModel=function(){return r.Message.getFieldWithDefault(this,6,0)},proto.Conf.DACDev.prototype.setModel=function(e){return r.Message.setProto3EnumField(this,6,e)},proto.Conf.DACDev.prototype.getI2c=function(){return r.Message.getWrapperField(this,proto.Conf.I2CBus,7)},proto.Conf.DACDev.prototype.setI2c=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.DACDev.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.Conf.DACDev.prototype.hasI2c=function(){return null!=r.Message.getField(this,7)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.SPDIFDev.prototype.toObject=function(e){return proto.Conf.SPDIFDev.toObject(e,this)},proto.Conf.SPDIFDev.toObject=function(e,t){var o,r={dc:(o=t.getDc())&&proto.Conf.GPIO.toObject(e,o),data:(o=t.getData())&&proto.Conf.GPIO.toObject(e,o),clk:(o=t.getClk())&&proto.Conf.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.Conf.SPDIFDev.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.SPDIFDev;return proto.Conf.SPDIFDev.deserializeBinaryFromReader(o,t)},proto.Conf.SPDIFDev.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setDc(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setData(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setClk(o);break;default:t.skipField()}}return e},proto.Conf.SPDIFDev.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.SPDIFDev.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.SPDIFDev.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getDc())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getData())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getClk())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.SPDIFDev.prototype.getDc=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.SPDIFDev.prototype.setDc=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.SPDIFDev.prototype.clearDc=function(){return this.setDc(void 0)},proto.Conf.SPDIFDev.prototype.hasDc=function(){return null!=r.Message.getField(this,1)},proto.Conf.SPDIFDev.prototype.getData=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.SPDIFDev.prototype.setData=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.SPDIFDev.prototype.clearData=function(){return this.setData(void 0)},proto.Conf.SPDIFDev.prototype.hasData=function(){return null!=r.Message.getField(this,2)},proto.Conf.SPDIFDev.prototype.getClk=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.SPDIFDev.prototype.setClk=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.SPDIFDev.prototype.clearClk=function(){return this.setClk(void 0)},proto.Conf.SPDIFDev.prototype.hasClk=function(){return null!=r.Message.getField(this,3)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.DispOffsets.prototype.toObject=function(e){return proto.Conf.DispOffsets.toObject(e,this)},proto.Conf.DispOffsets.toObject=function(e,t){var o={height:r.Message.getFieldWithDefault(t,1,0),width:r.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.DispOffsets.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.DispOffsets;return proto.Conf.DispOffsets.deserializeBinaryFromReader(o,t)},proto.Conf.DispOffsets.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setHeight(o);break;case 2:o=t.readInt32();e.setWidth(o);break;default:t.skipField()}}return e},proto.Conf.DispOffsets.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.DispOffsets.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.DispOffsets.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getHeight())&&t.writeInt32(1,o),0!==(o=e.getWidth())&&t.writeInt32(2,o)},proto.Conf.DispOffsets.prototype.getHeight=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.DispOffsets.prototype.setHeight=function(e){return r.Message.setProto3IntField(this,1,e)},proto.Conf.DispOffsets.prototype.getWidth=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.DispOffsets.prototype.setWidth=function(e){return r.Message.setProto3IntField(this,2,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.DispCommon.prototype.toObject=function(e){return proto.Conf.DispCommon.toObject(e,this)},proto.Conf.DispCommon.toObject=function(e,t){var o,n={width:r.Message.getFieldWithDefault(t,1,0),height:r.Message.getFieldWithDefault(t,2,0),hflip:r.Message.getBooleanFieldWithDefault(t,3,!1),vflip:r.Message.getBooleanFieldWithDefault(t,4,!1),driver:r.Message.getFieldWithDefault(t,5,0),bitdepth:r.Message.getFieldWithDefault(t,6,0),back:(o=t.getBack())&&proto.Conf.GPIO.toObject(e,o),reset:(o=t.getReset())&&proto.Conf.GPIO.toObject(e,o),ready:(o=t.getReady())&&proto.Conf.GPIO.toObject(e,o),offsets:(o=t.getOffsets())&&proto.Conf.DispOffsets.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.DispCommon.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.DispCommon;return proto.Conf.DispCommon.deserializeBinaryFromReader(o,t)},proto.Conf.DispCommon.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setWidth(o);break;case 2:o=t.readInt32();e.setHeight(o);break;case 3:o=t.readBool();e.setHflip(o);break;case 4:o=t.readBool();e.setVflip(o);break;case 5:o=t.readEnum();e.setDriver(o);break;case 6:o=t.readInt32();e.setBitdepth(o);break;case 7:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setBack(o);break;case 8:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setReset(o);break;case 9:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setReady(o);break;case 10:o=new proto.Conf.DispOffsets;t.readMessage(o,proto.Conf.DispOffsets.deserializeBinaryFromReader),e.setOffsets(o);break;default:t.skipField()}}return e},proto.Conf.DispCommon.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.DispCommon.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.DispCommon.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getWidth())&&t.writeInt32(1,o),0!==(o=e.getHeight())&&t.writeInt32(2,o),(o=e.getHflip())&&t.writeBool(3,o),(o=e.getVflip())&&t.writeBool(4,o),0!==(o=e.getDriver())&&t.writeEnum(5,o),0!==(o=e.getBitdepth())&&t.writeInt32(6,o),null!=(o=e.getBack())&&t.writeMessage(7,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getReset())&&t.writeMessage(8,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getReady())&&t.writeMessage(9,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getOffsets())&&t.writeMessage(10,o,proto.Conf.DispOffsets.serializeBinaryToWriter)},proto.Conf.DispCommon.prototype.getWidth=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.DispCommon.prototype.setWidth=function(e){return r.Message.setProto3IntField(this,1,e)},proto.Conf.DispCommon.prototype.getHeight=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.DispCommon.prototype.setHeight=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.DispCommon.prototype.getHflip=function(){return r.Message.getBooleanFieldWithDefault(this,3,!1)},proto.Conf.DispCommon.prototype.setHflip=function(e){return r.Message.setProto3BooleanField(this,3,e)},proto.Conf.DispCommon.prototype.getVflip=function(){return r.Message.getBooleanFieldWithDefault(this,4,!1)},proto.Conf.DispCommon.prototype.setVflip=function(e){return r.Message.setProto3BooleanField(this,4,e)},proto.Conf.DispCommon.prototype.getDriver=function(){return r.Message.getFieldWithDefault(this,5,0)},proto.Conf.DispCommon.prototype.setDriver=function(e){return r.Message.setProto3EnumField(this,5,e)},proto.Conf.DispCommon.prototype.getBitdepth=function(){return r.Message.getFieldWithDefault(this,6,0)},proto.Conf.DispCommon.prototype.setBitdepth=function(e){return r.Message.setProto3IntField(this,6,e)},proto.Conf.DispCommon.prototype.getBack=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,7)},proto.Conf.DispCommon.prototype.setBack=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.DispCommon.prototype.clearBack=function(){return this.setBack(void 0)},proto.Conf.DispCommon.prototype.hasBack=function(){return null!=r.Message.getField(this,7)},proto.Conf.DispCommon.prototype.getReset=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,8)},proto.Conf.DispCommon.prototype.setReset=function(e){return r.Message.setWrapperField(this,8,e)},proto.Conf.DispCommon.prototype.clearReset=function(){return this.setReset(void 0)},proto.Conf.DispCommon.prototype.hasReset=function(){return null!=r.Message.getField(this,8)},proto.Conf.DispCommon.prototype.getReady=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,9)},proto.Conf.DispCommon.prototype.setReady=function(e){return r.Message.setWrapperField(this,9,e)},proto.Conf.DispCommon.prototype.clearReady=function(){return this.setReady(void 0)},proto.Conf.DispCommon.prototype.hasReady=function(){return null!=r.Message.getField(this,9)},proto.Conf.DispCommon.prototype.getOffsets=function(){return r.Message.getWrapperField(this,proto.Conf.DispOffsets,10)},proto.Conf.DispCommon.prototype.setOffsets=function(e){return r.Message.setWrapperField(this,10,e)},proto.Conf.DispCommon.prototype.clearOffsets=function(){return this.setOffsets(void 0)},proto.Conf.DispCommon.prototype.hasOffsets=function(){return null!=r.Message.getField(this,10)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.I2CDisplay.prototype.toObject=function(e){return proto.Conf.I2CDisplay.toObject(e,this)},proto.Conf.I2CDisplay.toObject=function(e,t){var o={address:r.Message.getFieldWithDefault(t,1,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.I2CDisplay.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.I2CDisplay;return proto.Conf.I2CDisplay.deserializeBinaryFromReader(o,t)},proto.Conf.I2CDisplay.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(1===t.getFieldNumber()){var o=t.readInt32();e.setAddress(o)}else t.skipField()}return e},proto.Conf.I2CDisplay.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.I2CDisplay.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.I2CDisplay.serializeBinaryToWriter=function(e,t){var o;0!==(o=e.getAddress())&&t.writeInt32(1,o)},proto.Conf.I2CDisplay.prototype.getAddress=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.I2CDisplay.prototype.setAddress=function(e){return r.Message.setProto3IntField(this,1,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.SPIDisplay.prototype.toObject=function(e){return proto.Conf.SPIDisplay.toObject(e,this)},proto.Conf.SPIDisplay.toObject=function(e,t){var o,n={cs:(o=t.getCs())&&proto.Conf.GPIO.toObject(e,o),speed:r.Message.getFieldWithDefault(t,4,0),rotate:r.Message.getBooleanFieldWithDefault(t,5,!1)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.SPIDisplay.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.SPIDisplay;return proto.Conf.SPIDisplay.deserializeBinaryFromReader(o,t)},proto.Conf.SPIDisplay.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setCs(o);break;case 4:o=t.readInt32();e.setSpeed(o);break;case 5:o=t.readBool();e.setRotate(o);break;default:t.skipField()}}return e},proto.Conf.SPIDisplay.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.SPIDisplay.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.SPIDisplay.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getCs())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getSpeed())&&t.writeInt32(4,o),(o=e.getRotate())&&t.writeBool(5,o)},proto.Conf.SPIDisplay.prototype.getCs=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.SPIDisplay.prototype.setCs=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.SPIDisplay.prototype.clearCs=function(){return this.setCs(void 0)},proto.Conf.SPIDisplay.prototype.hasCs=function(){return null!=r.Message.getField(this,1)},proto.Conf.SPIDisplay.prototype.getSpeed=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.SPIDisplay.prototype.setSpeed=function(e){return r.Message.setProto3IntField(this,4,e)},proto.Conf.SPIDisplay.prototype.getRotate=function(){return r.Message.getBooleanFieldWithDefault(this,5,!1)},proto.Conf.SPIDisplay.prototype.setRotate=function(e){return r.Message.setProto3BooleanField(this,5,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.SPIBus.prototype.toObject=function(e){return proto.Conf.SPIBus.toObject(e,this)},proto.Conf.SPIBus.toObject=function(e,t){var o,n={mosi:(o=t.getMosi())&&proto.Conf.GPIO.toObject(e,o),miso:(o=t.getMiso())&&proto.Conf.GPIO.toObject(e,o),clk:(o=t.getClk())&&proto.Conf.GPIO.toObject(e,o),dc:(o=t.getDc())&&proto.Conf.GPIO.toObject(e,o),host:r.Message.getFieldWithDefault(t,5,0)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.SPIBus.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.SPIBus;return proto.Conf.SPIBus.deserializeBinaryFromReader(o,t)},proto.Conf.SPIBus.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setMosi(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setMiso(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setClk(o);break;case 4:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setDc(o);break;case 5:o=t.readEnum();e.setHost(o);break;default:t.skipField()}}return e},proto.Conf.SPIBus.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.SPIBus.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.SPIBus.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMosi())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getMiso())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getClk())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getDc())&&t.writeMessage(4,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getHost())&&t.writeEnum(5,o)},proto.Conf.SPIBus.prototype.getMosi=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.SPIBus.prototype.setMosi=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.SPIBus.prototype.clearMosi=function(){return this.setMosi(void 0)},proto.Conf.SPIBus.prototype.hasMosi=function(){return null!=r.Message.getField(this,1)},proto.Conf.SPIBus.prototype.getMiso=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.SPIBus.prototype.setMiso=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.SPIBus.prototype.clearMiso=function(){return this.setMiso(void 0)},proto.Conf.SPIBus.prototype.hasMiso=function(){return null!=r.Message.getField(this,2)},proto.Conf.SPIBus.prototype.getClk=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.SPIBus.prototype.setClk=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.SPIBus.prototype.clearClk=function(){return this.setClk(void 0)},proto.Conf.SPIBus.prototype.hasClk=function(){return null!=r.Message.getField(this,3)},proto.Conf.SPIBus.prototype.getDc=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,4)},proto.Conf.SPIBus.prototype.setDc=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.SPIBus.prototype.clearDc=function(){return this.setDc(void 0)},proto.Conf.SPIBus.prototype.hasDc=function(){return null!=r.Message.getField(this,4)},proto.Conf.SPIBus.prototype.getHost=function(){return r.Message.getFieldWithDefault(this,5,0)},proto.Conf.SPIBus.prototype.setHost=function(e){return r.Message.setProto3EnumField(this,5,e)},proto.Conf.DisplayDev.oneofGroups_=[[3,4]],proto.Conf.DisplayDev.DisptypeCase={DISPTYPE_NOT_SET:0,I2C:3,SPI:4},proto.Conf.DisplayDev.prototype.getDisptypeCase=function(){return r.Message.computeOneofCase(this,proto.Conf.DisplayDev.oneofGroups_[0])},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.DisplayDev.prototype.toObject=function(e){return proto.Conf.DisplayDev.toObject(e,this)},proto.Conf.DisplayDev.toObject=function(e,t){var o,n={type:r.Message.getFieldWithDefault(t,1,0),common:(o=t.getCommon())&&proto.Conf.DispCommon.toObject(e,o),i2c:(o=t.getI2c())&&proto.Conf.I2CDisplay.toObject(e,o),spi:(o=t.getSpi())&&proto.Conf.SPIDisplay.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.DisplayDev.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.DisplayDev;return proto.Conf.DisplayDev.deserializeBinaryFromReader(o,t)},proto.Conf.DisplayDev.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new proto.Conf.DispCommon;t.readMessage(o,proto.Conf.DispCommon.deserializeBinaryFromReader),e.setCommon(o);break;case 3:o=new proto.Conf.I2CDisplay;t.readMessage(o,proto.Conf.I2CDisplay.deserializeBinaryFromReader),e.setI2c(o);break;case 4:o=new proto.Conf.SPIDisplay;t.readMessage(o,proto.Conf.SPIDisplay.deserializeBinaryFromReader),e.setSpi(o);break;default:t.skipField()}}return e},proto.Conf.DisplayDev.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.DisplayDev.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.DisplayDev.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),null!=(o=e.getCommon())&&t.writeMessage(2,o,proto.Conf.DispCommon.serializeBinaryToWriter),null!=(o=e.getI2c())&&t.writeMessage(3,o,proto.Conf.I2CDisplay.serializeBinaryToWriter),null!=(o=e.getSpi())&&t.writeMessage(4,o,proto.Conf.SPIDisplay.serializeBinaryToWriter)},proto.Conf.DisplayDev.prototype.getType=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.DisplayDev.prototype.setType=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.DisplayDev.prototype.getCommon=function(){return r.Message.getWrapperField(this,proto.Conf.DispCommon,2)},proto.Conf.DisplayDev.prototype.setCommon=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.DisplayDev.prototype.clearCommon=function(){return this.setCommon(void 0)},proto.Conf.DisplayDev.prototype.hasCommon=function(){return null!=r.Message.getField(this,2)},proto.Conf.DisplayDev.prototype.getI2c=function(){return r.Message.getWrapperField(this,proto.Conf.I2CDisplay,3)},proto.Conf.DisplayDev.prototype.setI2c=function(e){return r.Message.setOneofWrapperField(this,3,proto.Conf.DisplayDev.oneofGroups_[0],e)},proto.Conf.DisplayDev.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.Conf.DisplayDev.prototype.hasI2c=function(){return null!=r.Message.getField(this,3)},proto.Conf.DisplayDev.prototype.getSpi=function(){return r.Message.getWrapperField(this,proto.Conf.SPIDisplay,4)},proto.Conf.DisplayDev.prototype.setSpi=function(e){return r.Message.setOneofWrapperField(this,4,proto.Conf.DisplayDev.oneofGroups_[0],e)},proto.Conf.DisplayDev.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.Conf.DisplayDev.prototype.hasSpi=function(){return null!=r.Message.getField(this,4)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.GPIOExp.prototype.toObject=function(e){return proto.Conf.GPIOExp.toObject(e,this)},proto.Conf.GPIOExp.toObject=function(e,t){var o,n={model:r.Message.getFieldWithDefault(t,1,0),addr:r.Message.getFieldWithDefault(t,2,0),port:r.Message.getFieldWithDefault(t,3,0),base:r.Message.getFieldWithDefault(t,4,0),count:r.Message.getFieldWithDefault(t,5,0),intr:(o=t.getIntr())&&proto.Conf.GPIO.toObject(e,o),cs:(o=t.getCs())&&proto.Conf.GPIO.toObject(e,o),speed:r.Message.getFieldWithDefault(t,8,0)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.GPIOExp.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.GPIOExp;return proto.Conf.GPIOExp.deserializeBinaryFromReader(o,t)},proto.Conf.GPIOExp.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setModel(o);break;case 2:o=t.readInt32();e.setAddr(o);break;case 3:o=t.readEnum();e.setPort(o);break;case 4:o=t.readInt32();e.setBase(o);break;case 5:o=t.readInt32();e.setCount(o);break;case 6:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setIntr(o);break;case 7:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setCs(o);break;case 8:o=t.readInt32();e.setSpeed(o);break;default:t.skipField()}}return e},proto.Conf.GPIOExp.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.GPIOExp.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.GPIOExp.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getModel())&&t.writeEnum(1,o),0!==(o=e.getAddr())&&t.writeInt32(2,o),0!==(o=e.getPort())&&t.writeEnum(3,o),0!==(o=e.getBase())&&t.writeInt32(4,o),0!==(o=e.getCount())&&t.writeInt32(5,o),null!=(o=e.getIntr())&&t.writeMessage(6,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getCs())&&t.writeMessage(7,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getSpeed())&&t.writeInt32(8,o)},proto.Conf.GPIOExp.prototype.getModel=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.GPIOExp.prototype.setModel=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.GPIOExp.prototype.getAddr=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.GPIOExp.prototype.setAddr=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.GPIOExp.prototype.getPort=function(){return r.Message.getFieldWithDefault(this,3,0)},proto.Conf.GPIOExp.prototype.setPort=function(e){return r.Message.setProto3EnumField(this,3,e)},proto.Conf.GPIOExp.prototype.getBase=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.GPIOExp.prototype.setBase=function(e){return r.Message.setProto3IntField(this,4,e)},proto.Conf.GPIOExp.prototype.getCount=function(){return r.Message.getFieldWithDefault(this,5,0)},proto.Conf.GPIOExp.prototype.setCount=function(e){return r.Message.setProto3IntField(this,5,e)},proto.Conf.GPIOExp.prototype.getIntr=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,6)},proto.Conf.GPIOExp.prototype.setIntr=function(e){return r.Message.setWrapperField(this,6,e)},proto.Conf.GPIOExp.prototype.clearIntr=function(){return this.setIntr(void 0)},proto.Conf.GPIOExp.prototype.hasIntr=function(){return null!=r.Message.getField(this,6)},proto.Conf.GPIOExp.prototype.getCs=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,7)},proto.Conf.GPIOExp.prototype.setCs=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.GPIOExp.prototype.clearCs=function(){return this.setCs(void 0)},proto.Conf.GPIOExp.prototype.hasCs=function(){return null!=r.Message.getField(this,7)},proto.Conf.GPIOExp.prototype.getSpeed=function(){return r.Message.getFieldWithDefault(this,8,0)},proto.Conf.GPIOExp.prototype.setSpeed=function(e){return r.Message.setProto3IntField(this,8,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.WS2812.prototype.toObject=function(e){return proto.Conf.WS2812.toObject(e,this)},proto.Conf.WS2812.toObject=function(e,t){var o,n={length:r.Message.getFieldWithDefault(t,1,0),gpio:(o=t.getGpio())&&proto.Conf.GPIO.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.WS2812.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.WS2812;return proto.Conf.WS2812.deserializeBinaryFromReader(o,t)},proto.Conf.WS2812.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setLength(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;default:t.skipField()}}return e},proto.Conf.WS2812.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.WS2812.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.WS2812.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getLength())&&t.writeInt32(1,o),null!=(o=e.getGpio())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.WS2812.prototype.getLength=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.WS2812.prototype.setLength=function(e){return r.Message.setProto3IntField(this,1,e)},proto.Conf.WS2812.prototype.getGpio=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.WS2812.prototype.setGpio=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.WS2812.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.Conf.WS2812.prototype.hasGpio=function(){return null!=r.Message.getField(this,2)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.LEDStrip.prototype.toObject=function(e){return proto.Conf.LEDStrip.toObject(e,this)},proto.Conf.LEDStrip.toObject=function(e,t){var o,r={ws2812:(o=t.getWs2812())&&proto.Conf.WS2812.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.Conf.LEDStrip.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.LEDStrip;return proto.Conf.LEDStrip.deserializeBinaryFromReader(o,t)},proto.Conf.LEDStrip.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){if(1===t.getFieldNumber()){var o=new proto.Conf.WS2812;t.readMessage(o,proto.Conf.WS2812.deserializeBinaryFromReader),e.setWs2812(o)}else t.skipField()}return e},proto.Conf.LEDStrip.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.LEDStrip.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.LEDStrip.serializeBinaryToWriter=function(e,t){var o;null!=(o=e.getWs2812())&&t.writeMessage(1,o,proto.Conf.WS2812.serializeBinaryToWriter)},proto.Conf.LEDStrip.prototype.getWs2812=function(){return r.Message.getWrapperField(this,proto.Conf.WS2812,1)},proto.Conf.LEDStrip.prototype.setWs2812=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.LEDStrip.prototype.clearWs2812=function(){return this.setWs2812(void 0)},proto.Conf.LEDStrip.prototype.hasWs2812=function(){return null!=r.Message.getField(this,1)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Rotary.prototype.toObject=function(e){return proto.Conf.Rotary.toObject(e,this)},proto.Conf.Rotary.toObject=function(e,t){var o,n={a:(o=t.getA())&&proto.Conf.GPIO.toObject(e,o),b:(o=t.getB())&&proto.Conf.GPIO.toObject(e,o),sw:(o=t.getSw())&&proto.Conf.GPIO.toObject(e,o),knobonly:r.Message.getFieldWithDefault(t,4,0),volume:r.Message.getBooleanFieldWithDefault(t,5,!1),longpress:r.Message.getBooleanFieldWithDefault(t,6,!1)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Rotary.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Rotary;return proto.Conf.Rotary.deserializeBinaryFromReader(o,t)},proto.Conf.Rotary.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setA(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setB(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setSw(o);break;case 4:o=t.readInt32();e.setKnobonly(o);break;case 5:o=t.readBool();e.setVolume(o);break;case 6:o=t.readBool();e.setLongpress(o);break;default:t.skipField()}}return e},proto.Conf.Rotary.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Rotary.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Rotary.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getA())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getB())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getSw())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getKnobonly())&&t.writeInt32(4,o),(o=e.getVolume())&&t.writeBool(5,o),(o=e.getLongpress())&&t.writeBool(6,o)},proto.Conf.Rotary.prototype.getA=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.Rotary.prototype.setA=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Rotary.prototype.clearA=function(){return this.setA(void 0)},proto.Conf.Rotary.prototype.hasA=function(){return null!=r.Message.getField(this,1)},proto.Conf.Rotary.prototype.getB=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.Rotary.prototype.setB=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Rotary.prototype.clearB=function(){return this.setB(void 0)},proto.Conf.Rotary.prototype.hasB=function(){return null!=r.Message.getField(this,2)},proto.Conf.Rotary.prototype.getSw=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.Rotary.prototype.setSw=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.Rotary.prototype.clearSw=function(){return this.setSw(void 0)},proto.Conf.Rotary.prototype.hasSw=function(){return null!=r.Message.getField(this,3)},proto.Conf.Rotary.prototype.getKnobonly=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.Rotary.prototype.setKnobonly=function(e){return r.Message.setProto3IntField(this,4,e)},proto.Conf.Rotary.prototype.getVolume=function(){return r.Message.getBooleanFieldWithDefault(this,5,!1)},proto.Conf.Rotary.prototype.setVolume=function(e){return r.Message.setProto3BooleanField(this,5,e)},proto.Conf.Rotary.prototype.getLongpress=function(){return r.Message.getBooleanFieldWithDefault(this,6,!1)},proto.Conf.Rotary.prototype.setLongpress=function(e){return r.Message.setProto3BooleanField(this,6,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.ButtonActions.prototype.toObject=function(e){return proto.Conf.ButtonActions.toObject(e,this)},proto.Conf.ButtonActions.toObject=function(e,t){var o={pressed:r.Message.getFieldWithDefault(t,1,0),released:r.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.ButtonActions.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.ButtonActions;return proto.Conf.ButtonActions.deserializeBinaryFromReader(o,t)},proto.Conf.ButtonActions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setPressed(o);break;case 2:o=t.readEnum();e.setReleased(o);break;default:t.skipField()}}return e},proto.Conf.ButtonActions.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.ButtonActions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.ButtonActions.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getPressed())&&t.writeEnum(1,o),0!==(o=e.getReleased())&&t.writeEnum(2,o)},proto.Conf.ButtonActions.prototype.getPressed=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.ButtonActions.prototype.setPressed=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.ButtonActions.prototype.getReleased=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.ButtonActions.prototype.setReleased=function(e){return r.Message.setProto3EnumField(this,2,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Button.prototype.toObject=function(e){return proto.Conf.Button.toObject(e,this)},proto.Conf.Button.toObject=function(e,t){var o,n={gpio:(o=t.getGpio())&&proto.Conf.GPIO.toObject(e,o),pull:r.Message.getBooleanFieldWithDefault(t,2,!1),debounce:r.Message.getFieldWithDefault(t,3,0),shifter:(o=t.getShifter())&&proto.Conf.GPIO.toObject(e,o),longduration:r.Message.getFieldWithDefault(t,5,0),normal:(o=t.getNormal())&&proto.Conf.ButtonActions.toObject(e,o),longpress:(o=t.getLongpress())&&proto.Conf.ButtonActions.toObject(e,o),shifted:(o=t.getShifted())&&proto.Conf.ButtonActions.toObject(e,o),longshifted:(o=t.getLongshifted())&&proto.Conf.ButtonActions.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Button.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Button;return proto.Conf.Button.deserializeBinaryFromReader(o,t)},proto.Conf.Button.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setGpio(o);break;case 2:o=t.readBool();e.setPull(o);break;case 3:o=t.readInt32();e.setDebounce(o);break;case 4:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setShifter(o);break;case 5:o=t.readInt32();e.setLongduration(o);break;case 6:o=new proto.Conf.ButtonActions;t.readMessage(o,proto.Conf.ButtonActions.deserializeBinaryFromReader),e.setNormal(o);break;case 7:o=new proto.Conf.ButtonActions;t.readMessage(o,proto.Conf.ButtonActions.deserializeBinaryFromReader),e.setLongpress(o);break;case 8:o=new proto.Conf.ButtonActions;t.readMessage(o,proto.Conf.ButtonActions.deserializeBinaryFromReader),e.setShifted(o);break;case 9:o=new proto.Conf.ButtonActions;t.readMessage(o,proto.Conf.ButtonActions.deserializeBinaryFromReader),e.setLongshifted(o);break;default:t.skipField()}}return e},proto.Conf.Button.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Button.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Button.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpio())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),(o=e.getPull())&&t.writeBool(2,o),0!==(o=e.getDebounce())&&t.writeInt32(3,o),null!=(o=e.getShifter())&&t.writeMessage(4,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getLongduration())&&t.writeInt32(5,o),null!=(o=e.getNormal())&&t.writeMessage(6,o,proto.Conf.ButtonActions.serializeBinaryToWriter),null!=(o=e.getLongpress())&&t.writeMessage(7,o,proto.Conf.ButtonActions.serializeBinaryToWriter),null!=(o=e.getShifted())&&t.writeMessage(8,o,proto.Conf.ButtonActions.serializeBinaryToWriter),null!=(o=e.getLongshifted())&&t.writeMessage(9,o,proto.Conf.ButtonActions.serializeBinaryToWriter)},proto.Conf.Button.prototype.getGpio=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.Button.prototype.setGpio=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Button.prototype.clearGpio=function(){return this.setGpio(void 0)},proto.Conf.Button.prototype.hasGpio=function(){return null!=r.Message.getField(this,1)},proto.Conf.Button.prototype.getPull=function(){return r.Message.getBooleanFieldWithDefault(this,2,!1)},proto.Conf.Button.prototype.setPull=function(e){return r.Message.setProto3BooleanField(this,2,e)},proto.Conf.Button.prototype.getDebounce=function(){return r.Message.getFieldWithDefault(this,3,0)},proto.Conf.Button.prototype.setDebounce=function(e){return r.Message.setProto3IntField(this,3,e)},proto.Conf.Button.prototype.getShifter=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,4)},proto.Conf.Button.prototype.setShifter=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.Button.prototype.clearShifter=function(){return this.setShifter(void 0)},proto.Conf.Button.prototype.hasShifter=function(){return null!=r.Message.getField(this,4)},proto.Conf.Button.prototype.getLongduration=function(){return r.Message.getFieldWithDefault(this,5,0)},proto.Conf.Button.prototype.setLongduration=function(e){return r.Message.setProto3IntField(this,5,e)},proto.Conf.Button.prototype.getNormal=function(){return r.Message.getWrapperField(this,proto.Conf.ButtonActions,6)},proto.Conf.Button.prototype.setNormal=function(e){return r.Message.setWrapperField(this,6,e)},proto.Conf.Button.prototype.clearNormal=function(){return this.setNormal(void 0)},proto.Conf.Button.prototype.hasNormal=function(){return null!=r.Message.getField(this,6)},proto.Conf.Button.prototype.getLongpress=function(){return r.Message.getWrapperField(this,proto.Conf.ButtonActions,7)},proto.Conf.Button.prototype.setLongpress=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.Button.prototype.clearLongpress=function(){return this.setLongpress(void 0)},proto.Conf.Button.prototype.hasLongpress=function(){return null!=r.Message.getField(this,7)},proto.Conf.Button.prototype.getShifted=function(){return r.Message.getWrapperField(this,proto.Conf.ButtonActions,8)},proto.Conf.Button.prototype.setShifted=function(e){return r.Message.setWrapperField(this,8,e)},proto.Conf.Button.prototype.clearShifted=function(){return this.setShifted(void 0)},proto.Conf.Button.prototype.hasShifted=function(){return null!=r.Message.getField(this,8)},proto.Conf.Button.prototype.getLongshifted=function(){return r.Message.getWrapperField(this,proto.Conf.ButtonActions,9)},proto.Conf.Button.prototype.setLongshifted=function(e){return r.Message.setWrapperField(this,9,e)},proto.Conf.Button.prototype.clearLongshifted=function(){return this.setLongshifted(void 0)},proto.Conf.Button.prototype.hasLongshifted=function(){return null!=r.Message.getField(this,9)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.EthCommon.prototype.toObject=function(e){return proto.Conf.EthCommon.toObject(e,this)},proto.Conf.EthCommon.toObject=function(e,t){var o,n={model:r.Message.getFieldWithDefault(t,1,0),rst:(o=t.getRst())&&proto.Conf.GPIO.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.EthCommon.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.EthCommon;return proto.Conf.EthCommon.deserializeBinaryFromReader(o,t)},proto.Conf.EthCommon.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setModel(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setRst(o);break;default:t.skipField()}}return e},proto.Conf.EthCommon.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.EthCommon.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.EthCommon.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getModel())&&t.writeEnum(1,o),null!=(o=e.getRst())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.EthCommon.prototype.getModel=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.EthCommon.prototype.setModel=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.EthCommon.prototype.getRst=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.EthCommon.prototype.setRst=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.EthCommon.prototype.clearRst=function(){return this.setRst(void 0)},proto.Conf.EthCommon.prototype.hasRst=function(){return null!=r.Message.getField(this,2)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.EthSPI.prototype.toObject=function(e){return proto.Conf.EthSPI.toObject(e,this)},proto.Conf.EthSPI.toObject=function(e,t){var o,n={cs:(o=t.getCs())&&proto.Conf.GPIO.toObject(e,o),speed:r.Message.getFieldWithDefault(t,2,0),intr:(o=t.getIntr())&&proto.Conf.GPIO.toObject(e,o),host:r.Message.getFieldWithDefault(t,4,0)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.EthSPI.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.EthSPI;return proto.Conf.EthSPI.deserializeBinaryFromReader(o,t)},proto.Conf.EthSPI.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setCs(o);break;case 2:o=t.readInt32();e.setSpeed(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setIntr(o);break;case 4:o=t.readInt32();e.setHost(o);break;default:t.skipField()}}return e},proto.Conf.EthSPI.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.EthSPI.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.EthSPI.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getCs())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getSpeed())&&t.writeInt32(2,o),null!=(o=e.getIntr())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getHost())&&t.writeInt32(4,o)},proto.Conf.EthSPI.prototype.getCs=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.EthSPI.prototype.setCs=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.EthSPI.prototype.clearCs=function(){return this.setCs(void 0)},proto.Conf.EthSPI.prototype.hasCs=function(){return null!=r.Message.getField(this,1)},proto.Conf.EthSPI.prototype.getSpeed=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.EthSPI.prototype.setSpeed=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.EthSPI.prototype.getIntr=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.EthSPI.prototype.setIntr=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.EthSPI.prototype.clearIntr=function(){return this.setIntr(void 0)},proto.Conf.EthSPI.prototype.hasIntr=function(){return null!=r.Message.getField(this,3)},proto.Conf.EthSPI.prototype.getHost=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.EthSPI.prototype.setHost=function(e){return r.Message.setProto3IntField(this,4,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.EthRMII.prototype.toObject=function(e){return proto.Conf.EthRMII.toObject(e,this)},proto.Conf.EthRMII.toObject=function(e,t){var o,r={mdc:(o=t.getMdc())&&proto.Conf.GPIO.toObject(e,o),mdio:(o=t.getMdio())&&proto.Conf.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.Conf.EthRMII.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.EthRMII;return proto.Conf.EthRMII.deserializeBinaryFromReader(o,t)},proto.Conf.EthRMII.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setMdc(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setMdio(o);break;default:t.skipField()}}return e},proto.Conf.EthRMII.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.EthRMII.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.EthRMII.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMdc())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getMdio())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.EthRMII.prototype.getMdc=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.EthRMII.prototype.setMdc=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.EthRMII.prototype.clearMdc=function(){return this.setMdc(void 0)},proto.Conf.EthRMII.prototype.hasMdc=function(){return null!=r.Message.getField(this,1)},proto.Conf.EthRMII.prototype.getMdio=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.EthRMII.prototype.setMdio=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.EthRMII.prototype.clearMdio=function(){return this.setMdio(void 0)},proto.Conf.EthRMII.prototype.hasMdio=function(){return null!=r.Message.getField(this,2)},proto.Conf.Eth.oneofGroups_=[[3,4]],proto.Conf.Eth.EthtypeCase={ETHTYPE_NOT_SET:0,SPI:3,RMII:4},proto.Conf.Eth.prototype.getEthtypeCase=function(){return r.Message.computeOneofCase(this,proto.Conf.Eth.oneofGroups_[0])},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Eth.prototype.toObject=function(e){return proto.Conf.Eth.toObject(e,this)},proto.Conf.Eth.toObject=function(e,t){var o,n={type:r.Message.getFieldWithDefault(t,1,0),common:(o=t.getCommon())&&proto.Conf.EthCommon.toObject(e,o),spi:(o=t.getSpi())&&proto.Conf.EthSPI.toObject(e,o),rmii:(o=t.getRmii())&&proto.Conf.EthRMII.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Eth.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Eth;return proto.Conf.Eth.deserializeBinaryFromReader(o,t)},proto.Conf.Eth.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setType(o);break;case 2:o=new proto.Conf.EthCommon;t.readMessage(o,proto.Conf.EthCommon.deserializeBinaryFromReader),e.setCommon(o);break;case 3:o=new proto.Conf.EthSPI;t.readMessage(o,proto.Conf.EthSPI.deserializeBinaryFromReader),e.setSpi(o);break;case 4:o=new proto.Conf.EthRMII;t.readMessage(o,proto.Conf.EthRMII.deserializeBinaryFromReader),e.setRmii(o);break;default:t.skipField()}}return e},proto.Conf.Eth.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Eth.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Eth.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getType())&&t.writeEnum(1,o),null!=(o=e.getCommon())&&t.writeMessage(2,o,proto.Conf.EthCommon.serializeBinaryToWriter),null!=(o=e.getSpi())&&t.writeMessage(3,o,proto.Conf.EthSPI.serializeBinaryToWriter),null!=(o=e.getRmii())&&t.writeMessage(4,o,proto.Conf.EthRMII.serializeBinaryToWriter)},proto.Conf.Eth.prototype.getType=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.Eth.prototype.setType=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.Eth.prototype.getCommon=function(){return r.Message.getWrapperField(this,proto.Conf.EthCommon,2)},proto.Conf.Eth.prototype.setCommon=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Eth.prototype.clearCommon=function(){return this.setCommon(void 0)},proto.Conf.Eth.prototype.hasCommon=function(){return null!=r.Message.getField(this,2)},proto.Conf.Eth.prototype.getSpi=function(){return r.Message.getWrapperField(this,proto.Conf.EthSPI,3)},proto.Conf.Eth.prototype.setSpi=function(e){return r.Message.setOneofWrapperField(this,3,proto.Conf.Eth.oneofGroups_[0],e)},proto.Conf.Eth.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.Conf.Eth.prototype.hasSpi=function(){return null!=r.Message.getField(this,3)},proto.Conf.Eth.prototype.getRmii=function(){return r.Message.getWrapperField(this,proto.Conf.EthRMII,4)},proto.Conf.Eth.prototype.setRmii=function(e){return r.Message.setOneofWrapperField(this,4,proto.Conf.Eth.oneofGroups_[0],e)},proto.Conf.Eth.prototype.clearRmii=function(){return this.setRmii(void 0)},proto.Conf.Eth.prototype.hasRmii=function(){return null!=r.Message.getField(this,4)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Battery.prototype.toObject=function(e){return proto.Conf.Battery.toObject(e,this)},proto.Conf.Battery.toObject=function(e,t){var o={channel:r.Message.getFieldWithDefault(t,1,0),scale:r.Message.getFloatingPointFieldWithDefault(t,2,0),cells:r.Message.getFieldWithDefault(t,3,0),atten:r.Message.getFieldWithDefault(t,4,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.Battery.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Battery;return proto.Conf.Battery.deserializeBinaryFromReader(o,t)},proto.Conf.Battery.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readEnum();e.setChannel(o);break;case 2:o=t.readFloat();e.setScale(o);break;case 3:o=t.readInt32();e.setCells(o);break;case 4:o=t.readEnum();e.setAtten(o);break;default:t.skipField()}}return e},proto.Conf.Battery.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Battery.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Battery.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getChannel())&&t.writeEnum(1,o),0!==(o=e.getScale())&&t.writeFloat(2,o),0!==(o=e.getCells())&&t.writeInt32(3,o),0!==(o=e.getAtten())&&t.writeEnum(4,o)},proto.Conf.Battery.prototype.getChannel=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.Battery.prototype.setChannel=function(e){return r.Message.setProto3EnumField(this,1,e)},proto.Conf.Battery.prototype.getScale=function(){return r.Message.getFloatingPointFieldWithDefault(this,2,0)},proto.Conf.Battery.prototype.setScale=function(e){return r.Message.setProto3FloatField(this,2,e)},proto.Conf.Battery.prototype.getCells=function(){return r.Message.getFieldWithDefault(this,3,0)},proto.Conf.Battery.prototype.setCells=function(e){return r.Message.setProto3IntField(this,3,e)},proto.Conf.Battery.prototype.getAtten=function(){return r.Message.getFieldWithDefault(this,4,0)},proto.Conf.Battery.prototype.setAtten=function(e){return r.Message.setProto3EnumField(this,4,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Gpios.prototype.toObject=function(e){return proto.Conf.Gpios.toObject(e,this)},proto.Conf.Gpios.toObject=function(e,t){var o,r={greenled:(o=t.getGreenled())&&proto.Conf.GPIO.toObject(e,o),redled:(o=t.getRedled())&&proto.Conf.GPIO.toObject(e,o),audiojack:(o=t.getAudiojack())&&proto.Conf.GPIO.toObject(e,o),amp:(o=t.getAmp())&&proto.Conf.GPIO.toObject(e,o),power:(o=t.getPower())&&proto.Conf.GPIO.toObject(e,o),ir:(o=t.getIr())&&proto.Conf.GPIO.toObject(e,o),jack:(o=t.getJack())&&proto.Conf.GPIO.toObject(e,o),spkfault:(o=t.getSpkfault())&&proto.Conf.GPIO.toObject(e,o),vcc:(o=t.getVcc())&&proto.Conf.GPIO.toObject(e,o),gnd:(o=t.getGnd())&&proto.Conf.GPIO.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.Conf.Gpios.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Gpios;return proto.Conf.Gpios.deserializeBinaryFromReader(o,t)},proto.Conf.Gpios.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setGreenled(o);break;case 2:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setRedled(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setAudiojack(o);break;case 4:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setAmp(o);break;case 5:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setPower(o);break;case 6:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setIr(o);break;case 7:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setJack(o);break;case 8:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setSpkfault(o);break;case 9:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setVcc(o);break;case 10:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setGnd(o);break;default:t.skipField()}}return e},proto.Conf.Gpios.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Gpios.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Gpios.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGreenled())&&t.writeMessage(1,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getRedled())&&t.writeMessage(2,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getAudiojack())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getAmp())&&t.writeMessage(4,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getPower())&&t.writeMessage(5,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getIr())&&t.writeMessage(6,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getJack())&&t.writeMessage(7,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getSpkfault())&&t.writeMessage(8,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getVcc())&&t.writeMessage(9,o,proto.Conf.GPIO.serializeBinaryToWriter),null!=(o=e.getGnd())&&t.writeMessage(10,o,proto.Conf.GPIO.serializeBinaryToWriter)},proto.Conf.Gpios.prototype.getGreenled=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,1)},proto.Conf.Gpios.prototype.setGreenled=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Gpios.prototype.clearGreenled=function(){return this.setGreenled(void 0)},proto.Conf.Gpios.prototype.hasGreenled=function(){return null!=r.Message.getField(this,1)},proto.Conf.Gpios.prototype.getRedled=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,2)},proto.Conf.Gpios.prototype.setRedled=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Gpios.prototype.clearRedled=function(){return this.setRedled(void 0)},proto.Conf.Gpios.prototype.hasRedled=function(){return null!=r.Message.getField(this,2)},proto.Conf.Gpios.prototype.getAudiojack=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.Gpios.prototype.setAudiojack=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.Gpios.prototype.clearAudiojack=function(){return this.setAudiojack(void 0)},proto.Conf.Gpios.prototype.hasAudiojack=function(){return null!=r.Message.getField(this,3)},proto.Conf.Gpios.prototype.getAmp=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,4)},proto.Conf.Gpios.prototype.setAmp=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.Gpios.prototype.clearAmp=function(){return this.setAmp(void 0)},proto.Conf.Gpios.prototype.hasAmp=function(){return null!=r.Message.getField(this,4)},proto.Conf.Gpios.prototype.getPower=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,5)},proto.Conf.Gpios.prototype.setPower=function(e){return r.Message.setWrapperField(this,5,e)},proto.Conf.Gpios.prototype.clearPower=function(){return this.setPower(void 0)},proto.Conf.Gpios.prototype.hasPower=function(){return null!=r.Message.getField(this,5)},proto.Conf.Gpios.prototype.getIr=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,6)},proto.Conf.Gpios.prototype.setIr=function(e){return r.Message.setWrapperField(this,6,e)},proto.Conf.Gpios.prototype.clearIr=function(){return this.setIr(void 0)},proto.Conf.Gpios.prototype.hasIr=function(){return null!=r.Message.getField(this,6)},proto.Conf.Gpios.prototype.getJack=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,7)},proto.Conf.Gpios.prototype.setJack=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.Gpios.prototype.clearJack=function(){return this.setJack(void 0)},proto.Conf.Gpios.prototype.hasJack=function(){return null!=r.Message.getField(this,7)},proto.Conf.Gpios.prototype.getSpkfault=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,8)},proto.Conf.Gpios.prototype.setSpkfault=function(e){return r.Message.setWrapperField(this,8,e)},proto.Conf.Gpios.prototype.clearSpkfault=function(){return this.setSpkfault(void 0)},proto.Conf.Gpios.prototype.hasSpkfault=function(){return null!=r.Message.getField(this,8)},proto.Conf.Gpios.prototype.getVcc=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,9)},proto.Conf.Gpios.prototype.setVcc=function(e){return r.Message.setWrapperField(this,9,e)},proto.Conf.Gpios.prototype.clearVcc=function(){return this.setVcc(void 0)},proto.Conf.Gpios.prototype.hasVcc=function(){return null!=r.Message.getField(this,9)},proto.Conf.Gpios.prototype.getGnd=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,10)},proto.Conf.Gpios.prototype.setGnd=function(e){return r.Message.setWrapperField(this,10,e)},proto.Conf.Gpios.prototype.clearGnd=function(){return this.setGnd(void 0)},proto.Conf.Gpios.prototype.hasGnd=function(){return null!=r.Message.getField(this,10)},proto.Conf.Dev.repeatedFields_=[9],r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Dev.prototype.toObject=function(e){return proto.Conf.Dev.toObject(e,this)},proto.Conf.Dev.toObject=function(e,t){var o,n={spi:(o=t.getSpi())&&proto.Conf.SPIBus.toObject(e,o),i2c:(o=t.getI2c())&&proto.Conf.I2CBus.toObject(e,o),dac:(o=t.getDac())&&proto.Conf.DACDev.toObject(e,o),spdif:(o=t.getSpdif())&&proto.Conf.SPDIFDev.toObject(e,o),display:(o=t.getDisplay())&&proto.Conf.DisplayDev.toObject(e,o),gpioExp:(o=t.getGpioExp())&&proto.Conf.GPIOExp.toObject(e,o),ledStrip:(o=t.getLedStrip())&&proto.Conf.LEDStrip.toObject(e,o),rotary:(o=t.getRotary())&&proto.Conf.Rotary.toObject(e,o),buttonsList:r.Message.toObjectList(t.getButtonsList(),proto.Conf.Button.toObject,e),eth:(o=t.getEth())&&proto.Conf.Eth.toObject(e,o),battery:(o=t.getBattery())&&proto.Conf.Battery.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Dev.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Dev;return proto.Conf.Dev.deserializeBinaryFromReader(o,t)},proto.Conf.Dev.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.SPIBus;t.readMessage(o,proto.Conf.SPIBus.deserializeBinaryFromReader),e.setSpi(o);break;case 2:o=new proto.Conf.I2CBus;t.readMessage(o,proto.Conf.I2CBus.deserializeBinaryFromReader),e.setI2c(o);break;case 3:o=new proto.Conf.DACDev;t.readMessage(o,proto.Conf.DACDev.deserializeBinaryFromReader),e.setDac(o);break;case 4:o=new proto.Conf.SPDIFDev;t.readMessage(o,proto.Conf.SPDIFDev.deserializeBinaryFromReader),e.setSpdif(o);break;case 5:o=new proto.Conf.DisplayDev;t.readMessage(o,proto.Conf.DisplayDev.deserializeBinaryFromReader),e.setDisplay(o);break;case 6:o=new proto.Conf.GPIOExp;t.readMessage(o,proto.Conf.GPIOExp.deserializeBinaryFromReader),e.setGpioExp(o);break;case 7:o=new proto.Conf.LEDStrip;t.readMessage(o,proto.Conf.LEDStrip.deserializeBinaryFromReader),e.setLedStrip(o);break;case 8:o=new proto.Conf.Rotary;t.readMessage(o,proto.Conf.Rotary.deserializeBinaryFromReader),e.setRotary(o);break;case 9:o=new proto.Conf.Button;t.readMessage(o,proto.Conf.Button.deserializeBinaryFromReader),e.addButtons(o);break;case 10:o=new proto.Conf.Eth;t.readMessage(o,proto.Conf.Eth.deserializeBinaryFromReader),e.setEth(o);break;case 11:o=new proto.Conf.Battery;t.readMessage(o,proto.Conf.Battery.deserializeBinaryFromReader),e.setBattery(o);break;default:t.skipField()}}return e},proto.Conf.Dev.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Dev.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Dev.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getSpi())&&t.writeMessage(1,o,proto.Conf.SPIBus.serializeBinaryToWriter),null!=(o=e.getI2c())&&t.writeMessage(2,o,proto.Conf.I2CBus.serializeBinaryToWriter),null!=(o=e.getDac())&&t.writeMessage(3,o,proto.Conf.DACDev.serializeBinaryToWriter),null!=(o=e.getSpdif())&&t.writeMessage(4,o,proto.Conf.SPDIFDev.serializeBinaryToWriter),null!=(o=e.getDisplay())&&t.writeMessage(5,o,proto.Conf.DisplayDev.serializeBinaryToWriter),null!=(o=e.getGpioExp())&&t.writeMessage(6,o,proto.Conf.GPIOExp.serializeBinaryToWriter),null!=(o=e.getLedStrip())&&t.writeMessage(7,o,proto.Conf.LEDStrip.serializeBinaryToWriter),null!=(o=e.getRotary())&&t.writeMessage(8,o,proto.Conf.Rotary.serializeBinaryToWriter),(o=e.getButtonsList()).length>0&&t.writeRepeatedMessage(9,o,proto.Conf.Button.serializeBinaryToWriter),null!=(o=e.getEth())&&t.writeMessage(10,o,proto.Conf.Eth.serializeBinaryToWriter),null!=(o=e.getBattery())&&t.writeMessage(11,o,proto.Conf.Battery.serializeBinaryToWriter)},proto.Conf.Dev.prototype.getSpi=function(){return r.Message.getWrapperField(this,proto.Conf.SPIBus,1)},proto.Conf.Dev.prototype.setSpi=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Dev.prototype.clearSpi=function(){return this.setSpi(void 0)},proto.Conf.Dev.prototype.hasSpi=function(){return null!=r.Message.getField(this,1)},proto.Conf.Dev.prototype.getI2c=function(){return r.Message.getWrapperField(this,proto.Conf.I2CBus,2)},proto.Conf.Dev.prototype.setI2c=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Dev.prototype.clearI2c=function(){return this.setI2c(void 0)},proto.Conf.Dev.prototype.hasI2c=function(){return null!=r.Message.getField(this,2)},proto.Conf.Dev.prototype.getDac=function(){return r.Message.getWrapperField(this,proto.Conf.DACDev,3)},proto.Conf.Dev.prototype.setDac=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.Dev.prototype.clearDac=function(){return this.setDac(void 0)},proto.Conf.Dev.prototype.hasDac=function(){return null!=r.Message.getField(this,3)},proto.Conf.Dev.prototype.getSpdif=function(){return r.Message.getWrapperField(this,proto.Conf.SPDIFDev,4)},proto.Conf.Dev.prototype.setSpdif=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.Dev.prototype.clearSpdif=function(){return this.setSpdif(void 0)},proto.Conf.Dev.prototype.hasSpdif=function(){return null!=r.Message.getField(this,4)},proto.Conf.Dev.prototype.getDisplay=function(){return r.Message.getWrapperField(this,proto.Conf.DisplayDev,5)},proto.Conf.Dev.prototype.setDisplay=function(e){return r.Message.setWrapperField(this,5,e)},proto.Conf.Dev.prototype.clearDisplay=function(){return this.setDisplay(void 0)},proto.Conf.Dev.prototype.hasDisplay=function(){return null!=r.Message.getField(this,5)},proto.Conf.Dev.prototype.getGpioExp=function(){return r.Message.getWrapperField(this,proto.Conf.GPIOExp,6)},proto.Conf.Dev.prototype.setGpioExp=function(e){return r.Message.setWrapperField(this,6,e)},proto.Conf.Dev.prototype.clearGpioExp=function(){return this.setGpioExp(void 0)},proto.Conf.Dev.prototype.hasGpioExp=function(){return null!=r.Message.getField(this,6)},proto.Conf.Dev.prototype.getLedStrip=function(){return r.Message.getWrapperField(this,proto.Conf.LEDStrip,7)},proto.Conf.Dev.prototype.setLedStrip=function(e){return r.Message.setWrapperField(this,7,e)},proto.Conf.Dev.prototype.clearLedStrip=function(){return this.setLedStrip(void 0)},proto.Conf.Dev.prototype.hasLedStrip=function(){return null!=r.Message.getField(this,7)},proto.Conf.Dev.prototype.getRotary=function(){return r.Message.getWrapperField(this,proto.Conf.Rotary,8)},proto.Conf.Dev.prototype.setRotary=function(e){return r.Message.setWrapperField(this,8,e)},proto.Conf.Dev.prototype.clearRotary=function(){return this.setRotary(void 0)},proto.Conf.Dev.prototype.hasRotary=function(){return null!=r.Message.getField(this,8)},proto.Conf.Dev.prototype.getButtonsList=function(){return r.Message.getRepeatedWrapperField(this,proto.Conf.Button,9)},proto.Conf.Dev.prototype.setButtonsList=function(e){return r.Message.setRepeatedWrapperField(this,9,e)},proto.Conf.Dev.prototype.addButtons=function(e,t){return r.Message.addToRepeatedWrapperField(this,9,e,proto.Conf.Button,t)},proto.Conf.Dev.prototype.clearButtonsList=function(){return this.setButtonsList([])},proto.Conf.Dev.prototype.getEth=function(){return r.Message.getWrapperField(this,proto.Conf.Eth,10)},proto.Conf.Dev.prototype.setEth=function(e){return r.Message.setWrapperField(this,10,e)},proto.Conf.Dev.prototype.clearEth=function(){return this.setEth(void 0)},proto.Conf.Dev.prototype.hasEth=function(){return null!=r.Message.getField(this,10)},proto.Conf.Dev.prototype.getBattery=function(){return r.Message.getWrapperField(this,proto.Conf.Battery,11)},proto.Conf.Dev.prototype.setBattery=function(e){return r.Message.setWrapperField(this,11,e)},proto.Conf.Dev.prototype.clearBattery=function(){return this.setBattery(void 0)},proto.Conf.Dev.prototype.hasBattery=function(){return null!=r.Message.getField(this,11)},proto.Conf.SleepService.repeatedFields_=[4,5],r.Message.GENERATE_TO_OBJECT&&(proto.Conf.SleepService.prototype.toObject=function(e){return proto.Conf.SleepService.toObject(e,this)},proto.Conf.SleepService.toObject=function(e,t){var o,n={delay:r.Message.getFieldWithDefault(t,1,0),spurious:r.Message.getFieldWithDefault(t,2,0),sleep:(o=t.getSleep())&&proto.Conf.GPIO.toObject(e,o),wakeList:r.Message.toObjectList(t.getWakeList(),proto.Conf.GPIO.toObject,e),rtcList:r.Message.toObjectList(t.getRtcList(),proto.Conf.GPIO.toObject,e),batt:r.Message.getFloatingPointFieldWithDefault(t,6,0)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.SleepService.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.SleepService;return proto.Conf.SleepService.deserializeBinaryFromReader(o,t)},proto.Conf.SleepService.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readUint32();e.setDelay(o);break;case 2:o=t.readInt32();e.setSpurious(o);break;case 3:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.setSleep(o);break;case 4:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.addWake(o);break;case 5:o=new proto.Conf.GPIO;t.readMessage(o,proto.Conf.GPIO.deserializeBinaryFromReader),e.addRtc(o);break;case 6:o=t.readFloat();e.setBatt(o);break;default:t.skipField()}}return e},proto.Conf.SleepService.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.SleepService.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.SleepService.serializeBinaryToWriter=function(e,t){var o=void 0;0!==(o=e.getDelay())&&t.writeUint32(1,o),0!==(o=e.getSpurious())&&t.writeInt32(2,o),null!=(o=e.getSleep())&&t.writeMessage(3,o,proto.Conf.GPIO.serializeBinaryToWriter),(o=e.getWakeList()).length>0&&t.writeRepeatedMessage(4,o,proto.Conf.GPIO.serializeBinaryToWriter),(o=e.getRtcList()).length>0&&t.writeRepeatedMessage(5,o,proto.Conf.GPIO.serializeBinaryToWriter),0!==(o=e.getBatt())&&t.writeFloat(6,o)},proto.Conf.SleepService.prototype.getDelay=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.Conf.SleepService.prototype.setDelay=function(e){return r.Message.setProto3IntField(this,1,e)},proto.Conf.SleepService.prototype.getSpurious=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.SleepService.prototype.setSpurious=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.SleepService.prototype.getSleep=function(){return r.Message.getWrapperField(this,proto.Conf.GPIO,3)},proto.Conf.SleepService.prototype.setSleep=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.SleepService.prototype.clearSleep=function(){return this.setSleep(void 0)},proto.Conf.SleepService.prototype.hasSleep=function(){return null!=r.Message.getField(this,3)},proto.Conf.SleepService.prototype.getWakeList=function(){return r.Message.getRepeatedWrapperField(this,proto.Conf.GPIO,4)},proto.Conf.SleepService.prototype.setWakeList=function(e){return r.Message.setRepeatedWrapperField(this,4,e)},proto.Conf.SleepService.prototype.addWake=function(e,t){return r.Message.addToRepeatedWrapperField(this,4,e,proto.Conf.GPIO,t)},proto.Conf.SleepService.prototype.clearWakeList=function(){return this.setWakeList([])},proto.Conf.SleepService.prototype.getRtcList=function(){return r.Message.getRepeatedWrapperField(this,proto.Conf.GPIO,5)},proto.Conf.SleepService.prototype.setRtcList=function(e){return r.Message.setRepeatedWrapperField(this,5,e)},proto.Conf.SleepService.prototype.addRtc=function(e,t){return r.Message.addToRepeatedWrapperField(this,5,e,proto.Conf.GPIO,t)},proto.Conf.SleepService.prototype.clearRtcList=function(){return this.setRtcList([])},proto.Conf.SleepService.prototype.getBatt=function(){return r.Message.getFloatingPointFieldWithDefault(this,6,0)},proto.Conf.SleepService.prototype.setBatt=function(e){return r.Message.setProto3FloatField(this,6,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Artwork.prototype.toObject=function(e){return proto.Conf.Artwork.toObject(e,this)},proto.Conf.Artwork.toObject=function(e,t){var o={enabled:r.Message.getBooleanFieldWithDefault(t,1,!1),resize:r.Message.getFieldWithDefault(t,2,0)};return e&&(o.$jspbMessageInstance=t),o}),proto.Conf.Artwork.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Artwork;return proto.Conf.Artwork.deserializeBinaryFromReader(o,t)},proto.Conf.Artwork.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readBool();e.setEnabled(o);break;case 2:o=t.readUint32();e.setResize(o);break;default:t.skipField()}}return e},proto.Conf.Artwork.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Artwork.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Artwork.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getEnabled())&&t.writeBool(1,o),0!==(o=e.getResize())&&t.writeUint32(2,o)},proto.Conf.Artwork.prototype.getEnabled=function(){return r.Message.getBooleanFieldWithDefault(this,1,!1)},proto.Conf.Artwork.prototype.setEnabled=function(e){return r.Message.setProto3BooleanField(this,1,e)},proto.Conf.Artwork.prototype.getResize=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.Artwork.prototype.setResize=function(e){return r.Message.setProto3IntField(this,2,e)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Metadata.prototype.toObject=function(e){return proto.Conf.Metadata.toObject(e,this)},proto.Conf.Metadata.toObject=function(e,t){var o,n={format:r.Message.getFieldWithDefault(t,1,""),speed:r.Message.getFieldWithDefault(t,2,0),pause:r.Message.getFieldWithDefault(t,3,0),artwork:(o=t.getArtwork())&&proto.Conf.Artwork.toObject(e,o)};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Metadata.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Metadata;return proto.Conf.Metadata.deserializeBinaryFromReader(o,t)},proto.Conf.Metadata.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readString();e.setFormat(o);break;case 2:o=t.readUint32();e.setSpeed(o);break;case 3:o=t.readUint32();e.setPause(o);break;case 4:o=new proto.Conf.Artwork;t.readMessage(o,proto.Conf.Artwork.deserializeBinaryFromReader),e.setArtwork(o);break;default:t.skipField()}}return e},proto.Conf.Metadata.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Metadata.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Metadata.serializeBinaryToWriter=function(e,t){var o=void 0;(o=e.getFormat()).length>0&&t.writeString(1,o),0!==(o=e.getSpeed())&&t.writeUint32(2,o),0!==(o=e.getPause())&&t.writeUint32(3,o),null!=(o=e.getArtwork())&&t.writeMessage(4,o,proto.Conf.Artwork.serializeBinaryToWriter)},proto.Conf.Metadata.prototype.getFormat=function(){return r.Message.getFieldWithDefault(this,1,"")},proto.Conf.Metadata.prototype.setFormat=function(e){return r.Message.setProto3StringField(this,1,e)},proto.Conf.Metadata.prototype.getSpeed=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.Conf.Metadata.prototype.setSpeed=function(e){return r.Message.setProto3IntField(this,2,e)},proto.Conf.Metadata.prototype.getPause=function(){return r.Message.getFieldWithDefault(this,3,0)},proto.Conf.Metadata.prototype.setPause=function(e){return r.Message.setProto3IntField(this,3,e)},proto.Conf.Metadata.prototype.getArtwork=function(){return r.Message.getWrapperField(this,proto.Conf.Artwork,4)},proto.Conf.Metadata.prototype.setArtwork=function(e){return r.Message.setWrapperField(this,4,e)},proto.Conf.Metadata.prototype.clearArtwork=function(){return this.setArtwork(void 0)},proto.Conf.Metadata.prototype.hasArtwork=function(){return null!=r.Message.getField(this,4)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Services.prototype.toObject=function(e){return proto.Conf.Services.toObject(e,this)},proto.Conf.Services.toObject=function(e,t){var o,r={metadata:(o=t.getMetadata())&&proto.Conf.Metadata.toObject(e,o),sleep:(o=t.getSleep())&&proto.Conf.SleepService.toObject(e,o)};return e&&(r.$jspbMessageInstance=t),r}),proto.Conf.Services.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Services;return proto.Conf.Services.deserializeBinaryFromReader(o,t)},proto.Conf.Services.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.Metadata;t.readMessage(o,proto.Conf.Metadata.deserializeBinaryFromReader),e.setMetadata(o);break;case 2:o=new proto.Conf.SleepService;t.readMessage(o,proto.Conf.SleepService.deserializeBinaryFromReader),e.setSleep(o);break;default:t.skipField()}}return e},proto.Conf.Services.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Services.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Services.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getMetadata())&&t.writeMessage(1,o,proto.Conf.Metadata.serializeBinaryToWriter),null!=(o=e.getSleep())&&t.writeMessage(2,o,proto.Conf.SleepService.serializeBinaryToWriter)},proto.Conf.Services.prototype.getMetadata=function(){return r.Message.getWrapperField(this,proto.Conf.Metadata,1)},proto.Conf.Services.prototype.setMetadata=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Services.prototype.clearMetadata=function(){return this.setMetadata(void 0)},proto.Conf.Services.prototype.hasMetadata=function(){return null!=r.Message.getField(this,1)},proto.Conf.Services.prototype.getSleep=function(){return r.Message.getWrapperField(this,proto.Conf.SleepService,2)},proto.Conf.Services.prototype.setSleep=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Services.prototype.clearSleep=function(){return this.setSleep(void 0)},proto.Conf.Services.prototype.hasSleep=function(){return null!=r.Message.getField(this,2)},r.Message.GENERATE_TO_OBJECT&&(proto.Conf.Config.prototype.toObject=function(e){return proto.Conf.Config.toObject(e,this)},proto.Conf.Config.toObject=function(e,t){var o,n={gpios:(o=t.getGpios())&&proto.Conf.Gpios.toObject(e,o),dev:(o=t.getDev())&&proto.Conf.Dev.toObject(e,o),services:(o=t.getServices())&&proto.Conf.Services.toObject(e,o),deviceName:r.Message.getFieldWithDefault(t,4,"")};return e&&(n.$jspbMessageInstance=t),n}),proto.Conf.Config.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.Conf.Config;return proto.Conf.Config.deserializeBinaryFromReader(o,t)},proto.Conf.Config.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=new proto.Conf.Gpios;t.readMessage(o,proto.Conf.Gpios.deserializeBinaryFromReader),e.setGpios(o);break;case 2:o=new proto.Conf.Dev;t.readMessage(o,proto.Conf.Dev.deserializeBinaryFromReader),e.setDev(o);break;case 3:o=new proto.Conf.Services;t.readMessage(o,proto.Conf.Services.deserializeBinaryFromReader),e.setServices(o);break;case 4:o=t.readString();e.setDeviceName(o);break;default:t.skipField()}}return e},proto.Conf.Config.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.Conf.Config.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.Conf.Config.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=e.getGpios())&&t.writeMessage(1,o,proto.Conf.Gpios.serializeBinaryToWriter),null!=(o=e.getDev())&&t.writeMessage(2,o,proto.Conf.Dev.serializeBinaryToWriter),null!=(o=e.getServices())&&t.writeMessage(3,o,proto.Conf.Services.serializeBinaryToWriter),(o=e.getDeviceName()).length>0&&t.writeString(4,o)},proto.Conf.Config.prototype.getGpios=function(){return r.Message.getWrapperField(this,proto.Conf.Gpios,1)},proto.Conf.Config.prototype.setGpios=function(e){return r.Message.setWrapperField(this,1,e)},proto.Conf.Config.prototype.clearGpios=function(){return this.setGpios(void 0)},proto.Conf.Config.prototype.hasGpios=function(){return null!=r.Message.getField(this,1)},proto.Conf.Config.prototype.getDev=function(){return r.Message.getWrapperField(this,proto.Conf.Dev,2)},proto.Conf.Config.prototype.setDev=function(e){return r.Message.setWrapperField(this,2,e)},proto.Conf.Config.prototype.clearDev=function(){return this.setDev(void 0)},proto.Conf.Config.prototype.hasDev=function(){return null!=r.Message.getField(this,2)},proto.Conf.Config.prototype.getServices=function(){return r.Message.getWrapperField(this,proto.Conf.Services,3)},proto.Conf.Config.prototype.setServices=function(e){return r.Message.setWrapperField(this,3,e)},proto.Conf.Config.prototype.clearServices=function(){return this.setServices(void 0)},proto.Conf.Config.prototype.hasServices=function(){return null!=r.Message.getField(this,3)},proto.Conf.Config.prototype.getDeviceName=function(){return r.Message.getFieldWithDefault(this,4,"")},proto.Conf.Config.prototype.setDeviceName=function(e){return r.Message.setProto3StringField(this,4,e)},proto.Conf.ButtonAction={ACTRLS_NONE:0,ACTRLS_POWER:1,ACTRLS_VOLUP:2,ACTRLS_VOLDOWN:3,ACTRLS_TOGGLE:4,ACTRLS_PLAY:5,ACTRLS_PAUSE:6,ACTRLS_STOP:7,ACTRLS_REW:8,ACTRLS_FWD:9,ACTRLS_PREV:10,ACTRLS_NEXT:11,BCTRLS_UP:12,BCTRLS_DOWN:13,BCTRLS_LEFT:14,BCTRLS_RIGHT:15,BCTRLS_PS1:16,BCTRLS_PS2:17,BCTRLS_PS3:18,BCTRLS_PS4:19,BCTRLS_PS5:20,BCTRLS_PS6:21,BCTRLS_PS7:22,BCTRLS_PS8:23,BCTRLS_PS9:24,BCTRLS_PS10:25,KNOB_LEFT:26,KNOB_RIGHT:27,KNOB_PUSH:28,ACTRLS_SLEEP:29},proto.Conf.DACModelEnum={UNSPECIFIED_MODEL:0,TAS57XX:1,TAS5713:2,AC101:3,WM8978:4,ES8388:5,I2S:6},proto.Conf.DeviceTypeEnum={UNSPECIFIED_TYPE:0,DEVTYPE_SPI:1,DEVTYPE_I2C:2,DEVTYPE__RMII:3},proto.Conf.DisplayDriverEnum={UNSPECIFIED_DRIVER:0,SSD1306:1,SSD1322:2,SSD1326:3,SSD1327:4,SH1106:5,SSD1675:6,ST7735:7,ST7789:8,ILI9341:9,ILI9341_24:10,SSD1351:11},proto.Conf.PortEnum={UNSPECIFIED_SYSTPORT:0,SYSTEM:1,DAC:2},proto.Conf.EthModelEnum={UNSPECIFIED_ETHMODEL:0,LAN8720:1,DM9051:2,W5500:3},proto.Conf.GPIOExpModelEnum={UNSPECIFIED_EXP:0,PCA9535:1,PCA85XX:2,MCP23017:3,MCP23S17:4},proto.Conf.HostEnum={UNSPECIFIED_HOST:0,HOST0:1,HOST1:2},proto.Conf.I2CPortEnum={UNSPECIFIED_PORT:0,I2CPORT0:1,I2CPORT1:2},proto.Conf.MCKEnum={UNSPECIFIED_MCK:0,MCK0:1,MCK1:2,MCK2:3},proto.Conf.BatteryChannelEnum={UNSPECIFIED_CH:0,CH0:1,CH1:2,CH2:3,CH3:4,CH4:5,CH5:6,CH6:7,CH7:8},proto.Conf.BatteryAttenEnum={UNSPECIFIED_ATT:0,ATT_0:1,ATT_1:2,ATT_2:3,ATT_3:4},proto.Conf.EthType={UNSPECIFIED_ETH:0,SPI:1,RMII:2},n.object.extend(t,proto.Conf)},21:(e,t,o)=>{var r=o(19),n=r,i=function(){return this?this:"undefined"!=typeof window?window:void 0!==i?i:"undefined"!=typeof self?self:Function("return this")()}.call(null),s=o(392);n.object.extend(proto,s),n.exportSymbol("proto.DescriptorSize",null,i),n.exportSymbol("proto.FieldType",null,i),n.exportSymbol("proto.IntSize",null,i),n.exportSymbol("proto.NanoPBOptions",null,i),n.exportSymbol("proto.TypenameMangling",null,i),n.exportSymbol("proto.nanopb",null,i),n.exportSymbol("proto.nanopbEnumopt",null,i),n.exportSymbol("proto.nanopbFileopt",null,i),n.exportSymbol("proto.nanopbMsgopt",null,i),proto.NanoPBOptions=function(e){r.Message.initialize(this,e,0,-1,proto.NanoPBOptions.repeatedFields_,null)},n.inherits(proto.NanoPBOptions,r.Message),n.DEBUG&&!COMPILED&&(proto.NanoPBOptions.displayName="proto.NanoPBOptions"),proto.NanoPBOptions.repeatedFields_=[24,26],r.Message.GENERATE_TO_OBJECT&&(proto.NanoPBOptions.prototype.toObject=function(e){return proto.NanoPBOptions.toObject(e,this)},proto.NanoPBOptions.toObject=function(e,t){var o,n={maxSize:null==(o=r.Message.getField(t,1))?void 0:o,maxLength:null==(o=r.Message.getField(t,14))?void 0:o,maxCount:null==(o=r.Message.getField(t,2))?void 0:o,intSize:r.Message.getFieldWithDefault(t,7,0),type:r.Message.getFieldWithDefault(t,3,0),longNames:r.Message.getBooleanFieldWithDefault(t,4,!0),packedStruct:r.Message.getBooleanFieldWithDefault(t,5,!1),packedEnum:r.Message.getBooleanFieldWithDefault(t,10,!1),skipMessage:r.Message.getBooleanFieldWithDefault(t,6,!1),noUnions:r.Message.getBooleanFieldWithDefault(t,8,!1),msgid:null==(o=r.Message.getField(t,9))?void 0:o,anonymousOneof:r.Message.getBooleanFieldWithDefault(t,11,!1),proto3:r.Message.getBooleanFieldWithDefault(t,12,!1),proto3SingularMsgs:r.Message.getBooleanFieldWithDefault(t,21,!1),enumToString:r.Message.getBooleanFieldWithDefault(t,13,!1),fixedLength:r.Message.getBooleanFieldWithDefault(t,15,!1),fixedCount:r.Message.getBooleanFieldWithDefault(t,16,!1),submsgCallback:r.Message.getBooleanFieldWithDefault(t,22,!1),mangleNames:r.Message.getFieldWithDefault(t,17,0),callbackDatatype:r.Message.getFieldWithDefault(t,18,"pb_callback_t"),callbackFunction:r.Message.getFieldWithDefault(t,19,"pb_default_field_callback"),descriptorsize:r.Message.getFieldWithDefault(t,20,0),defaultHas:r.Message.getBooleanFieldWithDefault(t,23,!1),includeList:null==(o=r.Message.getRepeatedField(t,24))?void 0:o,excludeList:null==(o=r.Message.getRepeatedField(t,26))?void 0:o,pb_package:null==(o=r.Message.getField(t,25))?void 0:o,typeOverride:null==(o=r.Message.getField(t,27))?void 0:o,sortByTag:r.Message.getBooleanFieldWithDefault(t,28,!0)};return e&&(n.$jspbMessageInstance=t),n}),proto.NanoPBOptions.deserializeBinary=function(e){var t=new r.BinaryReader(e),o=new proto.NanoPBOptions;return proto.NanoPBOptions.deserializeBinaryFromReader(o,t)},proto.NanoPBOptions.deserializeBinaryFromReader=function(e,t){for(;t.nextField()&&!t.isEndGroup();){switch(t.getFieldNumber()){case 1:var o=t.readInt32();e.setMaxSize(o);break;case 14:o=t.readInt32();e.setMaxLength(o);break;case 2:o=t.readInt32();e.setMaxCount(o);break;case 7:o=t.readEnum();e.setIntSize(o);break;case 3:o=t.readEnum();e.setType(o);break;case 4:o=t.readBool();e.setLongNames(o);break;case 5:o=t.readBool();e.setPackedStruct(o);break;case 10:o=t.readBool();e.setPackedEnum(o);break;case 6:o=t.readBool();e.setSkipMessage(o);break;case 8:o=t.readBool();e.setNoUnions(o);break;case 9:o=t.readUint32();e.setMsgid(o);break;case 11:o=t.readBool();e.setAnonymousOneof(o);break;case 12:o=t.readBool();e.setProto3(o);break;case 21:o=t.readBool();e.setProto3SingularMsgs(o);break;case 13:o=t.readBool();e.setEnumToString(o);break;case 15:o=t.readBool();e.setFixedLength(o);break;case 16:o=t.readBool();e.setFixedCount(o);break;case 22:o=t.readBool();e.setSubmsgCallback(o);break;case 17:o=t.readEnum();e.setMangleNames(o);break;case 18:o=t.readString();e.setCallbackDatatype(o);break;case 19:o=t.readString();e.setCallbackFunction(o);break;case 20:o=t.readEnum();e.setDescriptorsize(o);break;case 23:o=t.readBool();e.setDefaultHas(o);break;case 24:o=t.readString();e.addInclude(o);break;case 26:o=t.readString();e.addExclude(o);break;case 25:o=t.readString();e.setPackage(o);break;case 27:o=t.readEnum();e.setTypeOverride(o);break;case 28:o=t.readBool();e.setSortByTag(o);break;default:t.skipField()}}return e},proto.NanoPBOptions.prototype.serializeBinary=function(){var e=new r.BinaryWriter;return proto.NanoPBOptions.serializeBinaryToWriter(this,e),e.getResultBuffer()},proto.NanoPBOptions.serializeBinaryToWriter=function(e,t){var o=void 0;null!=(o=r.Message.getField(e,1))&&t.writeInt32(1,o),null!=(o=r.Message.getField(e,14))&&t.writeInt32(14,o),null!=(o=r.Message.getField(e,2))&&t.writeInt32(2,o),null!=(o=r.Message.getField(e,7))&&t.writeEnum(7,o),null!=(o=r.Message.getField(e,3))&&t.writeEnum(3,o),null!=(o=r.Message.getField(e,4))&&t.writeBool(4,o),null!=(o=r.Message.getField(e,5))&&t.writeBool(5,o),null!=(o=r.Message.getField(e,10))&&t.writeBool(10,o),null!=(o=r.Message.getField(e,6))&&t.writeBool(6,o),null!=(o=r.Message.getField(e,8))&&t.writeBool(8,o),null!=(o=r.Message.getField(e,9))&&t.writeUint32(9,o),null!=(o=r.Message.getField(e,11))&&t.writeBool(11,o),null!=(o=r.Message.getField(e,12))&&t.writeBool(12,o),null!=(o=r.Message.getField(e,21))&&t.writeBool(21,o),null!=(o=r.Message.getField(e,13))&&t.writeBool(13,o),null!=(o=r.Message.getField(e,15))&&t.writeBool(15,o),null!=(o=r.Message.getField(e,16))&&t.writeBool(16,o),null!=(o=r.Message.getField(e,22))&&t.writeBool(22,o),null!=(o=r.Message.getField(e,17))&&t.writeEnum(17,o),null!=(o=r.Message.getField(e,18))&&t.writeString(18,o),null!=(o=r.Message.getField(e,19))&&t.writeString(19,o),null!=(o=r.Message.getField(e,20))&&t.writeEnum(20,o),null!=(o=r.Message.getField(e,23))&&t.writeBool(23,o),(o=e.getIncludeList()).length>0&&t.writeRepeatedString(24,o),(o=e.getExcludeList()).length>0&&t.writeRepeatedString(26,o),null!=(o=r.Message.getField(e,25))&&t.writeString(25,o),null!=(o=r.Message.getField(e,27))&&t.writeEnum(27,o),null!=(o=r.Message.getField(e,28))&&t.writeBool(28,o)},proto.NanoPBOptions.prototype.getMaxSize=function(){return r.Message.getFieldWithDefault(this,1,0)},proto.NanoPBOptions.prototype.setMaxSize=function(e){return r.Message.setField(this,1,e)},proto.NanoPBOptions.prototype.clearMaxSize=function(){return r.Message.setField(this,1,void 0)},proto.NanoPBOptions.prototype.hasMaxSize=function(){return null!=r.Message.getField(this,1)},proto.NanoPBOptions.prototype.getMaxLength=function(){return r.Message.getFieldWithDefault(this,14,0)},proto.NanoPBOptions.prototype.setMaxLength=function(e){return r.Message.setField(this,14,e)},proto.NanoPBOptions.prototype.clearMaxLength=function(){return r.Message.setField(this,14,void 0)},proto.NanoPBOptions.prototype.hasMaxLength=function(){return null!=r.Message.getField(this,14)},proto.NanoPBOptions.prototype.getMaxCount=function(){return r.Message.getFieldWithDefault(this,2,0)},proto.NanoPBOptions.prototype.setMaxCount=function(e){return r.Message.setField(this,2,e)},proto.NanoPBOptions.prototype.clearMaxCount=function(){return r.Message.setField(this,2,void 0)},proto.NanoPBOptions.prototype.hasMaxCount=function(){return null!=r.Message.getField(this,2)},proto.NanoPBOptions.prototype.getIntSize=function(){return r.Message.getFieldWithDefault(this,7,0)},proto.NanoPBOptions.prototype.setIntSize=function(e){return r.Message.setField(this,7,e)},proto.NanoPBOptions.prototype.clearIntSize=function(){return r.Message.setField(this,7,void 0)},proto.NanoPBOptions.prototype.hasIntSize=function(){return null!=r.Message.getField(this,7)},proto.NanoPBOptions.prototype.getType=function(){return r.Message.getFieldWithDefault(this,3,0)},proto.NanoPBOptions.prototype.setType=function(e){return r.Message.setField(this,3,e)},proto.NanoPBOptions.prototype.clearType=function(){return r.Message.setField(this,3,void 0)},proto.NanoPBOptions.prototype.hasType=function(){return null!=r.Message.getField(this,3)},proto.NanoPBOptions.prototype.getLongNames=function(){return r.Message.getBooleanFieldWithDefault(this,4,!0)},proto.NanoPBOptions.prototype.setLongNames=function(e){return r.Message.setField(this,4,e)},proto.NanoPBOptions.prototype.clearLongNames=function(){return r.Message.setField(this,4,void 0)},proto.NanoPBOptions.prototype.hasLongNames=function(){return null!=r.Message.getField(this,4)},proto.NanoPBOptions.prototype.getPackedStruct=function(){return r.Message.getBooleanFieldWithDefault(this,5,!1)},proto.NanoPBOptions.prototype.setPackedStruct=function(e){return r.Message.setField(this,5,e)},proto.NanoPBOptions.prototype.clearPackedStruct=function(){return r.Message.setField(this,5,void 0)},proto.NanoPBOptions.prototype.hasPackedStruct=function(){return null!=r.Message.getField(this,5)},proto.NanoPBOptions.prototype.getPackedEnum=function(){return r.Message.getBooleanFieldWithDefault(this,10,!1)},proto.NanoPBOptions.prototype.setPackedEnum=function(e){return r.Message.setField(this,10,e)},proto.NanoPBOptions.prototype.clearPackedEnum=function(){return r.Message.setField(this,10,void 0)},proto.NanoPBOptions.prototype.hasPackedEnum=function(){return null!=r.Message.getField(this,10)},proto.NanoPBOptions.prototype.getSkipMessage=function(){return r.Message.getBooleanFieldWithDefault(this,6,!1)},proto.NanoPBOptions.prototype.setSkipMessage=function(e){return r.Message.setField(this,6,e)},proto.NanoPBOptions.prototype.clearSkipMessage=function(){return r.Message.setField(this,6,void 0)},proto.NanoPBOptions.prototype.hasSkipMessage=function(){return null!=r.Message.getField(this,6)},proto.NanoPBOptions.prototype.getNoUnions=function(){return r.Message.getBooleanFieldWithDefault(this,8,!1)},proto.NanoPBOptions.prototype.setNoUnions=function(e){return r.Message.setField(this,8,e)},proto.NanoPBOptions.prototype.clearNoUnions=function(){return r.Message.setField(this,8,void 0)},proto.NanoPBOptions.prototype.hasNoUnions=function(){return null!=r.Message.getField(this,8)},proto.NanoPBOptions.prototype.getMsgid=function(){return r.Message.getFieldWithDefault(this,9,0)},proto.NanoPBOptions.prototype.setMsgid=function(e){return r.Message.setField(this,9,e)},proto.NanoPBOptions.prototype.clearMsgid=function(){return r.Message.setField(this,9,void 0)},proto.NanoPBOptions.prototype.hasMsgid=function(){return null!=r.Message.getField(this,9)},proto.NanoPBOptions.prototype.getAnonymousOneof=function(){return r.Message.getBooleanFieldWithDefault(this,11,!1)},proto.NanoPBOptions.prototype.setAnonymousOneof=function(e){return r.Message.setField(this,11,e)},proto.NanoPBOptions.prototype.clearAnonymousOneof=function(){return r.Message.setField(this,11,void 0)},proto.NanoPBOptions.prototype.hasAnonymousOneof=function(){return null!=r.Message.getField(this,11)},proto.NanoPBOptions.prototype.getProto3=function(){return r.Message.getBooleanFieldWithDefault(this,12,!1)},proto.NanoPBOptions.prototype.setProto3=function(e){return r.Message.setField(this,12,e)},proto.NanoPBOptions.prototype.clearProto3=function(){return r.Message.setField(this,12,void 0)},proto.NanoPBOptions.prototype.hasProto3=function(){return null!=r.Message.getField(this,12)},proto.NanoPBOptions.prototype.getProto3SingularMsgs=function(){return r.Message.getBooleanFieldWithDefault(this,21,!1)},proto.NanoPBOptions.prototype.setProto3SingularMsgs=function(e){return r.Message.setField(this,21,e)},proto.NanoPBOptions.prototype.clearProto3SingularMsgs=function(){return r.Message.setField(this,21,void 0)},proto.NanoPBOptions.prototype.hasProto3SingularMsgs=function(){return null!=r.Message.getField(this,21)},proto.NanoPBOptions.prototype.getEnumToString=function(){return r.Message.getBooleanFieldWithDefault(this,13,!1)},proto.NanoPBOptions.prototype.setEnumToString=function(e){return r.Message.setField(this,13,e)},proto.NanoPBOptions.prototype.clearEnumToString=function(){return r.Message.setField(this,13,void 0)},proto.NanoPBOptions.prototype.hasEnumToString=function(){return null!=r.Message.getField(this,13)},proto.NanoPBOptions.prototype.getFixedLength=function(){return r.Message.getBooleanFieldWithDefault(this,15,!1)},proto.NanoPBOptions.prototype.setFixedLength=function(e){return r.Message.setField(this,15,e)},proto.NanoPBOptions.prototype.clearFixedLength=function(){return r.Message.setField(this,15,void 0)},proto.NanoPBOptions.prototype.hasFixedLength=function(){return null!=r.Message.getField(this,15)},proto.NanoPBOptions.prototype.getFixedCount=function(){return r.Message.getBooleanFieldWithDefault(this,16,!1)},proto.NanoPBOptions.prototype.setFixedCount=function(e){return r.Message.setField(this,16,e)},proto.NanoPBOptions.prototype.clearFixedCount=function(){return r.Message.setField(this,16,void 0)},proto.NanoPBOptions.prototype.hasFixedCount=function(){return null!=r.Message.getField(this,16)},proto.NanoPBOptions.prototype.getSubmsgCallback=function(){return r.Message.getBooleanFieldWithDefault(this,22,!1)},proto.NanoPBOptions.prototype.setSubmsgCallback=function(e){return r.Message.setField(this,22,e)},proto.NanoPBOptions.prototype.clearSubmsgCallback=function(){return r.Message.setField(this,22,void 0)},proto.NanoPBOptions.prototype.hasSubmsgCallback=function(){return null!=r.Message.getField(this,22)},proto.NanoPBOptions.prototype.getMangleNames=function(){return r.Message.getFieldWithDefault(this,17,0)},proto.NanoPBOptions.prototype.setMangleNames=function(e){return r.Message.setField(this,17,e)},proto.NanoPBOptions.prototype.clearMangleNames=function(){return r.Message.setField(this,17,void 0)},proto.NanoPBOptions.prototype.hasMangleNames=function(){return null!=r.Message.getField(this,17)},proto.NanoPBOptions.prototype.getCallbackDatatype=function(){return r.Message.getFieldWithDefault(this,18,"pb_callback_t")},proto.NanoPBOptions.prototype.setCallbackDatatype=function(e){return r.Message.setField(this,18,e)},proto.NanoPBOptions.prototype.clearCallbackDatatype=function(){return r.Message.setField(this,18,void 0)},proto.NanoPBOptions.prototype.hasCallbackDatatype=function(){return null!=r.Message.getField(this,18)},proto.NanoPBOptions.prototype.getCallbackFunction=function(){return r.Message.getFieldWithDefault(this,19,"pb_default_field_callback")},proto.NanoPBOptions.prototype.setCallbackFunction=function(e){return r.Message.setField(this,19,e)},proto.NanoPBOptions.prototype.clearCallbackFunction=function(){return r.Message.setField(this,19,void 0)},proto.NanoPBOptions.prototype.hasCallbackFunction=function(){return null!=r.Message.getField(this,19)},proto.NanoPBOptions.prototype.getDescriptorsize=function(){return r.Message.getFieldWithDefault(this,20,0)},proto.NanoPBOptions.prototype.setDescriptorsize=function(e){return r.Message.setField(this,20,e)},proto.NanoPBOptions.prototype.clearDescriptorsize=function(){return r.Message.setField(this,20,void 0)},proto.NanoPBOptions.prototype.hasDescriptorsize=function(){return null!=r.Message.getField(this,20)},proto.NanoPBOptions.prototype.getDefaultHas=function(){return r.Message.getBooleanFieldWithDefault(this,23,!1)},proto.NanoPBOptions.prototype.setDefaultHas=function(e){return r.Message.setField(this,23,e)},proto.NanoPBOptions.prototype.clearDefaultHas=function(){return r.Message.setField(this,23,void 0)},proto.NanoPBOptions.prototype.hasDefaultHas=function(){return null!=r.Message.getField(this,23)},proto.NanoPBOptions.prototype.getIncludeList=function(){return r.Message.getRepeatedField(this,24)},proto.NanoPBOptions.prototype.setIncludeList=function(e){return r.Message.setField(this,24,e||[])},proto.NanoPBOptions.prototype.addInclude=function(e,t){return r.Message.addToRepeatedField(this,24,e,t)},proto.NanoPBOptions.prototype.clearIncludeList=function(){return this.setIncludeList([])},proto.NanoPBOptions.prototype.getExcludeList=function(){return r.Message.getRepeatedField(this,26)},proto.NanoPBOptions.prototype.setExcludeList=function(e){return r.Message.setField(this,26,e||[])},proto.NanoPBOptions.prototype.addExclude=function(e,t){return r.Message.addToRepeatedField(this,26,e,t)},proto.NanoPBOptions.prototype.clearExcludeList=function(){return this.setExcludeList([])},proto.NanoPBOptions.prototype.getPackage=function(){return r.Message.getFieldWithDefault(this,25,"")},proto.NanoPBOptions.prototype.setPackage=function(e){return r.Message.setField(this,25,e)},proto.NanoPBOptions.prototype.clearPackage=function(){return r.Message.setField(this,25,void 0)},proto.NanoPBOptions.prototype.hasPackage=function(){return null!=r.Message.getField(this,25)},proto.NanoPBOptions.prototype.getTypeOverride=function(){return r.Message.getFieldWithDefault(this,27,1)},proto.NanoPBOptions.prototype.setTypeOverride=function(e){return r.Message.setField(this,27,e)},proto.NanoPBOptions.prototype.clearTypeOverride=function(){return r.Message.setField(this,27,void 0)},proto.NanoPBOptions.prototype.hasTypeOverride=function(){return null!=r.Message.getField(this,27)},proto.NanoPBOptions.prototype.getSortByTag=function(){return r.Message.getBooleanFieldWithDefault(this,28,!0)},proto.NanoPBOptions.prototype.setSortByTag=function(e){return r.Message.setField(this,28,e)},proto.NanoPBOptions.prototype.clearSortByTag=function(){return r.Message.setField(this,28,void 0)},proto.NanoPBOptions.prototype.hasSortByTag=function(){return null!=r.Message.getField(this,28)},proto.FieldType={FT_DEFAULT:0,FT_CALLBACK:1,FT_POINTER:4,FT_STATIC:2,FT_IGNORE:3,FT_INLINE:5},proto.IntSize={IS_DEFAULT:0,IS_8:8,IS_16:16,IS_32:32,IS_64:64},proto.TypenameMangling={M_NONE:0,M_STRIP_PACKAGE:1,M_FLATTEN:2,M_PACKAGE_INITIALS:3},proto.DescriptorSize={DS_AUTO:0,DS_1:1,DS_2:2,DS_4:4,DS_8:8},proto.nanopbFileopt=new r.ExtensionFieldInfo(1010,{nanopbFileopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),s.FileOptions.extensionsBinary[1010]=new r.ExtensionFieldBinaryInfo(proto.nanopbFileopt,r.BinaryReader.prototype.readMessage,r.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),s.FileOptions.extensions[1010]=proto.nanopbFileopt,proto.nanopbMsgopt=new r.ExtensionFieldInfo(1010,{nanopbMsgopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),s.MessageOptions.extensionsBinary[1010]=new r.ExtensionFieldBinaryInfo(proto.nanopbMsgopt,r.BinaryReader.prototype.readMessage,r.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),s.MessageOptions.extensions[1010]=proto.nanopbMsgopt,proto.nanopbEnumopt=new r.ExtensionFieldInfo(1010,{nanopbEnumopt:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),s.EnumOptions.extensionsBinary[1010]=new r.ExtensionFieldBinaryInfo(proto.nanopbEnumopt,r.BinaryReader.prototype.readMessage,r.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),s.EnumOptions.extensions[1010]=proto.nanopbEnumopt,proto.nanopb=new r.ExtensionFieldInfo(1010,{nanopb:0},proto.NanoPBOptions,proto.NanoPBOptions.toObject,0),s.FieldOptions.extensionsBinary[1010]=new r.ExtensionFieldBinaryInfo(proto.nanopb,r.BinaryReader.prototype.readMessage,r.BinaryWriter.prototype.writeMessage,proto.NanoPBOptions.serializeBinaryToWriter,proto.NanoPBOptions.deserializeBinaryFromReader,!1),s.FieldOptions.extensions[1010]=proto.nanopb,n.object.extend(t,proto)},393:(e,t,o)=>{"use strict";o.r(t)},607:(e,t,o)=>{"use strict";o(138),o(393),o(861),o(44)},44:function(e,t,o){"use strict";var r=o(755),n=this&&this.__createBinding||(Object.create?function(e,t,o,r){void 0===r&&(r=o);var n=Object.getOwnPropertyDescriptor(t,o);n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,r,n)}:function(e,t,o,r){void 0===r&&(r=o),e[r]=t[o]}),i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var o in e)"default"!==o&&Object.prototype.hasOwnProperty.call(e,o)&&n(t,e,o);return i(t,e),t},a=this&&this.__awaiter||function(e,t,o,r){return new(o||(o=Promise))((function(n,i){function s(e){try{p(r.next(e))}catch(e){i(e)}}function a(e){try{p(r.throw(e))}catch(e){i(e)}}function p(e){var t;e.done?n(e.value):(t=e.value,t instanceof o?t:new o((function(e){e(t)}))).then(s,a)}p((r=r.apply(e,t||[])).next())}))},p=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=o(492);const u=p(o(646)),f=s(o(874)),c=s(o(138));function d(){r("#flashfilename").val=null,O.StartOTA()}function g(e){"reboot_ota"==e?(r("#reboot_ota_nav").removeClass("active").prop("disabled",!0),le(500,"","reboot_ota")):(r("#reboot_nav").removeClass("active"),le(500,"",e))}function C(e){let t,o,n,i;return"string"==typeof e?(o=e,t=r(`#${o}`)):(o=r(e).attr("id"),t=r(e)),"checkbox"===t.attr("type")?(i=t.prop("checked")?o.replace("cmd_opt_",""):"",n=!0):(i=o.replace("cmd_opt_",""),n=t.val(),"string"==typeof n?n=`${n.includes(" ")?'"':""}${n}${n.includes(" ")?'"':""}`:"number"!=typeof n&&(n=n.toString())),{opt:i,val:n}}function h(){let e=y(u.default.get("show-nvs"));const t=r("input#show-nvs")[0];t.checked=e,t.checked||k?r('*[href*="-nvs"]').show():r('*[href*="-nvs"]').hide()}function y(e){return null!=e&&"string"==typeof e&&e.match("[Yy1]").length>0}var M;console.log(f),window.hideSurrounding=function(e){r(e).parent().parent().hide()},window.hFlash=function(){d()},window.handleReboot=function(e){g(e)},Object.assign(String.prototype,{format(...e){return this.replace(/{(\d+)}/g,(function(t,o){const r=parseInt(o,10);return void 0!==e[r]?e[r]:t}))}}),Object.assign(String.prototype,{encodeHTML(){return l.encode(this).replace(/\n/g,"
")}}),Object.assign(Date.prototype,{toLocalShort(){return this.toLocaleString(void 0,{dateStyle:"short",timeStyle:"short"})}}),function(e){e[e.NVS_TYPE_U8=1]="NVS_TYPE_U8",e[e.NVS_TYPE_I8=17]="NVS_TYPE_I8",e[e.NVS_TYPE_U16=2]="NVS_TYPE_U16",e[e.NVS_TYPE_I16=18]="NVS_TYPE_I16",e[e.NVS_TYPE_U32=4]="NVS_TYPE_U32",e[e.NVS_TYPE_I32=20]="NVS_TYPE_I32",e[e.NVS_TYPE_U64=8]="NVS_TYPE_U64",e[e.NVS_TYPE_I64=24]="NVS_TYPE_I64",e[e.NVS_TYPE_STR=33]="NVS_TYPE_STR",e[e.NVS_TYPE_BLOB=66]="NVS_TYPE_BLOB",e[e.NVS_TYPE_ANY=255]="NVS_TYPE_ANY"}(M||(M={}));const m={bt_playing:{label:"",icon:"media_bluetooth_on"},bt_disconnected:{label:"",icon:"media_bluetooth_off"},bt_neutral:{label:"",icon:"bluetooth"},bt_connecting:{label:"",icon:"bluetooth_searching"},bt_connected:{label:"",icon:"bluetooth_connected"},bt_disabled:{label:"",icon:"bluetooth_disabled"},play_arrow:{label:"",icon:"play_circle_filled"},pause:{label:"",icon:"pause_circle"},stop:{label:"",icon:"stop_circle"},"":{label:"",icon:""}},B=[{icon:"battery_0_bar",label:"▪",ranges:[{f:5.8,t:6.8},{f:8.8,t:10.2}]},{icon:"battery_2_bar",label:"▪▪",ranges:[{f:6.8,t:7.4},{f:10.2,t:11.1}]},{icon:"battery_3_bar",label:"▪▪▪",ranges:[{f:7.4,t:7.5},{f:11.1,t:11.25}]},{icon:"battery_4_bar",label:"▪▪▪▪",ranges:[{f:7.5,t:7.8},{f:11.25,t:11.7}]}],S=[{desc:"Idle",sub:["bt_neutral"]},{desc:"Discovering",sub:["bt_connecting"]},{desc:"Discovered",sub:["bt_connecting"]},{desc:"Unconnected",sub:["bt_disconnected"]},{desc:"Connecting",sub:["bt_connecting"]},{desc:"Connected",sub:["bt_connected","play_arrow","bt_playing","pause","stop"]},{desc:"Disconnecting",sub:["bt_disconnected"]}],v={OK:0,FAIL:1,DISC:2,LOST:3,RESTORE:4,ETH:5},b=["eRunning","eReady","eBlocked","eSuspended","eDeleted"];let O={NONE:0,REBOOT_TO_RECOVERY:2,SET_FWURL:5,FLASHING:6,DONE:7,UPLOADING:8,ERROR:9,UPLOADCOMPLETE:10,_state:-1,olderRecovery:!1,statusText:"",flashURL:"",flashFileName:"",statusPercent:0,Completed:!1,recovery:!1,prevRecovery:!1,updateModal:new c.Modal(document.getElementById("otadiv"),{}),reset:function(){return this.olderRecovery=!1,this.statusText="",this.statusPercent=-1,this.flashURL="",this.flashFileName=void 0,this.UpdateProgress(),r("#rTable tr.release").removeClass("table-success table-warning"),r(".flact").prop("disabled",!1),r("#flashfilename")[0].value=null,r("#fw-url-input")[0].value=null,this.isStateError()||(r("span#flash-status").html(""),r("#fwProgressLabel").parent().removeClass("bg-danger")),this._state=this.NONE,this},isStateUploadComplete:function(){return this._state==this.UPLOADCOMPLETE},isStateError:function(){return this._state==this.ERROR},isStateNone:function(){return this._state==this.NONE},isStateRebootRecovery:function(){return this._state==this.REBOOT_TO_RECOVERY},isStateSetUrl:function(){return this._state==this.SET_FWURL},isStateFlashing:function(){return this._state==this.FLASHING},isStateDone:function(){return this._state==this.DONE},isStateUploading:function(){return this._state==this.UPLOADING},init:function(){return this._state=this.NONE,this},SetStateError:function(){return this._state=this.ERROR,r("#fwProgressLabel").parent().addClass("bg-danger"),this},SetStateNone:function(){return this._state=this.NONE,this},SetStateRebootRecovery:function(){return this._state=this.REBOOT_TO_RECOVERY,this.SetStatusText("Starting recovery mode."),r.ajax({url:"/recovery.json",context:this,dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now()}),error:function(e,t,o){var r;this.setOTAError(`Unexpected error while trying to restart to recovery. (status=${null!==(r=e.status)&&void 0!==r?r:""}, error=${null!=o?o:""} ) `)},complete:function(e){this.SetStatusText("Waiting for system to boot.")}}),this},SetStateSetUrl:function(){return this._state=this.SET_FWURL,this.statusText="Sending firmware download location.",D({fwurl:{value:this.flashURL,type:33}}),this},SetStateFlashing:function(){return this._state=this.FLASHING,this},SetStateDone:function(){return this._state=this.DONE,this.reset(),this},SetStateUploading:function(){return this._state=this.UPLOADING,this.SetStatusText("Sending file to device.")},SetStateUploadComplete:function(){return this._state=this.UPLOADCOMPLETE,this},isFlashExecuting:function(){return!0==(this._state!=this.UPLOADING&&(""!==this.statusText||this.statusPercent>=0))},toString:function(){return Object.keys(this).find((e=>this[e]===this._state))},setOTATargets:function(){this.flashURL="",this.flashFileName="",this.flashURL=r("#fw-url-input").val();let e=r("#flashfilename")[0].files;return e.length>0&&(this.flashFileName=e[0]),0==this.flashFileName.length&&0==this.flashURL.length&&this.setOTAError("Invalid url or file. Cannot start OTA"),this},setOTAError:function(e){return this.SetStateError().SetStatusPercent(0).SetStatusText(e).reset(),this},ShowDialog:function(){return this.isStateNone()||(this.updateModal.show(),r(".flact").prop("disabled",!0)),this},SetStatusPercent:function(e){var t=this.statusPercent!=e;return this.statusPercent=e,t&&(this.isStateUploading()||this.isStateFlashing()||this.SetStateFlashing(),100==e&&(this.isStateFlashing()?this.SetStateDone():this.isStateUploading()&&(this.statusPercent=0,this.SetStateFlashing())),this.UpdateProgress().ShowDialog()),this},SetStatusText:function(e){var t=this.statusText!=e;return this.statusText=e,t&&(r("span#flash-status").html(this.statusText),this.ShowDialog()),this},UpdateProgress:function(){return r(".progress-bar").css("width",this.statusPercent+"%").attr("aria-valuenow",this.statusPercent).text(this.statusPercent+"%"),r(".progress-bar").html((this.isStateDone()?100:this.statusPercent)+"%"),this},StartOTA:function(){return this.logEvent(this.StartOTA.name),r("#fwProgressLabel").parent().removeClass("bg-danger"),this.setOTATargets(),this.isStateError()||(k?this.SetStateFlashing().TargetReadyStartOTA():this.SetStateRebootRecovery()),this},UploadLocalFile:function(){this.SetStateUploading();const e=new XMLHttpRequest;var t=this.HandleUploadProgressEvent.bind(this),o=this.setOTAError.bind(this);e.upload.addEventListener("progress",t,!1),e.onreadystatechange=function(){4===e.readyState&&(0!==e.status&&404!==e.status||o("Upload Failed. Recovery version might not support uploading. Please use web update instead."))},e.open("POST","/flash.json",!0),e.send(this.flashFileName)},TargetReadyStartOTA:function(){return k&&this.prevRecovery&&!this.isStateRebootRecovery()&&!this.isStateFlashing()?this:(this.logEvent(this.TargetReadyStartOTA.name),k?(this.prevRecovery=!0,void(""!==this.flashFileName?this.UploadLocalFile():""!=this.flashURL?this.SetStateSetUrl():this.setOTAError("Invalid URL or file name while trying to start the OTa process"))):(console.error("Event TargetReadyStartOTA fired in the wrong mode "),this))},HandleUploadProgressEvent:function(e){this.logEvent(this.HandleUploadProgressEvent.name),this.SetStateUploading().SetStatusPercent(Math.round(e.loaded/e.total*100)).SetStatusText("Uploading file to device")},EventTargetStatus:function(e){var t,o;this.isStateNone()||this.logEvent(this.EventTargetStatus.name),null!==(t=e.ota_pct)&&void 0!==t&&t&&(this.olderRecovery=!0,this.SetStatusPercent(e.ota_pct)),""!=(null!==(o=e.ota_dsc)&&void 0!==o?o:"")&&(this.olderRecovery=!0,this.SetStatusText(e.ota_dsc)),null!=e.recovery&&(this.recovery=1===e.recovery),this.isStateRebootRecovery()&&this.recovery&&this.TargetReadyStartOTA()},EventOTAMessageClass:function(e){this.logEvent(this.EventOTAMessageClass.name);var t=JSON.parse(e);this.SetStatusPercent(t.ota_pct).SetStatusText(t.ota_dsc)},logEvent:function(e){console.log(`${e}, flash state ${this.toString()}, recovery: ${this.recovery}, ota pct: ${this.statusPercent}, ota desc: ${this.statusText}`)}},F=!1,I=!1,P=2500;function D(e){let t={timestamp:Date.now(),config:e};r.ajax({url:"/config.json",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(t),error:T})}function E(e){const t={};let o,r,n="";const i=e.match(/("[^"]+"|'[^']+'|\S+)/g)||[];let s=0;for(;s0&&(t=t.substring(0,t.indexOf(" "))));return t}(t),r=function(e){let t;e.n&&(t=e.n.replace(/"/g,"").replace(/'/g,""));return t}(t);let a={btname:null,n:null};if(t.o&&"BT"===o.toUpperCase()){let e=E(t.o);e.name&&(a.btname=e.name),delete t.o}return t.n&&(a.n=t.n,delete t.n),{name:r,output:o,options:t,otherValues:n,otherOptions:a}}function w(){return V.hasOwnProperty("ip")&&"0.0.0.0"!=V.ip&&""!=V.ip}function G(e){return w()?e.icon:e.label}function W(e){r("#o_type").children("span").css({display:"none"});let t=!1;e!==H&&(t=!0,H=e),r("#"+H).prop("checked",!0),r("#o_"+H).css({display:"inline"}),t&&Object.entries(A[H]).forEach((([e,t])=>{r(`#cmd_opt_${e}`).val(t)}))}function T(e,t,o){console.log(e.status),console.log(o),""!==o&&Fe(o,"MESSAGING_ERROR")}function R(e,t,o,n=!1){let i="table-success";"MESSAGING_WARNING"===t?i="table-warning":"MESSAGING_ERROR"===t&&(i="table-danger"),r("#toast_"+e).removeClass("table-success").removeClass("table-warning").removeClass("table-danger").addClass(i).addClass("show");let s=o.substring(0,o.length-1).encodeHTML().replace(/\n/g,"
");s=(r("#msg_"+e).html().length>0&&n?r("#msg_"+e).html()+"
":"")+s,r("#msg_"+e).html(s)}let _="https://api.github.com/repos/sle118/squeezelite-esp32/releases",k=!1,N=!1,z="";const A={i2s:{b:"500:2000",C:"30",W:"",Z:"96000",o:"I2S"},spdif:{b:"500:2000",C:"30",W:"",Z:"48000",o:"SPDIF"},bt:{b:"500:2000",C:"30",W:"",Z:"44100",o:"BT"}};let x,j={codecs:["flac","pcm","mp3","ogg","aac","wma","alac","dsd","mad","mpg"]},L=null,$=0,U="MESSAGING_INFO",J=NaN;var H="";let V,Y,K="",q="Squeezelite-ESP32",X="",Z=q,Q=16,ee="",te=q,oe="",re="#cfg-audio-bt_source-sink_name",ne="",ie="";const se={CONN:0,MAN:1,STS:2};function ae(e,t){return new Promise(((o,r)=>{e.then((e=>setTimeout((()=>o(e)),t)),(e=>setTimeout((()=>r(e)),t)))}))}function pe(e){const t={};r("input.nvs").each((function(o,r){const n=r,i=n.attributes.getNamedItem("nvs_type");if(!e&&i){const e=parseInt(i.value,10);if(""!==n.id){const o=e<=M.NVS_TYPE_I64?parseInt(n.value,10):n.value;t[n.id]={value:o,type:e}}}else""!==n.id&&(t[n.id]=n.value)}));const o=r("#nvs-new-key").val(),n=r("#nvs-new-value").val();return o&&""!==o&&(t[o]=e?n:{value:n,type:M.NVS_TYPE_I8}),t}function le(e,t,o="reboot"){const n=`/${o}.json`;r("tbody#tasks").empty(),r("#tasks_sect").css("visibility","collapse"),ae(Promise.resolve({cmdname:t,url:n}),e).then((function(e){console.log("now triggering reboot"),r("button[onclick*='handleReboot']").addClass("rebooting"),r.ajax({complete:function(){console.log("reboot call completed"),ae(Promise.resolve(e),6e3).then((function(e){}))}})}))}function ue(e){R("cfg-audio-tmpl","MESSAGING_INFO","Saving.\n",!1);let t=`squeezelite -o ${H} `;r(".sqcmd").each((function(){let{opt:e,val:o}=C(r(this));if(e&&e.length>0&&"boolean"==typeof o||"string"==typeof o&&o.length>0){o="boolean"==typeof o?"":o,t+=`${":"===e?e:` -${e} `} ${o}`}}));const o=r("#cmd_opt_R input[name=resample]:checked");o.length>0&&""!==o.attr("suffix")&&(t+=o.attr("suffix"),r("#resample_i").is(":checked")&&"true"==o.attr("aint")&&(t+=r("#resample_i").attr("suffix"))),"bt"===H&&R("cfg-audio-tmpl","MESSAGING_INFO","Remember to configure the Bluetooth audio device name.\n",!0);const n={timestamp:Date.now(),config:{autoexec1:{value:t,type:M.NVS_TYPE_STR}}};r.ajax({url:"/config.json",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(n),error:T,complete:function(t){t.responseText&&"OK"===JSON.parse(t.responseText).result?(R("cfg-audio-tmpl","MESSAGING_INFO","Done.\n",!0),e&&le(1500,"cfg-audio-tmpl")):JSON.parse(t.responseText).result?R("cfg-audio-tmpl","MESSAGING_WARNING",JSON.parse(t.responseText).Result+"\n",!0):R("cfg-audio-tmpl","MESSAGING_ERROR",t.statusText+"\n"),console.log(t.responseText)}}),console.log("sent data:",JSON.stringify(n))}function fe(e){return r(".upf").filter((function(){return r(this).text().toUpperCase()===e.toUpperCase()})).length>0&&(r("#splf").val(e).trigger("input"),!0)}function ce(e,t){const o=`cmd_opt_${e}`;let n=`${o}-error`,i=r(`#${n}`),s=r(`#${o}`);return i&&0!=i.length||(s.after(`
`),i=r(`#${n}`)),0==t.length?(i.hide(),s.removeClass("is-invalid"),s.addClass("is-valid"),i.text("")):(i.show(),i.text(t),s.removeClass("is-valid"),s.addClass("is-invalid")),i}function de(e){return e>=-55?{label:"****",icon:"signal_wifi_statusbar_4_bar"}:e>=-60?{label:"***",icon:"network_wifi_3_bar"}:e>=-65?{label:"**",icon:"network_wifi_2_bar"}:e>=-70?{label:"*",icon:"network_wifi_1_bar"}:{label:".",icon:"signal_wifi_statusbar_null"}}function ge(){(null==V?void 0:V.urc)!==v.ETH&&(r.ajaxSetup({timeout:3e3}),r.getJSON("/scan.json",(function(){return a(this,void 0,void 0,(function*(){var e;yield(e=2e3,new Promise((t=>setTimeout(t,e)))),r.getJSON("/ap.json",(function(e){e.length>0&&(e.sort((function(e,t){const o=e.rssi,r=t.rssi;return or?-1:0})),L=e,he(L))}))}))})))}function Ce(e,t,o){const r=de(t),n={label:0==o?"🔓":"🔒",icon:0==o?"no_encryption":"lock"};return`${e}\n ${G(r)}\n \t\n ${G(n)}\n `}function he(e){var t;let o="";if(r("#wifiTable tr td:first-of-type").text(""),r("#wifiTable tr").removeClass("table-success table-warning"),e&&(e.forEach((function(e){o+=Ce(e.ssid,e.rssi,e.auth)})),r("#wifiTable").html(o)),0==r(".manual_add").length&&(r("#wifiTable").append(Ce("Manual add",0,0)),r("#wifiTable tr:last").addClass("table-light text-dark").addClass("manual_add")),!V.ssid||V.urc!==v.OK&&V.urc!==v.RESTORE)(null==V?void 0:V.urc)!==v.ETH&&r("span#foot-if").html("");else{const e=`#wifiTable td:contains("${V.ssid}")`;0==r(e).filter((function(){return r(this).text()===V.ssid})).length&&r("#wifiTable").prepend(`${Ce(V.ssid,null!==(t=V.rssi)&&void 0!==t?t:0,0)}`),r(e).filter((function(){return r(this).text()===V.ssid})).siblings().first().html("✓").parent().addClass(V.urc===v.OK?"table-success":"table-warning"),r("span#foot-if").html(`SSID: ${V.ssid}, IP: ${V.ip}`);const o=de(V.rssi),n=G(o);r("#wifiStsIcon").text(n),r("#wifiStsIcon").attr("aria-label",o.label),r("#wifiStsIcon").attr("icon",o.icon)}}function ye(e){console.debug(`${this.toLocaleString()}\t${e.nme}\t${e.cpu}\t${b[e.st]}\t${e.minstk}\t${e.bprio}\t${e.cprio}\t${e.num}`),r("tbody#tasks").append(`${e.num}${e.nme}${e.cpu}${b[e.st]}${e.minstk}${e.bprio}${e.cprio}`)}function Me(e){return r(`${re} option:contains('${e}')`)}function me(){r.ajaxSetup({timeout:P}),r.getJSON("/messages.json",(function(e){return a(this,void 0,void 0,(function*(){for(const l of e){const e=l.current_time-l.sent_time;var t=new Date;switch(t.setTime(t.getTime()-e),l.class){case"MESSAGING_CLASS_OTA":O.EventOTAMessageClass(l.message);break;case"MESSAGING_CLASS_STATS":var o=JSON.parse(l.message);if(console.debug(t.toLocalShort()+" - Number of running tasks: "+o.ntasks),console.debug(`${t.toLocalShort()}\tname\tcpu\tstate\tminstk\tbprio\tcprio\tnum`),o.tasks){o.tasks;"collapse"===r("#tasks_sect").css("visibility")&&r("#tasks_sect").css("visibility","visible"),r("tbody#tasks").html(""),o.taskList.sort((function(e,t){return t.cpu-e.cpu})).forEach(ye,t)}else"visible"===r("#tasks_sect").css("visibility")&&(r("tbody#tasks").empty(),r("#tasks_sect").css("visibility","collapse"));break;case"MESSAGING_CLASS_SYSTEM":Ie(l,t);break;case"MESSAGING_CLASS_CFGCMD":var n=l.message.split(/([^\n]*)\n(.*)/gs);R(n[1],l.type,n[2],!0);break;case"MESSAGING_CLASS_BT":if(r(re).is("input")){const e=r(re)[0];for(var i=e.attributes,s="",a=0;a `)}JSON.parse(l.message).forEach((function(e){Me(e.name).length>0||(r(re).append(``),Ie({type:l.type,message:`BT Audio device found: ${e.name} RSSI: ${e.rssi} `,class:"",sent_time:0,current_time:0},t)),Me(e.name).attr("data-bs-description",`${e.name} (${e.rssi}dB)`).attr("rssi",e.rssi).attr("value",e.name).text(`${e.name} [${e.rssi}dB]`).trigger("change")}));const e=Array.from(r(re).find("option"));e.sort((function(e,t){const o=parseInt(r(e).attr("rssi"),10),n=parseInt(r(t).attr("rssi"),10);return console.log(`${o} < ${n} ? `),n-o})),r(re).empty().append(e)}}setTimeout(me,P)}))})).fail((function(e,t,o){404==e.status?(r(".orec").hide(),N=!0):T(e,0,o),0==e.status&&0==e.readyState?setTimeout(me,2*P):N||setTimeout(me,P)}))}function Be(e){if(r("#WifiConnectDialog").is(":visible")){if(V.ip&&r("#ipAddress").text(V.ip),V.ssid&&r("#connectedToSSID").text(V.ssid),V.gw&&r("#gateway").text(V.gw),V.netmask&&r("#netmask").text(V.netmask),(void 0===Y.Action||Y.Action&&Y.Action==se.STS)&&(r("*[class*='connecting']").hide(),r(".connecting-status").show()),x.ap_ssid&&r("#apName").text(x.ap_ssid.value),x.ap_pwd&&r("#apPass").text(x.ap_pwd.value),!e)return;switch(e.urc){case v.OK:e.ssid&&e.ssid===Y.ssid&&(r("*[class*='connecting']").hide(),r(".connecting-success").show(),Y.Action=se.STS);break;case v.FAIL:Y.Action!=se.STS&&Y.ssid==e.ssid&&(r("*[class*='connecting']").hide(),r(".connecting-fail").show());break;case v.LOST:break;case v.RESTORE:Y.Action!=se.STS&&Y.ssid!=e.ssid&&(r("*[class*='connecting']").hide(),r(".connecting-fail").show());case v.DISC:}}}function Se(e){r(".material-icons").each((function(t,o){const r=o;r.textContent=r.getAttribute(e?"aria-label":"data-icon")||""}))}function ve(e){Se(!w()),!function(e){return e.urc!==V.urc||e.ssid!==V.ssid||e.gw!==V.gw||e.netmask!==V.netmask||e.ip!==V.ip||e.rssi!==V.rssi}(e)&&e.urc||(V=function(e){var t;return{urc:null!==(t=e.urc)&&void 0!==t?t:0,auth:void 0,pwd:void 0,dhcpname:void 0,Action:void 0,ip:e.ip,ssid:e.ssid,rssi:e.rssi,gw:e.gw,netmask:e.netmask}}(e),r(".if_eth").hide(),r(".if_wifi").hide(),e.urc&&V.urc==v.ETH?(r(".if_eth").show(),V.urc===v.ETH&&r("span#foot-if").html(`Network: Ethernet, IP: ${V.ip}`)):(r(".if_wifi").show(),he())),Be(e)}function be(){r.ajaxSetup({timeout:2e3}),r.getJSON("/status.json",(function(e){var t;if(function(e){var t;1===(null!==(t=e.recovery)&&void 0!==t?t:0)?(k=!0,r(".recovery_element").show(),r(".ota_element").hide(),r("#boot-button").html("Reboot"),r("#boot-form").attr("action","/reboot_ota.json")):(!k&&N&&(N=!1,setTimeout(me,P)),k=!1,r(".recovery_element").hide(),r(".ota_element").show(),r("#boot-button").html("Recovery"),r("#boot-form").attr("action","/recovery.json"))}(e),h(),ve(e),function(e){var t;let o={label:"",icon:""},n="";if(void 0!==e.bt_status&&void 0!==e.bt_sub_status){const r=null===(t=S[e.bt_status])||void 0===t?void 0:t.sub[e.bt_sub_status];r?(o=m[r],n=S[e.bt_status].desc):(o=m.bt_connected,n="Output status")}r("#o_type").attr("title",n),r("#o_bt").html(w()?o.label:o.icon)}(e),O.EventTargetStatus(e),e.depth&&(Q=e.depth,16==Q?r("#cmd_opt_R").show():r("#cmd_opt_R").hide()),e.project_name&&""!==e.project_name&&(Z=e.project_name),e.platform_name&&""!==e.platform_name&&(te=e.platform_name),""===ee&&(ee=Z),""===ee&&(ee="Squeezelite-ESP32"),e.version&&""!==e.version?(q=e.version,r("#navtitle").html(`${ee}${k?"
[recovery]":""}`),r("span#foot-fw").html(`fw: ${q}, mode: ${k?"Recovery":Z}`)):r("span#flash-status").html(""),e.Voltage){const t=function(e){for(const n of B)for(const i of n.ranges)if(t=e,o=i.f,r=i.t,(t-o)*(t-r)<=0)return{label:n.label,icon:n.icon};var t,o,r;return{label:"▪▪▪▪",icon:"battery_full"}}(e.Voltage);r("#battery").html(`${G(t)}`),r("#battery").attr("aria-label",t.label),r("#battery").attr("data-icon",t.icon),r("#battery").show()}else r("#battery").hide();if(""!=(null!==(t=e.message)&&void 0!==t?t:"")&&X!=e.message&&(X=e.message,Fe(e.message,"MESSAGING_INFO")),I=e.is_i2c_locked,I?r("flds-cfg-hw-preset").hide():r("flds-cfg-hw-preset").show(),r("button[onclick*='handleReboot']").removeClass("rebooting"),void 0===ne||e.lms_ip!=ie&&e.lms_ip&&e.lms_port){const t="http://"+e.lms_ip+":"+e.lms_port;ie=e.lms_ip,r.ajax({url:t+"/plugins/SqueezeESP32/firmware/-check.bin",type:"HEAD",dataType:"text",cache:!1,error:function(){ne=""},success:function(){ne=t}})}r("#o_jack").css({display:Number(e.Jack)?"inline":"none"}),setTimeout(be,2e3)})).fail((function(e,t,o){T(e,0,o),0==e.status&&0==e.readyState?setTimeout(be,2*P):setTimeout(be,P)}))}function Oe(e,t,o){return void 0!==e[t]?e[t][o]:""}function Fe(e,t){Ie({message:e,type:t,class:"",sent_time:0,current_time:0},new Date)}function Ie(e,t){let o="table-success";"MESSAGING_WARNING"===e.type?(o="table-warning","MESSAGING_INFO"===U&&(U="MESSAGING_WARNING")):"MESSAGING_ERROR"===e.type&&("MESSAGING_INFO"!==U&&"MESSAGING_WARNING"!==U||(U="MESSAGING_ERROR"),o="table-danger"),++$>0&&(r("#msgcnt").removeClass("badge-success"),r("#msgcnt").removeClass("badge-warning"),r("#msgcnt").removeClass("badge-danger"),r("#msgcnt").addClass({MESSAGING_INFO:"badge-success",MESSAGING_WARNING:"badge-warning",MESSAGING_ERROR:"badge-danger"}[U]),r("#msgcnt").text($)),r("#syslogTable").append(""+t.toLocalShort()+""+e.message.encodeHTML()+"")}r((function(){r(".material-icons").each((function(e,t){t.setAttribute("data-icon",t.textContent||"")})),Se(!0),h(),O.init(),r("#fw-url-input").on("input",(function(){const e=r(this).val().toString();e.length>8&&(e.startsWith("http://")||e.startsWith("https://"))?r("#start-flash").show():r("#start-flash").hide()})),r(".upSrch").on("input",(function(){const e=this,t=e.value;r("#rTable tr").removeClass(e.id+"_hide"),t.length>0&&r(`#rTable td:nth-child(${r(e).parent().index()+1})`).filter((function(){return!r(this).text().toUpperCase().includes(t.toUpperCase())})).parent().addClass(this.id+"_hide"),r('[class*="_hide"]').hide(),r("#rTable tr").not('[class*="_hide"]').show()})),setTimeout(ge,1500),r("#options input").on("input",(function(){const{opt:e,val:t}=C(this);if("c"===e||"e"===e){const o=t.toString().split(",").map((function(e){return e.trim()})).filter((function(e){return!j.codecs.includes(e)}));ce(e,o.length>0?`Invalid codec(s) ${o.join(", ")}`:"")}if("m"===e){ce(e,/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(t.toString())?"":"Invalid MAC address")}if("r"===e){ce(e,/^(\d+\.?\d*|\.\d+)-(\d+\.?\d*|\.\d+)$|^(\d+\.?\d*)$|^(\d+\.?\d*,)+\d+\.?\d*$/.test(t.toString())?"":`Invalid rate(s) ${t}. Acceptable format: |-|,,`)}})),r("#WifiConnectDialog")[0].addEventListener("shown.bs.modal",(function(e){r("*[class*='connecting']").hide(),(null==e?void 0:e.relatedTarget)&&(Y.Action=se.CONN,r(e.relatedTarget).children("td:eq(1)").text()==V.ssid?Y.Action=se.STS:r(e.relatedTarget).is(":last-child")?(Y.Action=se.MAN,Y.ssid="",r("#manual_ssid").val(Y.ssid)):(Y.ssid=r(e.relatedTarget).children("td:eq(1)").text(),r("#manual_ssid").val(Y.ssid))),Y.Action!==se.STS?(r(".connecting-init").show(),r("#manual_ssid").trigger("focus")):Be()})),r("#WifiConnectDialog")[0].addEventListener("hidden.bs.modal",(function(){r("#WifiConnectDialog input").val("")})),r("#uCnfrm")[0].addEventListener("shown.bs.modal",(function(){r("#selectedFWURL").text(r("#fw-url-input").val().toString())})),r("input#show-commands")[0].checked=1===J,r('a[href^="#tab-commands"]').hide(),r("#load-nvs").on("click",(function(){r("#nvsfilename").trigger("click")})),r("#nvsfilename").on("change",(function(){const e=this;if("function"!=typeof window.FileReader)throw"The file API isn't supported on this browser.";if(!e.files)throw"This browser does not support the `files` property of the file input.";if(!e.files[0])return;const t=e.files[0];let o=new FileReader;o.onload=function(e){let t;try{t=JSON.parse(e.target.result.toString())}catch(e){alert("Parsing failed!\r\n "+e)}r("input.nvs").each((function(e,o){r(this).parent().removeClass("bg-warning").removeClass("bg-success"),t[o.id]&&(t[o.id]!==o.value?(console.log("Changed "+o.id+" "+o.value+"==>"+t[o.id]),r(this).parent().addClass("bg-warning"),r(this).val(t[o.id])):r(this).parent().addClass("bg-success"))})),r("input.nvs").children(".bg-warning")&&alert("Highlighted values were changed. Press Commit to change on the device")},o.readAsText(t),e.value=null})),r("#clear-syslog").on("click",(function(){$=0,U="MESSAGING_INFO",r("#msgcnt").text(""),r("#syslogTable").html("")})),r("#ok-credits").on("click",(function(){r("#credits").slideUp("fast",(function(){})),r("#app").slideDown("fast",(function(){}))})),r("#acredits").on("click",(function(e){e.preventDefault(),r("#app").slideUp("fast",(function(){})),r("#credits").slideDown("fast",(function(){}))})),r("input#show-commands").on("click",(function(){const e=this;e.checked=!!e.checked,e.checked?(r('a[href^="#tab-commands"]').show(),J=1):(J=0,r('a[href^="#tab-commands"]').hide())})),r("#disable-squeezelite").on("click",(function(){if(this.checked){const e=r("#cmd_opt_s").val();r("#cmd_opt_s").data("originalValue",e),r("#cmd_opt_s").val("-disable")}else{const e=r("#cmd_opt_s").data("originalValue");r("#cmd_opt_s").val(e||"")}})),r("input#show-nvs").on("click",(function(){const e=this;e.checked=!!e.checked,u.default.set("show-nvs",e.checked?"Y":"N"),h()})),r("#btn_reboot_recovery").on("click",(function(){g("recovery")})),r("#btn_reboot").on("click",(function(){g("reboot")})),r("#btn_flash").on("click",(function(){d()})),r("#save-autoexec1").on("click",(function(){ue(!1)})),r("#commit-autoexec1").on("click",(function(){ue(!0)})),r("#btn_disconnect").on("click",(function(){V={auth:void 0,pwd:void 0,dhcpname:void 0,Action:void 0,ip:void 0,ssid:void 0,rssi:void 0,gw:void 0,netmask:void 0,urc:0},he(),r.ajax({url:"/connect.json",dataType:"text",method:"DELETE",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now()})})})),r("#btnJoin").on("click",(function(){Y.ssid=r("#manual_ssid").val().toString(),Y.pwd=r("#manual_pwd").val().toString(),Y.dhcpname=r("#dhcp-name2").val().toString(),r("*[class*='connecting']").hide(),r("#ssid-wait").text(Y.ssid),r(".connecting").show(),r.ajax({url:"/connect.json",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify({timestamp:Date.now(),ssid:Y.ssid,pwd:Y.pwd}),error:T})})),r("#reboot_nav").on("click",(function(){g("reboot")})),r("#reboot_ota_nav").on("click",(function(){g("reboot_ota")})),r("#save-as-nvs").on("click",(function(){const e=pe(!0),t=document.createElement("a");t.href=URL.createObjectURL(new Blob([JSON.stringify(e,null,2)],{type:"text/plain"})),t.setAttribute("download","nvs_config_"+K+"_"+Date.now()+"json"),document.body.appendChild(t),t.click(),document.body.removeChild(t)})),r("#save-nvs").on("click",(function(){D(pe(!1))})),r("#fwUpload").on("click",(function(){0===document.getElementById("flashfilename").files.length?alert("No file selected!"):(r("#fw-url-input").value=null,O.StartOTA())})),r("[name=output-tmpl]").on("click",(function(){W(this.id)})),r("#chkUpdates").on("click",(function(){r("#rTable").html(""),r.getJSON(_,(function(e){const t=[];e.forEach((function(e){const o=e.name.split("#")[3];t.includes(o)||t.push(o)}));let o="";t.forEach((function(e){o+='"})),r("#fwbranch").append(o),e.forEach((function(e){let t="";e.assets.forEach((function(e){e.name.match(/\.bin$/)&&(t=e.browser_download_url)}));const o=e.name.split("#"),n=o[0],i=o[2],s=o[3];var a=n.substr(n.lastIndexOf("-")+1);a="32"==a||"16"==a?a:"";let p=e.body;p=p.replace(/'/gi,'"'),p=p.replace(/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/,"$1"),p=p.replace(/- \(.+?\) /g,"- ").encodeHTML(),r("#rTable").append(`\n ${n}${new Date(e.created_at).toLocalShort()}\n ${i}${s}${a}`)})),r("#searchfw").css("display","inline"),fe(te)||fe(Z),r("#rTable tr.release").on("click",(function(){var e=this.getAttribute("fwurl");ne&&(e=e.replace(/.*\/download\//,ne+"/plugins/SqueezeESP32/firmware/")),r("#fw-url-input").val(e),r("#start-flash").show(),r("#rTable tr.release").removeClass("table-success table-warning"),r(this).addClass("table-success table-warning")}))})).fail((function(){alert("failed to fetch release history!")}))})),r("#fwcheck").on("click",(function(){r("#releaseTable").html(""),r("#fwbranch").empty(),r.getJSON(_,(function(e){let t=0;const o=[];let n;e.forEach((function(e){const t=e.name.split("#")[3];o.includes(t)||o.push(t)})),o.forEach((function(e){n+=``})),r("#fwbranch").append(n),e.forEach((function(e){let o="";e.assets.forEach((function(e){e.name.match(/\.bin$/)&&(o=e.browser_download_url)}));const n=e.name.split("#"),i=n[0],s=n[1],a=n[2],p=n[3];let l=e.body;l=l.replace(/'/gi,'"'),l=l.replace(/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/,"$1"),l=l.replace(/- \(.+?\) /g,"- ");const u=t++>6?" hide":"";r("#releaseTable").append(`${i}${new Date(e.created_at).toLocalShort()}${a}${s}${p}`)})),t>7&&(r("#releaseTable").append(""),r("#showallbutton").on("click",(function(){r("tr.hide").removeClass("hide"),r("tr#showall").addClass("hide")}))),r("#searchfw").css("display","inline")})).fail((function(){alert("failed to fetch release history!")}))})),r("#updateAP").on("click",(function(){ge(),console.log("refresh AP")})),r.ajaxSetup({timeout:7e3}),r.getJSON("/config.json",(function(e){r("#nvsTable tr").remove();const t=e.config?e.config:e;x=t,z="",Object.keys(t).sort().forEach((function(e){let o=t[e].value;"autoexec1"===e?function(e){const t=E(e);if(t.output.toUpperCase().startsWith("I2S")?W("i2s"):t.output.toUpperCase().startsWith("SPDIF")?W("spdif"):t.output.toUpperCase().startsWith("BT")&&(t.otherOptions.btname&&(z=t.otherOptions.btname),W("bt")),Object.keys(t.options).forEach((function(e){const o=t.options[e];r(`#cmd_opt_${e}`).hasOwnProperty("checked")?"boolean"==typeof o&&(r(`#cmd_opt_${e}`)[0].checked=o):r(`#cmd_opt_${e}`).val(o)})),t.options.hasOwnProperty("u")){const[e,o]=t.options.u.split(":");r(`#resample_${e}`).prop("checked",!0),o&&r("#resample_i").prop("checked",!0)}t.options.hasOwnProperty("s")&&("-disable"===t.options.s?r("#disable-squeezelite")[0].checked=!0:r("#disable-squeezelite")[0].checked=!1)}(o):"host_name"===e?(o=o.replaceAll('"',""),r("input#dhcp-name1").val(o),r("input#dhcp-name2").val(o),0==r("#cmd_opt_n").length&&r("#cmd_opt_n").val(o),document.title=o,K=o):"rel_api"===e?_=o:"enable_airplay"===e?r("#s_airplay").css({display:y(o)?"inline":"none"}):"enable_cspot"===e?r("#s_cspot").css({display:y(o)?"inline":"none"}):"preset_name"==e?oe=o:"board_model"==e&&(ee=o),r("tbody#nvsTable").append(`${e}`),r("input#"+e).val(t[e].value)})),z.length>0&&r("#cfg-audio-bt_source-sink_name").val(z),r("tbody#nvsTable").append(""),e.gpio?(r("#pins").show(),r("tbody#gpiotable tr").remove(),e.gpio.forEach((function(e){r("tbody#gpiotable").append(`${e.group}${e.name}${e.gpio}${e.fixed?"Fixed":"Configuration"}`)}))):r("#pins").hide()})).fail((function(e,t,o){T(e,0,o)})),r.ajaxSetup({timeout:7e3}),r.getJSON("/commands.json",(function(e){console.log(e),r(".orec").show(),e.commands.forEach((function(t){if(0===r("#flds-"+t.name).length){const o=t.name.split("-"),n="cfg"===o[0],i="#tab-"+o[0]+"-"+o[1];let s="";s+=`
${t.help.encodeHTML().replace(/\n/g,"
")}
`,t.argtable&&t.argtable.forEach((function(o){let r=o.datatype||"";const n=t.name+"-"+o.longopts,i=Oe(e.values,t.name,o.longopts);let a=`hasvalue=${o.hasvalue} `;a+='longopts="'+o.longopts+'" ',a+='shortopts="'+o.shortopts+'" ',a+="checkbox="+o.checkbox+" ",a+='cmdname="'+t.name+'" ',a+=`id="${n}" name="${n}" hasvalue="${o.hasvalue}" `;let p=o.mincount>0?"bg-success":"";"hidden"===o.glossary&&(a+=' style="visibility: hidden;"'),o.checkbox?s+=`
`:(s+=`
`,r.includes("|")?(p=r.startsWith("+")?" multiple ":"",r=r.replace("<","").replace("=","").replace(">",""),s+=`"):s+=``),s+=`${o.checkbox?"
":""}Previous value: ${o.checkbox?i?"Checked":"Unchecked":i||""}${o.checkbox?"":"
"}`})),s+=`
\n `,s+=n?`\n`:``,s+="
",n?r(i).append(s):r("#commands-list").append(s)}})),r(".sclk").off("click").on("click",(function(){window.runCommand(this,!1)})),r(".cclk").off("click").on("click",(function(){window.runCommand(this,!0)})),e.commands.forEach((function(t){r("[cmdname="+t.name+"]:input").val(""),r("[cmdname="+t.name+"]:checkbox").prop("checked",!1),t.argtable&&t.argtable.forEach((function(o){const n="#"+t.name+"-"+o.longopts;if(o.checkbox)r(n)[0].checked=Oe(e,t.name,o.longopts);else{let i=Oe(e,t.name,o.longopts);void 0!==i&&r(n).val(i.toString()).trigger("change"),0===r(n)[0].value.length&&(o.datatype||"").includes("|")&&(r(n)[0].value="--")}}))})),0!=r("#cfg-hw-preset-model_config").length&&(F||(F=!0,r("#cfg-hw-preset-model_config").html(""),r.getJSON("https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/",{_:(new Date).getTime()},(function(e){r.each(e,(function(e,t){r("#cfg-hw-preset-model_config").append(``),""!==oe&&oe==t.name&&r("#cfg-hw-preset-model_config").val(oe)})),""!==oe&&r("#prev_preset").show().val(oe)})).fail((function(e,t,o){const r=t+", "+o;console.log("Request Failed: "+r)}))))})).fail((function(e,t,o){404==e.status?r(".orec").hide():T(e,0,o),r("#commands-list").empty()})),me(),be()})),window.setURL=function(e){let t=e.dataset.url;r('[data-bs-url^="http"]').addClass("btn-success").removeClass("btn-danger"),r('[data-bs-url="'+t+'"]').addClass("btn-danger").removeClass("btn-success"),ne&&(t=t.replace(/.*\/download\//,ne+"/plugins/SqueezeESP32/firmware/")),r("#fwurl").val(t)},window.runCommand=function(e,t){let o=e.getAttribute("cmdname");R(o,"MESSAGING_INFO","Executing.",!1);const n=document.getElementById("flds-"+o),i=null==n?void 0:n.querySelectorAll("select,input");if("cfg-hw-preset"===o)return function(e,t){const o=JSON.parse(e[0].value),n=e[0].getAttribute("cmdname");console.log(`selected model: ${o.name}`);let i={timestamp:Date.now(),config:{model_config:{value:o.name,type:33}}};for(const[e,t]of Object.entries(o.config)){const o="string"==typeof t||t instanceof String?t:JSON.stringify(t);i.config[e]={value:o.toString(),type:M.NVS_TYPE_STR},R(n,"MESSAGING_INFO",`Setting ${e}=${o} `,!0)}R(n,"MESSAGING_INFO","Committing ",!0),r.ajax({url:"/config.json",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(i),error:function(e,t,o){T(e,0,o),R(n,"MESSAGING_ERROR",`Unexpected error ${""!==o?o:"with return status = "+e.status} `,!0)},success:function(e){R(n,"MESSAGING_INFO","Saving complete ",!0),console.log(e),t&&le(2500,n)}})}(i,t);if(o+=" ",n)for(const e of i){let t="",r="";const n="SELECT"===e.tagName,i="true"===e.getAttribute("hasvalue"),s=n&&"--"!==e.value||!n&&""!==e.value;if(!i||i&&s){const n=e.getAttribute("longopts"),s=e.getAttribute("shortopts");null!==n&&"undefined"!==n?r+="--"+n:null!==s&&"undefined"!==s&&(r="-"+s),i?(t=/\s/.test(e.value)?'"':"",o+=`${r} ${t}${e.value}${t} `):e.checked&&(o+=`${r} `)}}console.log(o);const s={timestamp:Date.now(),command:o};r.ajax({url:"/commands.json",dataType:"text",method:"POST",cache:!1,contentType:"application/json; charset=utf-8",data:JSON.stringify(s),error:function(e,t,o){var r=JSON.parse(this.data).command;404==e.status?R(r.substr(0,r.indexOf(" ")),"MESSAGING_ERROR",""+(k?"Limited recovery mode active. Unsupported action ":"Unexpected error while processing command"),!0):(T(e,0,o),R(r.substr(0,r.indexOf(" ")-1),"MESSAGING_ERROR",`Unexpected error ${""!==o?o:"with return status = "+e.status}`,!0))},success:function(o){r(".orec").show(),console.log(o),"Success"===JSON.parse(o).Result&&t&&le(2500,e.getAttribute("cmdname"))}})}},861:e=>{"use strict";e.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEXIycuswsKMjI4rqqZyc3RQlpQ6jIEmJifW2dq5ursppJ8Om4zC0NAFdGYmmpb///8Hg3O4x8cHkoEggX0jko5Ks6/P0dM5r6ocoZb3+PgiiYVevrp/y8bg4uOS09FtxMDs7+7M6um529qoysik2tiNn72gAAAAF3RSTlP94Fr/Wf39BP26/////////////////kibhL0AAAGjSURBVDjLbZMJkoMgEEWtmETEJWpkiSC45P5nnF4wk7HmW2jLfzYIdFYUxbXUYp5nIbTOUFoLAR2ivIKZFQXYuu6TahSHmdAlAqWub0/QNI1jSxrHacKeWw9EdtH1xHbbyiRgCJn67JqVAr9nO2fJnBDMoUuYEvsfmxnJBM66Zj8/iYmaAPKlOvRNJAC/fz8OefINEAngAbYPEMiHTJCCAZrACciVMpCCgDEBKwsAowymMO3IAP3Btqa5vYJx0ZlcOSUZaE/AWznvnTHOyfZ/wMUQvAIg/wb27QNEH94BgGj+APsZiF8AXAhQQEMwkIYYLW7xvsENoyUoF0I0ysf0F2O743kDQNXzXM8+j8Eb6byzDEz7gtpsO1PgrXG5Nd6btNTP+YXarKTny1uQ9JiAN6vbqT9au+BzMQjAWtlq6BiYttdjiVVVqfXxWFWFkk6Cz0DTdYOFPmpHAAK/YQCJoTppQJ8A3TAxVAAhR439Bg5tKe7NgSDEje3mDsf+ovuGCUbYZb/BwoHS6ykHMYfo/U6lx8Xb/+qo3U/x/lf+VP9c/j9c3zy20WEMxgAAAABJRU5ErkJggg=="}},o={};function r(e){var n=o[e];if(void 0!==n)return n.exports;var i=o[e]={id:e,loaded:!1,exports:{}};return t[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}r.m=t,e=[],r.O=(t,o,n,i)=>{if(!o){var s=1/0;for(u=0;u=i)&&Object.keys(r.O).every((e=>r.O[e](o[p])))?o.splice(p--,1):(a=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[o,n,i]},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={826:0};r.O.j=t=>0===e[t];var t=(t,o)=>{var n,i,[s,a,p]=o,l=0;if(s.some((t=>0!==e[t]))){for(n in a)r.o(a,n)&&(r.m[n]=a[n]);if(p)var u=p(r)}for(t&&t(o);lr(607)));n=r.O(n)})(); -//# sourceMappingURL=index.dd7cd3.bundle.js.map \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.gz b/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.gz deleted file mode 100644 index 9c8995503d4354051fb709fe49b43caa4a5f2f97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27809 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 E0OvkGr2qf` diff --git a/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.map b/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.map deleted file mode 100644 index 038307be..00000000 --- a/components/wifi-manager/webapp/dist/js/index.dd7cd3.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"./js/index.dd7cd3.bundle.js","mappings":"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","sources":["webpack://squeezelite-esp32/webpack/runtime/chunk loaded","webpack://squeezelite-esp32/./src/js/proto/configuration_pb.js","webpack://squeezelite-esp32/./src/js/proto/nanopb_pb.js","webpack://squeezelite-esp32/./src/index.ts","webpack://squeezelite-esp32/./src/js/custom.ts","webpack://squeezelite-esp32/webpack/bootstrap","webpack://squeezelite-esp32/webpack/runtime/define property getters","webpack://squeezelite-esp32/webpack/runtime/global","webpack://squeezelite-esp32/webpack/runtime/hasOwnProperty shorthand","webpack://squeezelite-esp32/webpack/runtime/make namespace object","webpack://squeezelite-esp32/webpack/runtime/node module decorator","webpack://squeezelite-esp32/webpack/runtime/jsonp chunk loading","webpack://squeezelite-esp32/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// source: configuration.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global = (function() {\n if (this) { return this; }\n if (typeof window !== 'undefined') { return window; }\n if (typeof global !== 'undefined') { return global; }\n if (typeof self !== 'undefined') { return self; }\n return Function('return this')();\n}.call(null));\n\nvar nanopb_pb = require('./nanopb_pb.js');\ngoog.object.extend(proto, nanopb_pb);\ngoog.exportSymbol('proto.Conf.Artwork', null, global);\ngoog.exportSymbol('proto.Conf.Battery', null, global);\ngoog.exportSymbol('proto.Conf.BatteryAttenEnum', null, global);\ngoog.exportSymbol('proto.Conf.BatteryChannelEnum', null, global);\ngoog.exportSymbol('proto.Conf.Button', null, global);\ngoog.exportSymbol('proto.Conf.ButtonAction', null, global);\ngoog.exportSymbol('proto.Conf.ButtonActions', null, global);\ngoog.exportSymbol('proto.Conf.Config', null, global);\ngoog.exportSymbol('proto.Conf.DACDev', null, global);\ngoog.exportSymbol('proto.Conf.DACModelEnum', null, global);\ngoog.exportSymbol('proto.Conf.Dev', null, global);\ngoog.exportSymbol('proto.Conf.DeviceTypeEnum', null, global);\ngoog.exportSymbol('proto.Conf.DispCommon', null, global);\ngoog.exportSymbol('proto.Conf.DispOffsets', null, global);\ngoog.exportSymbol('proto.Conf.DisplayDev', null, global);\ngoog.exportSymbol('proto.Conf.DisplayDev.DisptypeCase', null, global);\ngoog.exportSymbol('proto.Conf.DisplayDriverEnum', null, global);\ngoog.exportSymbol('proto.Conf.Eth', null, global);\ngoog.exportSymbol('proto.Conf.Eth.EthtypeCase', null, global);\ngoog.exportSymbol('proto.Conf.EthCommon', null, global);\ngoog.exportSymbol('proto.Conf.EthModelEnum', null, global);\ngoog.exportSymbol('proto.Conf.EthRMII', null, global);\ngoog.exportSymbol('proto.Conf.EthSPI', null, global);\ngoog.exportSymbol('proto.Conf.EthType', null, global);\ngoog.exportSymbol('proto.Conf.GPIO', null, global);\ngoog.exportSymbol('proto.Conf.GPIOExp', null, global);\ngoog.exportSymbol('proto.Conf.GPIOExpModelEnum', null, global);\ngoog.exportSymbol('proto.Conf.Gpios', null, global);\ngoog.exportSymbol('proto.Conf.HostEnum', null, global);\ngoog.exportSymbol('proto.Conf.I2CBus', null, global);\ngoog.exportSymbol('proto.Conf.I2CDisplay', null, global);\ngoog.exportSymbol('proto.Conf.I2CPortEnum', null, global);\ngoog.exportSymbol('proto.Conf.LEDStrip', null, global);\ngoog.exportSymbol('proto.Conf.MCKEnum', null, global);\ngoog.exportSymbol('proto.Conf.Metadata', null, global);\ngoog.exportSymbol('proto.Conf.PortEnum', null, global);\ngoog.exportSymbol('proto.Conf.Rotary', null, global);\ngoog.exportSymbol('proto.Conf.SPDIFDev', null, global);\ngoog.exportSymbol('proto.Conf.SPIBus', null, global);\ngoog.exportSymbol('proto.Conf.SPIDisplay', null, global);\ngoog.exportSymbol('proto.Conf.Services', null, global);\ngoog.exportSymbol('proto.Conf.SleepService', null, global);\ngoog.exportSymbol('proto.Conf.WS2812', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.GPIO = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.GPIO, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.GPIO.displayName = 'proto.Conf.GPIO';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.I2CBus = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.I2CBus, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.I2CBus.displayName = 'proto.Conf.I2CBus';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.DACDev = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.DACDev, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.DACDev.displayName = 'proto.Conf.DACDev';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.SPDIFDev = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.SPDIFDev, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.SPDIFDev.displayName = 'proto.Conf.SPDIFDev';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.DispOffsets = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.DispOffsets, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.DispOffsets.displayName = 'proto.Conf.DispOffsets';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.DispCommon = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.DispCommon, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.DispCommon.displayName = 'proto.Conf.DispCommon';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.I2CDisplay = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.I2CDisplay, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.I2CDisplay.displayName = 'proto.Conf.I2CDisplay';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.SPIDisplay = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.SPIDisplay, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.SPIDisplay.displayName = 'proto.Conf.SPIDisplay';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.SPIBus = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.SPIBus, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.SPIBus.displayName = 'proto.Conf.SPIBus';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.DisplayDev = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.Conf.DisplayDev.oneofGroups_);\n};\ngoog.inherits(proto.Conf.DisplayDev, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.DisplayDev.displayName = 'proto.Conf.DisplayDev';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.GPIOExp = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.GPIOExp, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.GPIOExp.displayName = 'proto.Conf.GPIOExp';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.WS2812 = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.WS2812, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.WS2812.displayName = 'proto.Conf.WS2812';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.LEDStrip = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.LEDStrip, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.LEDStrip.displayName = 'proto.Conf.LEDStrip';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Rotary = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Rotary, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Rotary.displayName = 'proto.Conf.Rotary';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.ButtonActions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.ButtonActions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.ButtonActions.displayName = 'proto.Conf.ButtonActions';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Button = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Button, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Button.displayName = 'proto.Conf.Button';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.EthCommon = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.EthCommon, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.EthCommon.displayName = 'proto.Conf.EthCommon';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.EthSPI = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.EthSPI, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.EthSPI.displayName = 'proto.Conf.EthSPI';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.EthRMII = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.EthRMII, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.EthRMII.displayName = 'proto.Conf.EthRMII';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Eth = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, proto.Conf.Eth.oneofGroups_);\n};\ngoog.inherits(proto.Conf.Eth, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Eth.displayName = 'proto.Conf.Eth';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Battery = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Battery, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Battery.displayName = 'proto.Conf.Battery';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Gpios = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Gpios, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Gpios.displayName = 'proto.Conf.Gpios';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Dev = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.Conf.Dev.repeatedFields_, null);\n};\ngoog.inherits(proto.Conf.Dev, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Dev.displayName = 'proto.Conf.Dev';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.SleepService = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.Conf.SleepService.repeatedFields_, null);\n};\ngoog.inherits(proto.Conf.SleepService, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.SleepService.displayName = 'proto.Conf.SleepService';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Artwork = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Artwork, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Artwork.displayName = 'proto.Conf.Artwork';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Metadata = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Metadata, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Metadata.displayName = 'proto.Conf.Metadata';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Services = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Services, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Services.displayName = 'proto.Conf.Services';\n}\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.Conf.Config = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, null, null);\n};\ngoog.inherits(proto.Conf.Config, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.Conf.Config.displayName = 'proto.Conf.Config';\n}\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.GPIO.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.GPIO.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.GPIO} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.GPIO.toObject = function(includeInstance, msg) {\n var f, obj = {\n pin: jspb.Message.getFieldWithDefault(msg, 1, 0),\n level: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.GPIO}\n */\nproto.Conf.GPIO.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.GPIO;\n return proto.Conf.GPIO.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.GPIO} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.GPIO}\n */\nproto.Conf.GPIO.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setPin(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setLevel(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.GPIO.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.GPIO.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.GPIO} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.GPIO.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPin();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 2));\n if (f != null) {\n writer.writeInt32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional int32 pin = 1;\n * @return {number}\n */\nproto.Conf.GPIO.prototype.getPin = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIO} returns this\n */\nproto.Conf.GPIO.prototype.setPin = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 level = 2;\n * @return {number}\n */\nproto.Conf.GPIO.prototype.getLevel = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIO} returns this\n */\nproto.Conf.GPIO.prototype.setLevel = function(value) {\n return jspb.Message.setField(this, 2, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.Conf.GPIO} returns this\n */\nproto.Conf.GPIO.prototype.clearLevel = function() {\n return jspb.Message.setField(this, 2, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.GPIO.prototype.hasLevel = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.I2CBus.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.I2CBus.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.I2CBus} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.I2CBus.toObject = function(includeInstance, msg) {\n var f, obj = {\n port: jspb.Message.getFieldWithDefault(msg, 1, 0),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n sda: (f = msg.getSda()) && proto.Conf.GPIO.toObject(includeInstance, f),\n scl: (f = msg.getScl()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.I2CBus}\n */\nproto.Conf.I2CBus.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.I2CBus;\n return proto.Conf.I2CBus.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.I2CBus} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.I2CBus}\n */\nproto.Conf.I2CBus.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.I2CPortEnum} */ (reader.readEnum());\n msg.setPort(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setSda(value);\n break;\n case 4:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setScl(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.I2CBus.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.I2CBus.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.I2CBus} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.I2CBus.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPort();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getSda();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getScl();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional I2CPortEnum port = 1;\n * @return {!proto.Conf.I2CPortEnum}\n */\nproto.Conf.I2CBus.prototype.getPort = function() {\n return /** @type {!proto.Conf.I2CPortEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.I2CPortEnum} value\n * @return {!proto.Conf.I2CBus} returns this\n */\nproto.Conf.I2CBus.prototype.setPort = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional int32 speed = 2;\n * @return {number}\n */\nproto.Conf.I2CBus.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.I2CBus} returns this\n */\nproto.Conf.I2CBus.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO sda = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.I2CBus.prototype.getSda = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.I2CBus} returns this\n*/\nproto.Conf.I2CBus.prototype.setSda = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.I2CBus} returns this\n */\nproto.Conf.I2CBus.prototype.clearSda = function() {\n return this.setSda(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.I2CBus.prototype.hasSda = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO scl = 4;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.I2CBus.prototype.getScl = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.I2CBus} returns this\n*/\nproto.Conf.I2CBus.prototype.setScl = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.I2CBus} returns this\n */\nproto.Conf.I2CBus.prototype.clearScl = function() {\n return this.setScl(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.I2CBus.prototype.hasScl = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.DACDev.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.DACDev.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.DACDev} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DACDev.toObject = function(includeInstance, msg) {\n var f, obj = {\n bck: (f = msg.getBck()) && proto.Conf.GPIO.toObject(includeInstance, f),\n ws: (f = msg.getWs()) && proto.Conf.GPIO.toObject(includeInstance, f),\n dout: (f = msg.getDout()) && proto.Conf.GPIO.toObject(includeInstance, f),\n mck: jspb.Message.getFieldWithDefault(msg, 4, 0),\n mute: (f = msg.getMute()) && proto.Conf.GPIO.toObject(includeInstance, f),\n model: jspb.Message.getFieldWithDefault(msg, 6, 0),\n i2c: (f = msg.getI2c()) && proto.Conf.I2CBus.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.DACDev}\n */\nproto.Conf.DACDev.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.DACDev;\n return proto.Conf.DACDev.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.DACDev} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.DACDev}\n */\nproto.Conf.DACDev.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setBck(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setWs(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setDout(value);\n break;\n case 4:\n var value = /** @type {!proto.Conf.MCKEnum} */ (reader.readEnum());\n msg.setMck(value);\n break;\n case 5:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setMute(value);\n break;\n case 6:\n var value = /** @type {!proto.Conf.DACModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 7:\n var value = new proto.Conf.I2CBus;\n reader.readMessage(value,proto.Conf.I2CBus.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.DACDev.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.DACDev.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.DACDev} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DACDev.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getBck();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getWs();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getDout();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMck();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n f = message.getMute();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 6,\n f\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.I2CBus.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO bck = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DACDev.prototype.getBck = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DACDev} returns this\n*/\nproto.Conf.DACDev.prototype.setBck = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.clearBck = function() {\n return this.setBck(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DACDev.prototype.hasBck = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO ws = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DACDev.prototype.getWs = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DACDev} returns this\n*/\nproto.Conf.DACDev.prototype.setWs = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.clearWs = function() {\n return this.setWs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DACDev.prototype.hasWs = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO dout = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DACDev.prototype.getDout = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DACDev} returns this\n*/\nproto.Conf.DACDev.prototype.setDout = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.clearDout = function() {\n return this.setDout(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DACDev.prototype.hasDout = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional MCKEnum mck = 4;\n * @return {!proto.Conf.MCKEnum}\n */\nproto.Conf.DACDev.prototype.getMck = function() {\n return /** @type {!proto.Conf.MCKEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.Conf.MCKEnum} value\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.setMck = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n/**\n * optional GPIO mute = 5;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DACDev.prototype.getMute = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 5));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DACDev} returns this\n*/\nproto.Conf.DACDev.prototype.setMute = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.clearMute = function() {\n return this.setMute(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DACDev.prototype.hasMute = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional DACModelEnum model = 6;\n * @return {!proto.Conf.DACModelEnum}\n */\nproto.Conf.DACDev.prototype.getModel = function() {\n return /** @type {!proto.Conf.DACModelEnum} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {!proto.Conf.DACModelEnum} value\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 6, value);\n};\n\n\n/**\n * optional I2CBus i2c = 7;\n * @return {?proto.Conf.I2CBus}\n */\nproto.Conf.DACDev.prototype.getI2c = function() {\n return /** @type{?proto.Conf.I2CBus} */ (\n jspb.Message.getWrapperField(this, proto.Conf.I2CBus, 7));\n};\n\n\n/**\n * @param {?proto.Conf.I2CBus|undefined} value\n * @return {!proto.Conf.DACDev} returns this\n*/\nproto.Conf.DACDev.prototype.setI2c = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DACDev} returns this\n */\nproto.Conf.DACDev.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DACDev.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.SPDIFDev.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.SPDIFDev.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.SPDIFDev} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPDIFDev.toObject = function(includeInstance, msg) {\n var f, obj = {\n dc: (f = msg.getDc()) && proto.Conf.GPIO.toObject(includeInstance, f),\n data: (f = msg.getData()) && proto.Conf.GPIO.toObject(includeInstance, f),\n clk: (f = msg.getClk()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.SPDIFDev}\n */\nproto.Conf.SPDIFDev.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.SPDIFDev;\n return proto.Conf.SPDIFDev.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.SPDIFDev} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.SPDIFDev}\n */\nproto.Conf.SPDIFDev.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setDc(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setData(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setClk(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.SPDIFDev.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.SPDIFDev.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.SPDIFDev} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPDIFDev.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDc();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getData();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getClk();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO dc = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPDIFDev.prototype.getDc = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPDIFDev} returns this\n*/\nproto.Conf.SPDIFDev.prototype.setDc = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPDIFDev} returns this\n */\nproto.Conf.SPDIFDev.prototype.clearDc = function() {\n return this.setDc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPDIFDev.prototype.hasDc = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO data = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPDIFDev.prototype.getData = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPDIFDev} returns this\n*/\nproto.Conf.SPDIFDev.prototype.setData = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPDIFDev} returns this\n */\nproto.Conf.SPDIFDev.prototype.clearData = function() {\n return this.setData(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPDIFDev.prototype.hasData = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO clk = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPDIFDev.prototype.getClk = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPDIFDev} returns this\n*/\nproto.Conf.SPDIFDev.prototype.setClk = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPDIFDev} returns this\n */\nproto.Conf.SPDIFDev.prototype.clearClk = function() {\n return this.setClk(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPDIFDev.prototype.hasClk = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.DispOffsets.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.DispOffsets.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.DispOffsets} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DispOffsets.toObject = function(includeInstance, msg) {\n var f, obj = {\n height: jspb.Message.getFieldWithDefault(msg, 1, 0),\n width: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.DispOffsets}\n */\nproto.Conf.DispOffsets.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.DispOffsets;\n return proto.Conf.DispOffsets.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.DispOffsets} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.DispOffsets}\n */\nproto.Conf.DispOffsets.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHeight(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setWidth(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.DispOffsets.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.DispOffsets.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.DispOffsets} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DispOffsets.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getHeight();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getWidth();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional int32 height = 1;\n * @return {number}\n */\nproto.Conf.DispOffsets.prototype.getHeight = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.DispOffsets} returns this\n */\nproto.Conf.DispOffsets.prototype.setHeight = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 width = 2;\n * @return {number}\n */\nproto.Conf.DispOffsets.prototype.getWidth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.DispOffsets} returns this\n */\nproto.Conf.DispOffsets.prototype.setWidth = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.DispCommon.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.DispCommon.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.DispCommon} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DispCommon.toObject = function(includeInstance, msg) {\n var f, obj = {\n width: jspb.Message.getFieldWithDefault(msg, 1, 0),\n height: jspb.Message.getFieldWithDefault(msg, 2, 0),\n hflip: jspb.Message.getBooleanFieldWithDefault(msg, 3, false),\n vflip: jspb.Message.getBooleanFieldWithDefault(msg, 4, false),\n driver: jspb.Message.getFieldWithDefault(msg, 5, 0),\n bitdepth: jspb.Message.getFieldWithDefault(msg, 6, 0),\n back: (f = msg.getBack()) && proto.Conf.GPIO.toObject(includeInstance, f),\n reset: (f = msg.getReset()) && proto.Conf.GPIO.toObject(includeInstance, f),\n ready: (f = msg.getReady()) && proto.Conf.GPIO.toObject(includeInstance, f),\n offsets: (f = msg.getOffsets()) && proto.Conf.DispOffsets.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.DispCommon}\n */\nproto.Conf.DispCommon.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.DispCommon;\n return proto.Conf.DispCommon.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.DispCommon} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.DispCommon}\n */\nproto.Conf.DispCommon.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setWidth(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHeight(value);\n break;\n case 3:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setHflip(value);\n break;\n case 4:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setVflip(value);\n break;\n case 5:\n var value = /** @type {!proto.Conf.DisplayDriverEnum} */ (reader.readEnum());\n msg.setDriver(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setBitdepth(value);\n break;\n case 7:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setBack(value);\n break;\n case 8:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setReset(value);\n break;\n case 9:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setReady(value);\n break;\n case 10:\n var value = new proto.Conf.DispOffsets;\n reader.readMessage(value,proto.Conf.DispOffsets.deserializeBinaryFromReader);\n msg.setOffsets(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.DispCommon.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.DispCommon.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.DispCommon} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DispCommon.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getWidth();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getHeight();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getHflip();\n if (f) {\n writer.writeBool(\n 3,\n f\n );\n }\n f = message.getVflip();\n if (f) {\n writer.writeBool(\n 4,\n f\n );\n }\n f = message.getDriver();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n f = message.getBitdepth();\n if (f !== 0) {\n writer.writeInt32(\n 6,\n f\n );\n }\n f = message.getBack();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getReset();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getReady();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getOffsets();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n proto.Conf.DispOffsets.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional int32 width = 1;\n * @return {number}\n */\nproto.Conf.DispCommon.prototype.getWidth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setWidth = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 height = 2;\n * @return {number}\n */\nproto.Conf.DispCommon.prototype.getHeight = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setHeight = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional bool HFlip = 3;\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.getHflip = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setHflip = function(value) {\n return jspb.Message.setProto3BooleanField(this, 3, value);\n};\n\n\n/**\n * optional bool VFlip = 4;\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.getVflip = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setVflip = function(value) {\n return jspb.Message.setProto3BooleanField(this, 4, value);\n};\n\n\n/**\n * optional DisplayDriverEnum driver = 5;\n * @return {!proto.Conf.DisplayDriverEnum}\n */\nproto.Conf.DispCommon.prototype.getDriver = function() {\n return /** @type {!proto.Conf.DisplayDriverEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.Conf.DisplayDriverEnum} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setDriver = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n/**\n * optional int32 bitDepth = 6;\n * @return {number}\n */\nproto.Conf.DispCommon.prototype.getBitdepth = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.setBitdepth = function(value) {\n return jspb.Message.setProto3IntField(this, 6, value);\n};\n\n\n/**\n * optional GPIO back = 7;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DispCommon.prototype.getBack = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DispCommon} returns this\n*/\nproto.Conf.DispCommon.prototype.setBack = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.clearBack = function() {\n return this.setBack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.hasBack = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional GPIO reset = 8;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DispCommon.prototype.getReset = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 8));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DispCommon} returns this\n*/\nproto.Conf.DispCommon.prototype.setReset = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.clearReset = function() {\n return this.setReset(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.hasReset = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional GPIO ready = 9;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.DispCommon.prototype.getReady = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 9));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.DispCommon} returns this\n*/\nproto.Conf.DispCommon.prototype.setReady = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.clearReady = function() {\n return this.setReady(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.hasReady = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional DispOffsets offsets = 10;\n * @return {?proto.Conf.DispOffsets}\n */\nproto.Conf.DispCommon.prototype.getOffsets = function() {\n return /** @type{?proto.Conf.DispOffsets} */ (\n jspb.Message.getWrapperField(this, proto.Conf.DispOffsets, 10));\n};\n\n\n/**\n * @param {?proto.Conf.DispOffsets|undefined} value\n * @return {!proto.Conf.DispCommon} returns this\n*/\nproto.Conf.DispCommon.prototype.setOffsets = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DispCommon} returns this\n */\nproto.Conf.DispCommon.prototype.clearOffsets = function() {\n return this.setOffsets(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DispCommon.prototype.hasOffsets = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.I2CDisplay.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.I2CDisplay.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.I2CDisplay} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.I2CDisplay.toObject = function(includeInstance, msg) {\n var f, obj = {\n address: jspb.Message.getFieldWithDefault(msg, 1, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.I2CDisplay}\n */\nproto.Conf.I2CDisplay.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.I2CDisplay;\n return proto.Conf.I2CDisplay.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.I2CDisplay} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.I2CDisplay}\n */\nproto.Conf.I2CDisplay.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setAddress(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.I2CDisplay.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.I2CDisplay.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.I2CDisplay} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.I2CDisplay.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getAddress();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n};\n\n\n/**\n * optional int32 address = 1;\n * @return {number}\n */\nproto.Conf.I2CDisplay.prototype.getAddress = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.I2CDisplay} returns this\n */\nproto.Conf.I2CDisplay.prototype.setAddress = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.SPIDisplay.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.SPIDisplay.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.SPIDisplay} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPIDisplay.toObject = function(includeInstance, msg) {\n var f, obj = {\n cs: (f = msg.getCs()) && proto.Conf.GPIO.toObject(includeInstance, f),\n speed: jspb.Message.getFieldWithDefault(msg, 4, 0),\n rotate: jspb.Message.getBooleanFieldWithDefault(msg, 5, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.SPIDisplay}\n */\nproto.Conf.SPIDisplay.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.SPIDisplay;\n return proto.Conf.SPIDisplay.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.SPIDisplay} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.SPIDisplay}\n */\nproto.Conf.SPIDisplay.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setRotate(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.SPIDisplay.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.SPIDisplay.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.SPIDisplay} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPIDisplay.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n f = message.getRotate();\n if (f) {\n writer.writeBool(\n 5,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO cs = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPIDisplay.prototype.getCs = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPIDisplay} returns this\n*/\nproto.Conf.SPIDisplay.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPIDisplay} returns this\n */\nproto.Conf.SPIDisplay.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPIDisplay.prototype.hasCs = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 speed = 4;\n * @return {number}\n */\nproto.Conf.SPIDisplay.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.SPIDisplay} returns this\n */\nproto.Conf.SPIDisplay.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n/**\n * optional bool rotate = 5;\n * @return {boolean}\n */\nproto.Conf.SPIDisplay.prototype.getRotate = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.SPIDisplay} returns this\n */\nproto.Conf.SPIDisplay.prototype.setRotate = function(value) {\n return jspb.Message.setProto3BooleanField(this, 5, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.SPIBus.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.SPIBus.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.SPIBus} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPIBus.toObject = function(includeInstance, msg) {\n var f, obj = {\n mosi: (f = msg.getMosi()) && proto.Conf.GPIO.toObject(includeInstance, f),\n miso: (f = msg.getMiso()) && proto.Conf.GPIO.toObject(includeInstance, f),\n clk: (f = msg.getClk()) && proto.Conf.GPIO.toObject(includeInstance, f),\n dc: (f = msg.getDc()) && proto.Conf.GPIO.toObject(includeInstance, f),\n host: jspb.Message.getFieldWithDefault(msg, 5, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.SPIBus}\n */\nproto.Conf.SPIBus.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.SPIBus;\n return proto.Conf.SPIBus.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.SPIBus} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.SPIBus}\n */\nproto.Conf.SPIBus.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setMosi(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setMiso(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setClk(value);\n break;\n case 4:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setDc(value);\n break;\n case 5:\n var value = /** @type {!proto.Conf.HostEnum} */ (reader.readEnum());\n msg.setHost(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.SPIBus.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.SPIBus.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.SPIBus} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SPIBus.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMosi();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMiso();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getClk();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getDc();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getHost();\n if (f !== 0.0) {\n writer.writeEnum(\n 5,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO mosi = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPIBus.prototype.getMosi = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPIBus} returns this\n*/\nproto.Conf.SPIBus.prototype.setMosi = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPIBus} returns this\n */\nproto.Conf.SPIBus.prototype.clearMosi = function() {\n return this.setMosi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPIBus.prototype.hasMosi = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO miso = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPIBus.prototype.getMiso = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPIBus} returns this\n*/\nproto.Conf.SPIBus.prototype.setMiso = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPIBus} returns this\n */\nproto.Conf.SPIBus.prototype.clearMiso = function() {\n return this.setMiso(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPIBus.prototype.hasMiso = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO clk = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPIBus.prototype.getClk = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPIBus} returns this\n*/\nproto.Conf.SPIBus.prototype.setClk = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPIBus} returns this\n */\nproto.Conf.SPIBus.prototype.clearClk = function() {\n return this.setClk(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPIBus.prototype.hasClk = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO dc = 4;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SPIBus.prototype.getDc = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SPIBus} returns this\n*/\nproto.Conf.SPIBus.prototype.setDc = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SPIBus} returns this\n */\nproto.Conf.SPIBus.prototype.clearDc = function() {\n return this.setDc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SPIBus.prototype.hasDc = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional HostEnum host = 5;\n * @return {!proto.Conf.HostEnum}\n */\nproto.Conf.SPIBus.prototype.getHost = function() {\n return /** @type {!proto.Conf.HostEnum} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {!proto.Conf.HostEnum} value\n * @return {!proto.Conf.SPIBus} returns this\n */\nproto.Conf.SPIBus.prototype.setHost = function(value) {\n return jspb.Message.setProto3EnumField(this, 5, value);\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.Conf.DisplayDev.oneofGroups_ = [[3,4]];\n\n/**\n * @enum {number}\n */\nproto.Conf.DisplayDev.DisptypeCase = {\n DISPTYPE_NOT_SET: 0,\n I2C: 3,\n SPI: 4\n};\n\n/**\n * @return {proto.Conf.DisplayDev.DisptypeCase}\n */\nproto.Conf.DisplayDev.prototype.getDisptypeCase = function() {\n return /** @type {proto.Conf.DisplayDev.DisptypeCase} */(jspb.Message.computeOneofCase(this, proto.Conf.DisplayDev.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.DisplayDev.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.DisplayDev.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.DisplayDev} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DisplayDev.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n common: (f = msg.getCommon()) && proto.Conf.DispCommon.toObject(includeInstance, f),\n i2c: (f = msg.getI2c()) && proto.Conf.I2CDisplay.toObject(includeInstance, f),\n spi: (f = msg.getSpi()) && proto.Conf.SPIDisplay.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.DisplayDev}\n */\nproto.Conf.DisplayDev.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.DisplayDev;\n return proto.Conf.DisplayDev.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.DisplayDev} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.DisplayDev}\n */\nproto.Conf.DisplayDev.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.DeviceTypeEnum} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new proto.Conf.DispCommon;\n reader.readMessage(value,proto.Conf.DispCommon.deserializeBinaryFromReader);\n msg.setCommon(value);\n break;\n case 3:\n var value = new proto.Conf.I2CDisplay;\n reader.readMessage(value,proto.Conf.I2CDisplay.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 4:\n var value = new proto.Conf.SPIDisplay;\n reader.readMessage(value,proto.Conf.SPIDisplay.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.DisplayDev.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.DisplayDev.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.DisplayDev} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.DisplayDev.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getCommon();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.DispCommon.serializeBinaryToWriter\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.I2CDisplay.serializeBinaryToWriter\n );\n }\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.SPIDisplay.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional DeviceTypeEnum type = 1;\n * @return {!proto.Conf.DeviceTypeEnum}\n */\nproto.Conf.DisplayDev.prototype.getType = function() {\n return /** @type {!proto.Conf.DeviceTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.DeviceTypeEnum} value\n * @return {!proto.Conf.DisplayDev} returns this\n */\nproto.Conf.DisplayDev.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional DispCommon common = 2;\n * @return {?proto.Conf.DispCommon}\n */\nproto.Conf.DisplayDev.prototype.getCommon = function() {\n return /** @type{?proto.Conf.DispCommon} */ (\n jspb.Message.getWrapperField(this, proto.Conf.DispCommon, 2));\n};\n\n\n/**\n * @param {?proto.Conf.DispCommon|undefined} value\n * @return {!proto.Conf.DisplayDev} returns this\n*/\nproto.Conf.DisplayDev.prototype.setCommon = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DisplayDev} returns this\n */\nproto.Conf.DisplayDev.prototype.clearCommon = function() {\n return this.setCommon(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DisplayDev.prototype.hasCommon = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional I2CDisplay i2c = 3;\n * @return {?proto.Conf.I2CDisplay}\n */\nproto.Conf.DisplayDev.prototype.getI2c = function() {\n return /** @type{?proto.Conf.I2CDisplay} */ (\n jspb.Message.getWrapperField(this, proto.Conf.I2CDisplay, 3));\n};\n\n\n/**\n * @param {?proto.Conf.I2CDisplay|undefined} value\n * @return {!proto.Conf.DisplayDev} returns this\n*/\nproto.Conf.DisplayDev.prototype.setI2c = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.Conf.DisplayDev.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DisplayDev} returns this\n */\nproto.Conf.DisplayDev.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DisplayDev.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional SPIDisplay spi = 4;\n * @return {?proto.Conf.SPIDisplay}\n */\nproto.Conf.DisplayDev.prototype.getSpi = function() {\n return /** @type{?proto.Conf.SPIDisplay} */ (\n jspb.Message.getWrapperField(this, proto.Conf.SPIDisplay, 4));\n};\n\n\n/**\n * @param {?proto.Conf.SPIDisplay|undefined} value\n * @return {!proto.Conf.DisplayDev} returns this\n*/\nproto.Conf.DisplayDev.prototype.setSpi = function(value) {\n return jspb.Message.setOneofWrapperField(this, 4, proto.Conf.DisplayDev.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.DisplayDev} returns this\n */\nproto.Conf.DisplayDev.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.DisplayDev.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.GPIOExp.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.GPIOExp.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.GPIOExp} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.GPIOExp.toObject = function(includeInstance, msg) {\n var f, obj = {\n model: jspb.Message.getFieldWithDefault(msg, 1, 0),\n addr: jspb.Message.getFieldWithDefault(msg, 2, 0),\n port: jspb.Message.getFieldWithDefault(msg, 3, 0),\n base: jspb.Message.getFieldWithDefault(msg, 4, 0),\n count: jspb.Message.getFieldWithDefault(msg, 5, 0),\n intr: (f = msg.getIntr()) && proto.Conf.GPIO.toObject(includeInstance, f),\n cs: (f = msg.getCs()) && proto.Conf.GPIO.toObject(includeInstance, f),\n speed: jspb.Message.getFieldWithDefault(msg, 8, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.GPIOExp}\n */\nproto.Conf.GPIOExp.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.GPIOExp;\n return proto.Conf.GPIOExp.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.GPIOExp} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.GPIOExp}\n */\nproto.Conf.GPIOExp.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.GPIOExpModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setAddr(value);\n break;\n case 3:\n var value = /** @type {!proto.Conf.PortEnum} */ (reader.readEnum());\n msg.setPort(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setBase(value);\n break;\n case 5:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setCount(value);\n break;\n case 6:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setIntr(value);\n break;\n case 7:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n case 8:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.GPIOExp.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.GPIOExp.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.GPIOExp} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.GPIOExp.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getAddr();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getPort();\n if (f !== 0.0) {\n writer.writeEnum(\n 3,\n f\n );\n }\n f = message.getBase();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n f = message.getCount();\n if (f !== 0) {\n writer.writeInt32(\n 5,\n f\n );\n }\n f = message.getIntr();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 8,\n f\n );\n }\n};\n\n\n/**\n * optional GPIOExpModelEnum model = 1;\n * @return {!proto.Conf.GPIOExpModelEnum}\n */\nproto.Conf.GPIOExp.prototype.getModel = function() {\n return /** @type {!proto.Conf.GPIOExpModelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.GPIOExpModelEnum} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional int32 addr = 2;\n * @return {number}\n */\nproto.Conf.GPIOExp.prototype.getAddr = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setAddr = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional PortEnum port = 3;\n * @return {!proto.Conf.PortEnum}\n */\nproto.Conf.GPIOExp.prototype.getPort = function() {\n return /** @type {!proto.Conf.PortEnum} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.Conf.PortEnum} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setPort = function(value) {\n return jspb.Message.setProto3EnumField(this, 3, value);\n};\n\n\n/**\n * optional int32 base = 4;\n * @return {number}\n */\nproto.Conf.GPIOExp.prototype.getBase = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setBase = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n/**\n * optional int32 count = 5;\n * @return {number}\n */\nproto.Conf.GPIOExp.prototype.getCount = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setCount = function(value) {\n return jspb.Message.setProto3IntField(this, 5, value);\n};\n\n\n/**\n * optional GPIO intr = 6;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.GPIOExp.prototype.getIntr = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 6));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.GPIOExp} returns this\n*/\nproto.Conf.GPIOExp.prototype.setIntr = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.clearIntr = function() {\n return this.setIntr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.GPIOExp.prototype.hasIntr = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional GPIO cs = 7;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.GPIOExp.prototype.getCs = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.GPIOExp} returns this\n*/\nproto.Conf.GPIOExp.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.GPIOExp.prototype.hasCs = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional int32 speed = 8;\n * @return {number}\n */\nproto.Conf.GPIOExp.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.GPIOExp} returns this\n */\nproto.Conf.GPIOExp.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 8, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.WS2812.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.WS2812.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.WS2812} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.WS2812.toObject = function(includeInstance, msg) {\n var f, obj = {\n length: jspb.Message.getFieldWithDefault(msg, 1, 0),\n gpio: (f = msg.getGpio()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.WS2812}\n */\nproto.Conf.WS2812.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.WS2812;\n return proto.Conf.WS2812.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.WS2812} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.WS2812}\n */\nproto.Conf.WS2812.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setLength(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.WS2812.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.WS2812.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.WS2812} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.WS2812.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getLength();\n if (f !== 0) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional int32 length = 1;\n * @return {number}\n */\nproto.Conf.WS2812.prototype.getLength = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.WS2812} returns this\n */\nproto.Conf.WS2812.prototype.setLength = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional GPIO gpio = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.WS2812.prototype.getGpio = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.WS2812} returns this\n*/\nproto.Conf.WS2812.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.WS2812} returns this\n */\nproto.Conf.WS2812.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.WS2812.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.LEDStrip.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.LEDStrip.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.LEDStrip} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.LEDStrip.toObject = function(includeInstance, msg) {\n var f, obj = {\n ws2812: (f = msg.getWs2812()) && proto.Conf.WS2812.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.LEDStrip}\n */\nproto.Conf.LEDStrip.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.LEDStrip;\n return proto.Conf.LEDStrip.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.LEDStrip} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.LEDStrip}\n */\nproto.Conf.LEDStrip.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.WS2812;\n reader.readMessage(value,proto.Conf.WS2812.deserializeBinaryFromReader);\n msg.setWs2812(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.LEDStrip.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.LEDStrip.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.LEDStrip} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.LEDStrip.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getWs2812();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.WS2812.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional WS2812 WS2812 = 1;\n * @return {?proto.Conf.WS2812}\n */\nproto.Conf.LEDStrip.prototype.getWs2812 = function() {\n return /** @type{?proto.Conf.WS2812} */ (\n jspb.Message.getWrapperField(this, proto.Conf.WS2812, 1));\n};\n\n\n/**\n * @param {?proto.Conf.WS2812|undefined} value\n * @return {!proto.Conf.LEDStrip} returns this\n*/\nproto.Conf.LEDStrip.prototype.setWs2812 = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.LEDStrip} returns this\n */\nproto.Conf.LEDStrip.prototype.clearWs2812 = function() {\n return this.setWs2812(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.LEDStrip.prototype.hasWs2812 = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Rotary.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Rotary.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Rotary} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Rotary.toObject = function(includeInstance, msg) {\n var f, obj = {\n a: (f = msg.getA()) && proto.Conf.GPIO.toObject(includeInstance, f),\n b: (f = msg.getB()) && proto.Conf.GPIO.toObject(includeInstance, f),\n sw: (f = msg.getSw()) && proto.Conf.GPIO.toObject(includeInstance, f),\n knobonly: jspb.Message.getFieldWithDefault(msg, 4, 0),\n volume: jspb.Message.getBooleanFieldWithDefault(msg, 5, false),\n longpress: jspb.Message.getBooleanFieldWithDefault(msg, 6, false)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Rotary}\n */\nproto.Conf.Rotary.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Rotary;\n return proto.Conf.Rotary.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Rotary} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Rotary}\n */\nproto.Conf.Rotary.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setA(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setB(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setSw(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setKnobonly(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setVolume(value);\n break;\n case 6:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setLongpress(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Rotary.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Rotary.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Rotary} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Rotary.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getA();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getB();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSw();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getKnobonly();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n f = message.getVolume();\n if (f) {\n writer.writeBool(\n 5,\n f\n );\n }\n f = message.getLongpress();\n if (f) {\n writer.writeBool(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO A = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Rotary.prototype.getA = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Rotary} returns this\n*/\nproto.Conf.Rotary.prototype.setA = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.clearA = function() {\n return this.setA(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Rotary.prototype.hasA = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO B = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Rotary.prototype.getB = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Rotary} returns this\n*/\nproto.Conf.Rotary.prototype.setB = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.clearB = function() {\n return this.setB(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Rotary.prototype.hasB = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO SW = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Rotary.prototype.getSw = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Rotary} returns this\n*/\nproto.Conf.Rotary.prototype.setSw = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.clearSw = function() {\n return this.setSw(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Rotary.prototype.hasSw = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional int32 knobonly = 4;\n * @return {number}\n */\nproto.Conf.Rotary.prototype.getKnobonly = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.setKnobonly = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n/**\n * optional bool volume = 5;\n * @return {boolean}\n */\nproto.Conf.Rotary.prototype.getVolume = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.setVolume = function(value) {\n return jspb.Message.setProto3BooleanField(this, 5, value);\n};\n\n\n/**\n * optional bool longpress = 6;\n * @return {boolean}\n */\nproto.Conf.Rotary.prototype.getLongpress = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.Rotary} returns this\n */\nproto.Conf.Rotary.prototype.setLongpress = function(value) {\n return jspb.Message.setProto3BooleanField(this, 6, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.ButtonActions.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.ButtonActions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.ButtonActions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.ButtonActions.toObject = function(includeInstance, msg) {\n var f, obj = {\n pressed: jspb.Message.getFieldWithDefault(msg, 1, 0),\n released: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.ButtonActions}\n */\nproto.Conf.ButtonActions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.ButtonActions;\n return proto.Conf.ButtonActions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.ButtonActions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.ButtonActions}\n */\nproto.Conf.ButtonActions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.ButtonAction} */ (reader.readEnum());\n msg.setPressed(value);\n break;\n case 2:\n var value = /** @type {!proto.Conf.ButtonAction} */ (reader.readEnum());\n msg.setReleased(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.ButtonActions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.ButtonActions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.ButtonActions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.ButtonActions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getPressed();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getReleased();\n if (f !== 0.0) {\n writer.writeEnum(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional ButtonAction pressed = 1;\n * @return {!proto.Conf.ButtonAction}\n */\nproto.Conf.ButtonActions.prototype.getPressed = function() {\n return /** @type {!proto.Conf.ButtonAction} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.ButtonAction} value\n * @return {!proto.Conf.ButtonActions} returns this\n */\nproto.Conf.ButtonActions.prototype.setPressed = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional ButtonAction released = 2;\n * @return {!proto.Conf.ButtonAction}\n */\nproto.Conf.ButtonActions.prototype.getReleased = function() {\n return /** @type {!proto.Conf.ButtonAction} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {!proto.Conf.ButtonAction} value\n * @return {!proto.Conf.ButtonActions} returns this\n */\nproto.Conf.ButtonActions.prototype.setReleased = function(value) {\n return jspb.Message.setProto3EnumField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Button.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Button.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Button} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Button.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpio: (f = msg.getGpio()) && proto.Conf.GPIO.toObject(includeInstance, f),\n pull: jspb.Message.getBooleanFieldWithDefault(msg, 2, false),\n debounce: jspb.Message.getFieldWithDefault(msg, 3, 0),\n shifter: (f = msg.getShifter()) && proto.Conf.GPIO.toObject(includeInstance, f),\n longduration: jspb.Message.getFieldWithDefault(msg, 5, 0),\n normal: (f = msg.getNormal()) && proto.Conf.ButtonActions.toObject(includeInstance, f),\n longpress: (f = msg.getLongpress()) && proto.Conf.ButtonActions.toObject(includeInstance, f),\n shifted: (f = msg.getShifted()) && proto.Conf.ButtonActions.toObject(includeInstance, f),\n longshifted: (f = msg.getLongshifted()) && proto.Conf.ButtonActions.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Button}\n */\nproto.Conf.Button.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Button;\n return proto.Conf.Button.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Button} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Button}\n */\nproto.Conf.Button.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setGpio(value);\n break;\n case 2:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPull(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setDebounce(value);\n break;\n case 4:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setShifter(value);\n break;\n case 5:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setLongduration(value);\n break;\n case 6:\n var value = new proto.Conf.ButtonActions;\n reader.readMessage(value,proto.Conf.ButtonActions.deserializeBinaryFromReader);\n msg.setNormal(value);\n break;\n case 7:\n var value = new proto.Conf.ButtonActions;\n reader.readMessage(value,proto.Conf.ButtonActions.deserializeBinaryFromReader);\n msg.setLongpress(value);\n break;\n case 8:\n var value = new proto.Conf.ButtonActions;\n reader.readMessage(value,proto.Conf.ButtonActions.deserializeBinaryFromReader);\n msg.setShifted(value);\n break;\n case 9:\n var value = new proto.Conf.ButtonActions;\n reader.readMessage(value,proto.Conf.ButtonActions.deserializeBinaryFromReader);\n msg.setLongshifted(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Button.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Button.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Button} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Button.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpio();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getPull();\n if (f) {\n writer.writeBool(\n 2,\n f\n );\n }\n f = message.getDebounce();\n if (f !== 0) {\n writer.writeInt32(\n 3,\n f\n );\n }\n f = message.getShifter();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getLongduration();\n if (f !== 0) {\n writer.writeInt32(\n 5,\n f\n );\n }\n f = message.getNormal();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.Conf.ButtonActions.serializeBinaryToWriter\n );\n }\n f = message.getLongpress();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.ButtonActions.serializeBinaryToWriter\n );\n }\n f = message.getShifted();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.Conf.ButtonActions.serializeBinaryToWriter\n );\n }\n f = message.getLongshifted();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n proto.Conf.ButtonActions.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO gpio = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Button.prototype.getGpio = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setGpio = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearGpio = function() {\n return this.setGpio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasGpio = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional bool pull = 2;\n * @return {boolean}\n */\nproto.Conf.Button.prototype.getPull = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.setPull = function(value) {\n return jspb.Message.setProto3BooleanField(this, 2, value);\n};\n\n\n/**\n * optional int32 debounce = 3;\n * @return {number}\n */\nproto.Conf.Button.prototype.getDebounce = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.setDebounce = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional GPIO shifter = 4;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Button.prototype.getShifter = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setShifter = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearShifter = function() {\n return this.setShifter(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasShifter = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional int32 longduration = 5;\n * @return {number}\n */\nproto.Conf.Button.prototype.getLongduration = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.setLongduration = function(value) {\n return jspb.Message.setProto3IntField(this, 5, value);\n};\n\n\n/**\n * optional ButtonActions normal = 6;\n * @return {?proto.Conf.ButtonActions}\n */\nproto.Conf.Button.prototype.getNormal = function() {\n return /** @type{?proto.Conf.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.Conf.ButtonActions, 6));\n};\n\n\n/**\n * @param {?proto.Conf.ButtonActions|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setNormal = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearNormal = function() {\n return this.setNormal(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasNormal = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional ButtonActions longpress = 7;\n * @return {?proto.Conf.ButtonActions}\n */\nproto.Conf.Button.prototype.getLongpress = function() {\n return /** @type{?proto.Conf.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.Conf.ButtonActions, 7));\n};\n\n\n/**\n * @param {?proto.Conf.ButtonActions|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setLongpress = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearLongpress = function() {\n return this.setLongpress(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasLongpress = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional ButtonActions shifted = 8;\n * @return {?proto.Conf.ButtonActions}\n */\nproto.Conf.Button.prototype.getShifted = function() {\n return /** @type{?proto.Conf.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.Conf.ButtonActions, 8));\n};\n\n\n/**\n * @param {?proto.Conf.ButtonActions|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setShifted = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearShifted = function() {\n return this.setShifted(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasShifted = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional ButtonActions longshifted = 9;\n * @return {?proto.Conf.ButtonActions}\n */\nproto.Conf.Button.prototype.getLongshifted = function() {\n return /** @type{?proto.Conf.ButtonActions} */ (\n jspb.Message.getWrapperField(this, proto.Conf.ButtonActions, 9));\n};\n\n\n/**\n * @param {?proto.Conf.ButtonActions|undefined} value\n * @return {!proto.Conf.Button} returns this\n*/\nproto.Conf.Button.prototype.setLongshifted = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Button} returns this\n */\nproto.Conf.Button.prototype.clearLongshifted = function() {\n return this.setLongshifted(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Button.prototype.hasLongshifted = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.EthCommon.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.EthCommon.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.EthCommon} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthCommon.toObject = function(includeInstance, msg) {\n var f, obj = {\n model: jspb.Message.getFieldWithDefault(msg, 1, 0),\n rst: (f = msg.getRst()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.EthCommon}\n */\nproto.Conf.EthCommon.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.EthCommon;\n return proto.Conf.EthCommon.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.EthCommon} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.EthCommon}\n */\nproto.Conf.EthCommon.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.EthModelEnum} */ (reader.readEnum());\n msg.setModel(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setRst(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.EthCommon.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.EthCommon.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.EthCommon} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthCommon.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getModel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getRst();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional EthModelEnum model = 1;\n * @return {!proto.Conf.EthModelEnum}\n */\nproto.Conf.EthCommon.prototype.getModel = function() {\n return /** @type {!proto.Conf.EthModelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.EthModelEnum} value\n * @return {!proto.Conf.EthCommon} returns this\n */\nproto.Conf.EthCommon.prototype.setModel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional GPIO rst = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.EthCommon.prototype.getRst = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.EthCommon} returns this\n*/\nproto.Conf.EthCommon.prototype.setRst = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.EthCommon} returns this\n */\nproto.Conf.EthCommon.prototype.clearRst = function() {\n return this.setRst(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.EthCommon.prototype.hasRst = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.EthSPI.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.EthSPI.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.EthSPI} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthSPI.toObject = function(includeInstance, msg) {\n var f, obj = {\n cs: (f = msg.getCs()) && proto.Conf.GPIO.toObject(includeInstance, f),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n intr: (f = msg.getIntr()) && proto.Conf.GPIO.toObject(includeInstance, f),\n host: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.EthSPI}\n */\nproto.Conf.EthSPI.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.EthSPI;\n return proto.Conf.EthSPI.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.EthSPI} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.EthSPI}\n */\nproto.Conf.EthSPI.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setCs(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setIntr(value);\n break;\n case 4:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setHost(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.EthSPI.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.EthSPI.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.EthSPI} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthSPI.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getCs();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getIntr();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getHost();\n if (f !== 0) {\n writer.writeInt32(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional GPIO cs = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.EthSPI.prototype.getCs = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.EthSPI} returns this\n*/\nproto.Conf.EthSPI.prototype.setCs = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.EthSPI} returns this\n */\nproto.Conf.EthSPI.prototype.clearCs = function() {\n return this.setCs(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.EthSPI.prototype.hasCs = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 speed = 2;\n * @return {number}\n */\nproto.Conf.EthSPI.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.EthSPI} returns this\n */\nproto.Conf.EthSPI.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO intr = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.EthSPI.prototype.getIntr = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.EthSPI} returns this\n*/\nproto.Conf.EthSPI.prototype.setIntr = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.EthSPI} returns this\n */\nproto.Conf.EthSPI.prototype.clearIntr = function() {\n return this.setIntr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.EthSPI.prototype.hasIntr = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional int32 host = 4;\n * @return {number}\n */\nproto.Conf.EthSPI.prototype.getHost = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.EthSPI} returns this\n */\nproto.Conf.EthSPI.prototype.setHost = function(value) {\n return jspb.Message.setProto3IntField(this, 4, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.EthRMII.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.EthRMII.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.EthRMII} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthRMII.toObject = function(includeInstance, msg) {\n var f, obj = {\n mdc: (f = msg.getMdc()) && proto.Conf.GPIO.toObject(includeInstance, f),\n mdio: (f = msg.getMdio()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.EthRMII}\n */\nproto.Conf.EthRMII.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.EthRMII;\n return proto.Conf.EthRMII.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.EthRMII} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.EthRMII}\n */\nproto.Conf.EthRMII.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setMdc(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setMdio(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.EthRMII.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.EthRMII.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.EthRMII} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.EthRMII.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMdc();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getMdio();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO mdc = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.EthRMII.prototype.getMdc = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.EthRMII} returns this\n*/\nproto.Conf.EthRMII.prototype.setMdc = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.EthRMII} returns this\n */\nproto.Conf.EthRMII.prototype.clearMdc = function() {\n return this.setMdc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.EthRMII.prototype.hasMdc = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO mdio = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.EthRMII.prototype.getMdio = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.EthRMII} returns this\n*/\nproto.Conf.EthRMII.prototype.setMdio = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.EthRMII} returns this\n */\nproto.Conf.EthRMII.prototype.clearMdio = function() {\n return this.setMdio(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.EthRMII.prototype.hasMdio = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n/**\n * Oneof group definitions for this message. Each group defines the field\n * numbers belonging to that group. When of these fields' value is set, all\n * other fields in the group are cleared. During deserialization, if multiple\n * fields are encountered for a group, only the last value seen will be kept.\n * @private {!Array>}\n * @const\n */\nproto.Conf.Eth.oneofGroups_ = [[3,4]];\n\n/**\n * @enum {number}\n */\nproto.Conf.Eth.EthtypeCase = {\n ETHTYPE_NOT_SET: 0,\n SPI: 3,\n RMII: 4\n};\n\n/**\n * @return {proto.Conf.Eth.EthtypeCase}\n */\nproto.Conf.Eth.prototype.getEthtypeCase = function() {\n return /** @type {proto.Conf.Eth.EthtypeCase} */(jspb.Message.computeOneofCase(this, proto.Conf.Eth.oneofGroups_[0]));\n};\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Eth.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Eth.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Eth} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Eth.toObject = function(includeInstance, msg) {\n var f, obj = {\n type: jspb.Message.getFieldWithDefault(msg, 1, 0),\n common: (f = msg.getCommon()) && proto.Conf.EthCommon.toObject(includeInstance, f),\n spi: (f = msg.getSpi()) && proto.Conf.EthSPI.toObject(includeInstance, f),\n rmii: (f = msg.getRmii()) && proto.Conf.EthRMII.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Eth}\n */\nproto.Conf.Eth.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Eth;\n return proto.Conf.Eth.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Eth} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Eth}\n */\nproto.Conf.Eth.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.DeviceTypeEnum} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 2:\n var value = new proto.Conf.EthCommon;\n reader.readMessage(value,proto.Conf.EthCommon.deserializeBinaryFromReader);\n msg.setCommon(value);\n break;\n case 3:\n var value = new proto.Conf.EthSPI;\n reader.readMessage(value,proto.Conf.EthSPI.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n case 4:\n var value = new proto.Conf.EthRMII;\n reader.readMessage(value,proto.Conf.EthRMII.deserializeBinaryFromReader);\n msg.setRmii(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Eth.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Eth.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Eth} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Eth.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getType();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getCommon();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.EthCommon.serializeBinaryToWriter\n );\n }\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.EthSPI.serializeBinaryToWriter\n );\n }\n f = message.getRmii();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.EthRMII.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional DeviceTypeEnum type = 1;\n * @return {!proto.Conf.DeviceTypeEnum}\n */\nproto.Conf.Eth.prototype.getType = function() {\n return /** @type {!proto.Conf.DeviceTypeEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.DeviceTypeEnum} value\n * @return {!proto.Conf.Eth} returns this\n */\nproto.Conf.Eth.prototype.setType = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional EthCommon common = 2;\n * @return {?proto.Conf.EthCommon}\n */\nproto.Conf.Eth.prototype.getCommon = function() {\n return /** @type{?proto.Conf.EthCommon} */ (\n jspb.Message.getWrapperField(this, proto.Conf.EthCommon, 2));\n};\n\n\n/**\n * @param {?proto.Conf.EthCommon|undefined} value\n * @return {!proto.Conf.Eth} returns this\n*/\nproto.Conf.Eth.prototype.setCommon = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Eth} returns this\n */\nproto.Conf.Eth.prototype.clearCommon = function() {\n return this.setCommon(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Eth.prototype.hasCommon = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional EthSPI spi = 3;\n * @return {?proto.Conf.EthSPI}\n */\nproto.Conf.Eth.prototype.getSpi = function() {\n return /** @type{?proto.Conf.EthSPI} */ (\n jspb.Message.getWrapperField(this, proto.Conf.EthSPI, 3));\n};\n\n\n/**\n * @param {?proto.Conf.EthSPI|undefined} value\n * @return {!proto.Conf.Eth} returns this\n*/\nproto.Conf.Eth.prototype.setSpi = function(value) {\n return jspb.Message.setOneofWrapperField(this, 3, proto.Conf.Eth.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Eth} returns this\n */\nproto.Conf.Eth.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Eth.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional EthRMII rmii = 4;\n * @return {?proto.Conf.EthRMII}\n */\nproto.Conf.Eth.prototype.getRmii = function() {\n return /** @type{?proto.Conf.EthRMII} */ (\n jspb.Message.getWrapperField(this, proto.Conf.EthRMII, 4));\n};\n\n\n/**\n * @param {?proto.Conf.EthRMII|undefined} value\n * @return {!proto.Conf.Eth} returns this\n*/\nproto.Conf.Eth.prototype.setRmii = function(value) {\n return jspb.Message.setOneofWrapperField(this, 4, proto.Conf.Eth.oneofGroups_[0], value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Eth} returns this\n */\nproto.Conf.Eth.prototype.clearRmii = function() {\n return this.setRmii(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Eth.prototype.hasRmii = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Battery.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Battery.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Battery} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Battery.toObject = function(includeInstance, msg) {\n var f, obj = {\n channel: jspb.Message.getFieldWithDefault(msg, 1, 0),\n scale: jspb.Message.getFloatingPointFieldWithDefault(msg, 2, 0.0),\n cells: jspb.Message.getFieldWithDefault(msg, 3, 0),\n atten: jspb.Message.getFieldWithDefault(msg, 4, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Battery}\n */\nproto.Conf.Battery.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Battery;\n return proto.Conf.Battery.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Battery} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Battery}\n */\nproto.Conf.Battery.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {!proto.Conf.BatteryChannelEnum} */ (reader.readEnum());\n msg.setChannel(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setScale(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setCells(value);\n break;\n case 4:\n var value = /** @type {!proto.Conf.BatteryAttenEnum} */ (reader.readEnum());\n msg.setAtten(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Battery.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Battery.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Battery} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Battery.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getChannel();\n if (f !== 0.0) {\n writer.writeEnum(\n 1,\n f\n );\n }\n f = message.getScale();\n if (f !== 0.0) {\n writer.writeFloat(\n 2,\n f\n );\n }\n f = message.getCells();\n if (f !== 0) {\n writer.writeInt32(\n 3,\n f\n );\n }\n f = message.getAtten();\n if (f !== 0.0) {\n writer.writeEnum(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional BatteryChannelEnum channel = 1;\n * @return {!proto.Conf.BatteryChannelEnum}\n */\nproto.Conf.Battery.prototype.getChannel = function() {\n return /** @type {!proto.Conf.BatteryChannelEnum} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {!proto.Conf.BatteryChannelEnum} value\n * @return {!proto.Conf.Battery} returns this\n */\nproto.Conf.Battery.prototype.setChannel = function(value) {\n return jspb.Message.setProto3EnumField(this, 1, value);\n};\n\n\n/**\n * optional float scale = 2;\n * @return {number}\n */\nproto.Conf.Battery.prototype.getScale = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 2, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Battery} returns this\n */\nproto.Conf.Battery.prototype.setScale = function(value) {\n return jspb.Message.setProto3FloatField(this, 2, value);\n};\n\n\n/**\n * optional int32 cells = 3;\n * @return {number}\n */\nproto.Conf.Battery.prototype.getCells = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Battery} returns this\n */\nproto.Conf.Battery.prototype.setCells = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional BatteryAttenEnum atten = 4;\n * @return {!proto.Conf.BatteryAttenEnum}\n */\nproto.Conf.Battery.prototype.getAtten = function() {\n return /** @type {!proto.Conf.BatteryAttenEnum} */ (jspb.Message.getFieldWithDefault(this, 4, 0));\n};\n\n\n/**\n * @param {!proto.Conf.BatteryAttenEnum} value\n * @return {!proto.Conf.Battery} returns this\n */\nproto.Conf.Battery.prototype.setAtten = function(value) {\n return jspb.Message.setProto3EnumField(this, 4, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Gpios.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Gpios.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Gpios} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Gpios.toObject = function(includeInstance, msg) {\n var f, obj = {\n greenled: (f = msg.getGreenled()) && proto.Conf.GPIO.toObject(includeInstance, f),\n redled: (f = msg.getRedled()) && proto.Conf.GPIO.toObject(includeInstance, f),\n audiojack: (f = msg.getAudiojack()) && proto.Conf.GPIO.toObject(includeInstance, f),\n amp: (f = msg.getAmp()) && proto.Conf.GPIO.toObject(includeInstance, f),\n power: (f = msg.getPower()) && proto.Conf.GPIO.toObject(includeInstance, f),\n ir: (f = msg.getIr()) && proto.Conf.GPIO.toObject(includeInstance, f),\n jack: (f = msg.getJack()) && proto.Conf.GPIO.toObject(includeInstance, f),\n spkfault: (f = msg.getSpkfault()) && proto.Conf.GPIO.toObject(includeInstance, f),\n vcc: (f = msg.getVcc()) && proto.Conf.GPIO.toObject(includeInstance, f),\n gnd: (f = msg.getGnd()) && proto.Conf.GPIO.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Gpios}\n */\nproto.Conf.Gpios.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Gpios;\n return proto.Conf.Gpios.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Gpios} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Gpios}\n */\nproto.Conf.Gpios.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setGreenled(value);\n break;\n case 2:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setRedled(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setAudiojack(value);\n break;\n case 4:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setAmp(value);\n break;\n case 5:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setPower(value);\n break;\n case 6:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setIr(value);\n break;\n case 7:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setJack(value);\n break;\n case 8:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setSpkfault(value);\n break;\n case 9:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setVcc(value);\n break;\n case 10:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setGnd(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Gpios.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Gpios.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Gpios} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Gpios.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGreenled();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getRedled();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getAudiojack();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getAmp();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getPower();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getIr();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getJack();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getSpkfault();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getVcc();\n if (f != null) {\n writer.writeMessage(\n 9,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getGnd();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional GPIO greenLED = 1;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getGreenled = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 1));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setGreenled = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearGreenled = function() {\n return this.setGreenled(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasGreenled = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional GPIO redLED = 2;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getRedled = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 2));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setRedled = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearRedled = function() {\n return this.setRedled(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasRedled = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional GPIO audioJack = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getAudiojack = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setAudiojack = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearAudiojack = function() {\n return this.setAudiojack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasAudiojack = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional GPIO amp = 4;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getAmp = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 4));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setAmp = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearAmp = function() {\n return this.setAmp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasAmp = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional GPIO power = 5;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getPower = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 5));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setPower = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearPower = function() {\n return this.setPower(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasPower = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional GPIO ir = 6;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getIr = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 6));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setIr = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearIr = function() {\n return this.setIr(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasIr = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional GPIO jack = 7;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getJack = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 7));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setJack = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearJack = function() {\n return this.setJack(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasJack = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional GPIO spkfault = 8;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getSpkfault = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 8));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setSpkfault = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearSpkfault = function() {\n return this.setSpkfault(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasSpkfault = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional GPIO Vcc = 9;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getVcc = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 9));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setVcc = function(value) {\n return jspb.Message.setWrapperField(this, 9, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearVcc = function() {\n return this.setVcc(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasVcc = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional GPIO GND = 10;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.Gpios.prototype.getGnd = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 10));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.Gpios} returns this\n*/\nproto.Conf.Gpios.prototype.setGnd = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Gpios} returns this\n */\nproto.Conf.Gpios.prototype.clearGnd = function() {\n return this.setGnd(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Gpios.prototype.hasGnd = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.Conf.Dev.repeatedFields_ = [9];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Dev.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Dev.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Dev} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Dev.toObject = function(includeInstance, msg) {\n var f, obj = {\n spi: (f = msg.getSpi()) && proto.Conf.SPIBus.toObject(includeInstance, f),\n i2c: (f = msg.getI2c()) && proto.Conf.I2CBus.toObject(includeInstance, f),\n dac: (f = msg.getDac()) && proto.Conf.DACDev.toObject(includeInstance, f),\n spdif: (f = msg.getSpdif()) && proto.Conf.SPDIFDev.toObject(includeInstance, f),\n display: (f = msg.getDisplay()) && proto.Conf.DisplayDev.toObject(includeInstance, f),\n gpioExp: (f = msg.getGpioExp()) && proto.Conf.GPIOExp.toObject(includeInstance, f),\n ledStrip: (f = msg.getLedStrip()) && proto.Conf.LEDStrip.toObject(includeInstance, f),\n rotary: (f = msg.getRotary()) && proto.Conf.Rotary.toObject(includeInstance, f),\n buttonsList: jspb.Message.toObjectList(msg.getButtonsList(),\n proto.Conf.Button.toObject, includeInstance),\n eth: (f = msg.getEth()) && proto.Conf.Eth.toObject(includeInstance, f),\n battery: (f = msg.getBattery()) && proto.Conf.Battery.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Dev}\n */\nproto.Conf.Dev.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Dev;\n return proto.Conf.Dev.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Dev} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Dev}\n */\nproto.Conf.Dev.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.SPIBus;\n reader.readMessage(value,proto.Conf.SPIBus.deserializeBinaryFromReader);\n msg.setSpi(value);\n break;\n case 2:\n var value = new proto.Conf.I2CBus;\n reader.readMessage(value,proto.Conf.I2CBus.deserializeBinaryFromReader);\n msg.setI2c(value);\n break;\n case 3:\n var value = new proto.Conf.DACDev;\n reader.readMessage(value,proto.Conf.DACDev.deserializeBinaryFromReader);\n msg.setDac(value);\n break;\n case 4:\n var value = new proto.Conf.SPDIFDev;\n reader.readMessage(value,proto.Conf.SPDIFDev.deserializeBinaryFromReader);\n msg.setSpdif(value);\n break;\n case 5:\n var value = new proto.Conf.DisplayDev;\n reader.readMessage(value,proto.Conf.DisplayDev.deserializeBinaryFromReader);\n msg.setDisplay(value);\n break;\n case 6:\n var value = new proto.Conf.GPIOExp;\n reader.readMessage(value,proto.Conf.GPIOExp.deserializeBinaryFromReader);\n msg.setGpioExp(value);\n break;\n case 7:\n var value = new proto.Conf.LEDStrip;\n reader.readMessage(value,proto.Conf.LEDStrip.deserializeBinaryFromReader);\n msg.setLedStrip(value);\n break;\n case 8:\n var value = new proto.Conf.Rotary;\n reader.readMessage(value,proto.Conf.Rotary.deserializeBinaryFromReader);\n msg.setRotary(value);\n break;\n case 9:\n var value = new proto.Conf.Button;\n reader.readMessage(value,proto.Conf.Button.deserializeBinaryFromReader);\n msg.addButtons(value);\n break;\n case 10:\n var value = new proto.Conf.Eth;\n reader.readMessage(value,proto.Conf.Eth.deserializeBinaryFromReader);\n msg.setEth(value);\n break;\n case 11:\n var value = new proto.Conf.Battery;\n reader.readMessage(value,proto.Conf.Battery.deserializeBinaryFromReader);\n msg.setBattery(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Dev.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Dev.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Dev} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Dev.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getSpi();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.SPIBus.serializeBinaryToWriter\n );\n }\n f = message.getI2c();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.I2CBus.serializeBinaryToWriter\n );\n }\n f = message.getDac();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.DACDev.serializeBinaryToWriter\n );\n }\n f = message.getSpdif();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.SPDIFDev.serializeBinaryToWriter\n );\n }\n f = message.getDisplay();\n if (f != null) {\n writer.writeMessage(\n 5,\n f,\n proto.Conf.DisplayDev.serializeBinaryToWriter\n );\n }\n f = message.getGpioExp();\n if (f != null) {\n writer.writeMessage(\n 6,\n f,\n proto.Conf.GPIOExp.serializeBinaryToWriter\n );\n }\n f = message.getLedStrip();\n if (f != null) {\n writer.writeMessage(\n 7,\n f,\n proto.Conf.LEDStrip.serializeBinaryToWriter\n );\n }\n f = message.getRotary();\n if (f != null) {\n writer.writeMessage(\n 8,\n f,\n proto.Conf.Rotary.serializeBinaryToWriter\n );\n }\n f = message.getButtonsList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 9,\n f,\n proto.Conf.Button.serializeBinaryToWriter\n );\n }\n f = message.getEth();\n if (f != null) {\n writer.writeMessage(\n 10,\n f,\n proto.Conf.Eth.serializeBinaryToWriter\n );\n }\n f = message.getBattery();\n if (f != null) {\n writer.writeMessage(\n 11,\n f,\n proto.Conf.Battery.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional SPIBus spi = 1;\n * @return {?proto.Conf.SPIBus}\n */\nproto.Conf.Dev.prototype.getSpi = function() {\n return /** @type{?proto.Conf.SPIBus} */ (\n jspb.Message.getWrapperField(this, proto.Conf.SPIBus, 1));\n};\n\n\n/**\n * @param {?proto.Conf.SPIBus|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setSpi = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearSpi = function() {\n return this.setSpi(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasSpi = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional I2CBus i2c = 2;\n * @return {?proto.Conf.I2CBus}\n */\nproto.Conf.Dev.prototype.getI2c = function() {\n return /** @type{?proto.Conf.I2CBus} */ (\n jspb.Message.getWrapperField(this, proto.Conf.I2CBus, 2));\n};\n\n\n/**\n * @param {?proto.Conf.I2CBus|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setI2c = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearI2c = function() {\n return this.setI2c(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasI2c = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional DACDev dac = 3;\n * @return {?proto.Conf.DACDev}\n */\nproto.Conf.Dev.prototype.getDac = function() {\n return /** @type{?proto.Conf.DACDev} */ (\n jspb.Message.getWrapperField(this, proto.Conf.DACDev, 3));\n};\n\n\n/**\n * @param {?proto.Conf.DACDev|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setDac = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearDac = function() {\n return this.setDac(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasDac = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional SPDIFDev spdif = 4;\n * @return {?proto.Conf.SPDIFDev}\n */\nproto.Conf.Dev.prototype.getSpdif = function() {\n return /** @type{?proto.Conf.SPDIFDev} */ (\n jspb.Message.getWrapperField(this, proto.Conf.SPDIFDev, 4));\n};\n\n\n/**\n * @param {?proto.Conf.SPDIFDev|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setSpdif = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearSpdif = function() {\n return this.setSpdif(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasSpdif = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional DisplayDev display = 5;\n * @return {?proto.Conf.DisplayDev}\n */\nproto.Conf.Dev.prototype.getDisplay = function() {\n return /** @type{?proto.Conf.DisplayDev} */ (\n jspb.Message.getWrapperField(this, proto.Conf.DisplayDev, 5));\n};\n\n\n/**\n * @param {?proto.Conf.DisplayDev|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setDisplay = function(value) {\n return jspb.Message.setWrapperField(this, 5, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearDisplay = function() {\n return this.setDisplay(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasDisplay = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional GPIOExp gpio_exp = 6;\n * @return {?proto.Conf.GPIOExp}\n */\nproto.Conf.Dev.prototype.getGpioExp = function() {\n return /** @type{?proto.Conf.GPIOExp} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIOExp, 6));\n};\n\n\n/**\n * @param {?proto.Conf.GPIOExp|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setGpioExp = function(value) {\n return jspb.Message.setWrapperField(this, 6, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearGpioExp = function() {\n return this.setGpioExp(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasGpioExp = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional LEDStrip led_strip = 7;\n * @return {?proto.Conf.LEDStrip}\n */\nproto.Conf.Dev.prototype.getLedStrip = function() {\n return /** @type{?proto.Conf.LEDStrip} */ (\n jspb.Message.getWrapperField(this, proto.Conf.LEDStrip, 7));\n};\n\n\n/**\n * @param {?proto.Conf.LEDStrip|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setLedStrip = function(value) {\n return jspb.Message.setWrapperField(this, 7, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearLedStrip = function() {\n return this.setLedStrip(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasLedStrip = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional Rotary rotary = 8;\n * @return {?proto.Conf.Rotary}\n */\nproto.Conf.Dev.prototype.getRotary = function() {\n return /** @type{?proto.Conf.Rotary} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Rotary, 8));\n};\n\n\n/**\n * @param {?proto.Conf.Rotary|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setRotary = function(value) {\n return jspb.Message.setWrapperField(this, 8, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearRotary = function() {\n return this.setRotary(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasRotary = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * repeated Button buttons = 9;\n * @return {!Array}\n */\nproto.Conf.Dev.prototype.getButtonsList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.Conf.Button, 9));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setButtonsList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 9, value);\n};\n\n\n/**\n * @param {!proto.Conf.Button=} opt_value\n * @param {number=} opt_index\n * @return {!proto.Conf.Button}\n */\nproto.Conf.Dev.prototype.addButtons = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.Conf.Button, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearButtonsList = function() {\n return this.setButtonsList([]);\n};\n\n\n/**\n * optional Eth eth = 10;\n * @return {?proto.Conf.Eth}\n */\nproto.Conf.Dev.prototype.getEth = function() {\n return /** @type{?proto.Conf.Eth} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Eth, 10));\n};\n\n\n/**\n * @param {?proto.Conf.Eth|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setEth = function(value) {\n return jspb.Message.setWrapperField(this, 10, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearEth = function() {\n return this.setEth(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasEth = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional Battery battery = 11;\n * @return {?proto.Conf.Battery}\n */\nproto.Conf.Dev.prototype.getBattery = function() {\n return /** @type{?proto.Conf.Battery} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Battery, 11));\n};\n\n\n/**\n * @param {?proto.Conf.Battery|undefined} value\n * @return {!proto.Conf.Dev} returns this\n*/\nproto.Conf.Dev.prototype.setBattery = function(value) {\n return jspb.Message.setWrapperField(this, 11, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Dev} returns this\n */\nproto.Conf.Dev.prototype.clearBattery = function() {\n return this.setBattery(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Dev.prototype.hasBattery = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.Conf.SleepService.repeatedFields_ = [4,5];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.SleepService.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.SleepService.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.SleepService} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SleepService.toObject = function(includeInstance, msg) {\n var f, obj = {\n delay: jspb.Message.getFieldWithDefault(msg, 1, 0),\n spurious: jspb.Message.getFieldWithDefault(msg, 2, 0),\n sleep: (f = msg.getSleep()) && proto.Conf.GPIO.toObject(includeInstance, f),\n wakeList: jspb.Message.toObjectList(msg.getWakeList(),\n proto.Conf.GPIO.toObject, includeInstance),\n rtcList: jspb.Message.toObjectList(msg.getRtcList(),\n proto.Conf.GPIO.toObject, includeInstance),\n batt: jspb.Message.getFloatingPointFieldWithDefault(msg, 6, 0.0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.SleepService}\n */\nproto.Conf.SleepService.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.SleepService;\n return proto.Conf.SleepService.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.SleepService} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.SleepService}\n */\nproto.Conf.SleepService.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setDelay(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setSpurious(value);\n break;\n case 3:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.setSleep(value);\n break;\n case 4:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.addWake(value);\n break;\n case 5:\n var value = new proto.Conf.GPIO;\n reader.readMessage(value,proto.Conf.GPIO.deserializeBinaryFromReader);\n msg.addRtc(value);\n break;\n case 6:\n var value = /** @type {number} */ (reader.readFloat());\n msg.setBatt(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.SleepService.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.SleepService.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.SleepService} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.SleepService.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getDelay();\n if (f !== 0) {\n writer.writeUint32(\n 1,\n f\n );\n }\n f = message.getSpurious();\n if (f !== 0) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = message.getSleep();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getWakeList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 4,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getRtcList();\n if (f.length > 0) {\n writer.writeRepeatedMessage(\n 5,\n f,\n proto.Conf.GPIO.serializeBinaryToWriter\n );\n }\n f = message.getBatt();\n if (f !== 0.0) {\n writer.writeFloat(\n 6,\n f\n );\n }\n};\n\n\n/**\n * optional uint32 delay = 1;\n * @return {number}\n */\nproto.Conf.SleepService.prototype.getDelay = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.setDelay = function(value) {\n return jspb.Message.setProto3IntField(this, 1, value);\n};\n\n\n/**\n * optional int32 spurious = 2;\n * @return {number}\n */\nproto.Conf.SleepService.prototype.getSpurious = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.setSpurious = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional GPIO sleep = 3;\n * @return {?proto.Conf.GPIO}\n */\nproto.Conf.SleepService.prototype.getSleep = function() {\n return /** @type{?proto.Conf.GPIO} */ (\n jspb.Message.getWrapperField(this, proto.Conf.GPIO, 3));\n};\n\n\n/**\n * @param {?proto.Conf.GPIO|undefined} value\n * @return {!proto.Conf.SleepService} returns this\n*/\nproto.Conf.SleepService.prototype.setSleep = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.clearSleep = function() {\n return this.setSleep(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.SleepService.prototype.hasSleep = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * repeated GPIO wake = 4;\n * @return {!Array}\n */\nproto.Conf.SleepService.prototype.getWakeList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.Conf.GPIO, 4));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.Conf.SleepService} returns this\n*/\nproto.Conf.SleepService.prototype.setWakeList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 4, value);\n};\n\n\n/**\n * @param {!proto.Conf.GPIO=} opt_value\n * @param {number=} opt_index\n * @return {!proto.Conf.GPIO}\n */\nproto.Conf.SleepService.prototype.addWake = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 4, opt_value, proto.Conf.GPIO, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.clearWakeList = function() {\n return this.setWakeList([]);\n};\n\n\n/**\n * repeated GPIO rtc = 5;\n * @return {!Array}\n */\nproto.Conf.SleepService.prototype.getRtcList = function() {\n return /** @type{!Array} */ (\n jspb.Message.getRepeatedWrapperField(this, proto.Conf.GPIO, 5));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.Conf.SleepService} returns this\n*/\nproto.Conf.SleepService.prototype.setRtcList = function(value) {\n return jspb.Message.setRepeatedWrapperField(this, 5, value);\n};\n\n\n/**\n * @param {!proto.Conf.GPIO=} opt_value\n * @param {number=} opt_index\n * @return {!proto.Conf.GPIO}\n */\nproto.Conf.SleepService.prototype.addRtc = function(opt_value, opt_index) {\n return jspb.Message.addToRepeatedWrapperField(this, 5, opt_value, proto.Conf.GPIO, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.clearRtcList = function() {\n return this.setRtcList([]);\n};\n\n\n/**\n * optional float batt = 6;\n * @return {number}\n */\nproto.Conf.SleepService.prototype.getBatt = function() {\n return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 6, 0.0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.SleepService} returns this\n */\nproto.Conf.SleepService.prototype.setBatt = function(value) {\n return jspb.Message.setProto3FloatField(this, 6, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Artwork.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Artwork.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Artwork} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Artwork.toObject = function(includeInstance, msg) {\n var f, obj = {\n enabled: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),\n resize: jspb.Message.getFieldWithDefault(msg, 2, 0)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Artwork}\n */\nproto.Conf.Artwork.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Artwork;\n return proto.Conf.Artwork.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Artwork} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Artwork}\n */\nproto.Conf.Artwork.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnabled(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setResize(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Artwork.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Artwork.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Artwork} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Artwork.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getEnabled();\n if (f) {\n writer.writeBool(\n 1,\n f\n );\n }\n f = message.getResize();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n};\n\n\n/**\n * optional bool enabled = 1;\n * @return {boolean}\n */\nproto.Conf.Artwork.prototype.getEnabled = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.Conf.Artwork} returns this\n */\nproto.Conf.Artwork.prototype.setEnabled = function(value) {\n return jspb.Message.setProto3BooleanField(this, 1, value);\n};\n\n\n/**\n * optional uint32 resize = 2;\n * @return {number}\n */\nproto.Conf.Artwork.prototype.getResize = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Artwork} returns this\n */\nproto.Conf.Artwork.prototype.setResize = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Metadata.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Metadata.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Metadata} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Metadata.toObject = function(includeInstance, msg) {\n var f, obj = {\n format: jspb.Message.getFieldWithDefault(msg, 1, \"\"),\n speed: jspb.Message.getFieldWithDefault(msg, 2, 0),\n pause: jspb.Message.getFieldWithDefault(msg, 3, 0),\n artwork: (f = msg.getArtwork()) && proto.Conf.Artwork.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Metadata}\n */\nproto.Conf.Metadata.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Metadata;\n return proto.Conf.Metadata.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Metadata} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Metadata}\n */\nproto.Conf.Metadata.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {string} */ (reader.readString());\n msg.setFormat(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setSpeed(value);\n break;\n case 3:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setPause(value);\n break;\n case 4:\n var value = new proto.Conf.Artwork;\n reader.readMessage(value,proto.Conf.Artwork.deserializeBinaryFromReader);\n msg.setArtwork(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Metadata.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Metadata.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Metadata} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Metadata.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getFormat();\n if (f.length > 0) {\n writer.writeString(\n 1,\n f\n );\n }\n f = message.getSpeed();\n if (f !== 0) {\n writer.writeUint32(\n 2,\n f\n );\n }\n f = message.getPause();\n if (f !== 0) {\n writer.writeUint32(\n 3,\n f\n );\n }\n f = message.getArtwork();\n if (f != null) {\n writer.writeMessage(\n 4,\n f,\n proto.Conf.Artwork.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional string format = 1;\n * @return {string}\n */\nproto.Conf.Metadata.prototype.getFormat = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.Conf.Metadata} returns this\n */\nproto.Conf.Metadata.prototype.setFormat = function(value) {\n return jspb.Message.setProto3StringField(this, 1, value);\n};\n\n\n/**\n * optional uint32 speed = 2;\n * @return {number}\n */\nproto.Conf.Metadata.prototype.getSpeed = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Metadata} returns this\n */\nproto.Conf.Metadata.prototype.setSpeed = function(value) {\n return jspb.Message.setProto3IntField(this, 2, value);\n};\n\n\n/**\n * optional uint32 pause = 3;\n * @return {number}\n */\nproto.Conf.Metadata.prototype.getPause = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.Conf.Metadata} returns this\n */\nproto.Conf.Metadata.prototype.setPause = function(value) {\n return jspb.Message.setProto3IntField(this, 3, value);\n};\n\n\n/**\n * optional Artwork artwork = 4;\n * @return {?proto.Conf.Artwork}\n */\nproto.Conf.Metadata.prototype.getArtwork = function() {\n return /** @type{?proto.Conf.Artwork} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Artwork, 4));\n};\n\n\n/**\n * @param {?proto.Conf.Artwork|undefined} value\n * @return {!proto.Conf.Metadata} returns this\n*/\nproto.Conf.Metadata.prototype.setArtwork = function(value) {\n return jspb.Message.setWrapperField(this, 4, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Metadata} returns this\n */\nproto.Conf.Metadata.prototype.clearArtwork = function() {\n return this.setArtwork(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Metadata.prototype.hasArtwork = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Services.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Services.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Services} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Services.toObject = function(includeInstance, msg) {\n var f, obj = {\n metadata: (f = msg.getMetadata()) && proto.Conf.Metadata.toObject(includeInstance, f),\n sleep: (f = msg.getSleep()) && proto.Conf.SleepService.toObject(includeInstance, f)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Services}\n */\nproto.Conf.Services.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Services;\n return proto.Conf.Services.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Services} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Services}\n */\nproto.Conf.Services.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.Metadata;\n reader.readMessage(value,proto.Conf.Metadata.deserializeBinaryFromReader);\n msg.setMetadata(value);\n break;\n case 2:\n var value = new proto.Conf.SleepService;\n reader.readMessage(value,proto.Conf.SleepService.deserializeBinaryFromReader);\n msg.setSleep(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Services.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Services.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Services} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Services.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getMetadata();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.Metadata.serializeBinaryToWriter\n );\n }\n f = message.getSleep();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.SleepService.serializeBinaryToWriter\n );\n }\n};\n\n\n/**\n * optional Metadata metadata = 1;\n * @return {?proto.Conf.Metadata}\n */\nproto.Conf.Services.prototype.getMetadata = function() {\n return /** @type{?proto.Conf.Metadata} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Metadata, 1));\n};\n\n\n/**\n * @param {?proto.Conf.Metadata|undefined} value\n * @return {!proto.Conf.Services} returns this\n*/\nproto.Conf.Services.prototype.setMetadata = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Services} returns this\n */\nproto.Conf.Services.prototype.clearMetadata = function() {\n return this.setMetadata(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Services.prototype.hasMetadata = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional SleepService sleep = 2;\n * @return {?proto.Conf.SleepService}\n */\nproto.Conf.Services.prototype.getSleep = function() {\n return /** @type{?proto.Conf.SleepService} */ (\n jspb.Message.getWrapperField(this, proto.Conf.SleepService, 2));\n};\n\n\n/**\n * @param {?proto.Conf.SleepService|undefined} value\n * @return {!proto.Conf.Services} returns this\n*/\nproto.Conf.Services.prototype.setSleep = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Services} returns this\n */\nproto.Conf.Services.prototype.clearSleep = function() {\n return this.setSleep(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Services.prototype.hasSleep = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.Conf.Config.prototype.toObject = function(opt_includeInstance) {\n return proto.Conf.Config.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.Conf.Config} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Config.toObject = function(includeInstance, msg) {\n var f, obj = {\n gpios: (f = msg.getGpios()) && proto.Conf.Gpios.toObject(includeInstance, f),\n dev: (f = msg.getDev()) && proto.Conf.Dev.toObject(includeInstance, f),\n services: (f = msg.getServices()) && proto.Conf.Services.toObject(includeInstance, f),\n deviceName: jspb.Message.getFieldWithDefault(msg, 4, \"\")\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.Conf.Config}\n */\nproto.Conf.Config.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.Conf.Config;\n return proto.Conf.Config.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.Conf.Config} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.Conf.Config}\n */\nproto.Conf.Config.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = new proto.Conf.Gpios;\n reader.readMessage(value,proto.Conf.Gpios.deserializeBinaryFromReader);\n msg.setGpios(value);\n break;\n case 2:\n var value = new proto.Conf.Dev;\n reader.readMessage(value,proto.Conf.Dev.deserializeBinaryFromReader);\n msg.setDev(value);\n break;\n case 3:\n var value = new proto.Conf.Services;\n reader.readMessage(value,proto.Conf.Services.deserializeBinaryFromReader);\n msg.setServices(value);\n break;\n case 4:\n var value = /** @type {string} */ (reader.readString());\n msg.setDeviceName(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.Conf.Config.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.Conf.Config.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.Conf.Config} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.Conf.Config.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = message.getGpios();\n if (f != null) {\n writer.writeMessage(\n 1,\n f,\n proto.Conf.Gpios.serializeBinaryToWriter\n );\n }\n f = message.getDev();\n if (f != null) {\n writer.writeMessage(\n 2,\n f,\n proto.Conf.Dev.serializeBinaryToWriter\n );\n }\n f = message.getServices();\n if (f != null) {\n writer.writeMessage(\n 3,\n f,\n proto.Conf.Services.serializeBinaryToWriter\n );\n }\n f = message.getDeviceName();\n if (f.length > 0) {\n writer.writeString(\n 4,\n f\n );\n }\n};\n\n\n/**\n * optional Gpios gpios = 1;\n * @return {?proto.Conf.Gpios}\n */\nproto.Conf.Config.prototype.getGpios = function() {\n return /** @type{?proto.Conf.Gpios} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Gpios, 1));\n};\n\n\n/**\n * @param {?proto.Conf.Gpios|undefined} value\n * @return {!proto.Conf.Config} returns this\n*/\nproto.Conf.Config.prototype.setGpios = function(value) {\n return jspb.Message.setWrapperField(this, 1, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Config} returns this\n */\nproto.Conf.Config.prototype.clearGpios = function() {\n return this.setGpios(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Config.prototype.hasGpios = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional Dev dev = 2;\n * @return {?proto.Conf.Dev}\n */\nproto.Conf.Config.prototype.getDev = function() {\n return /** @type{?proto.Conf.Dev} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Dev, 2));\n};\n\n\n/**\n * @param {?proto.Conf.Dev|undefined} value\n * @return {!proto.Conf.Config} returns this\n*/\nproto.Conf.Config.prototype.setDev = function(value) {\n return jspb.Message.setWrapperField(this, 2, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Config} returns this\n */\nproto.Conf.Config.prototype.clearDev = function() {\n return this.setDev(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Config.prototype.hasDev = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional Services services = 3;\n * @return {?proto.Conf.Services}\n */\nproto.Conf.Config.prototype.getServices = function() {\n return /** @type{?proto.Conf.Services} */ (\n jspb.Message.getWrapperField(this, proto.Conf.Services, 3));\n};\n\n\n/**\n * @param {?proto.Conf.Services|undefined} value\n * @return {!proto.Conf.Config} returns this\n*/\nproto.Conf.Config.prototype.setServices = function(value) {\n return jspb.Message.setWrapperField(this, 3, value);\n};\n\n\n/**\n * Clears the message field making it undefined.\n * @return {!proto.Conf.Config} returns this\n */\nproto.Conf.Config.prototype.clearServices = function() {\n return this.setServices(undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.Conf.Config.prototype.hasServices = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional string device_name = 4;\n * @return {string}\n */\nproto.Conf.Config.prototype.getDeviceName = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.Conf.Config} returns this\n */\nproto.Conf.Config.prototype.setDeviceName = function(value) {\n return jspb.Message.setProto3StringField(this, 4, value);\n};\n\n\n/**\n * @enum {number}\n */\nproto.Conf.ButtonAction = {\n ACTRLS_NONE: 0,\n ACTRLS_POWER: 1,\n ACTRLS_VOLUP: 2,\n ACTRLS_VOLDOWN: 3,\n ACTRLS_TOGGLE: 4,\n ACTRLS_PLAY: 5,\n ACTRLS_PAUSE: 6,\n ACTRLS_STOP: 7,\n ACTRLS_REW: 8,\n ACTRLS_FWD: 9,\n ACTRLS_PREV: 10,\n ACTRLS_NEXT: 11,\n BCTRLS_UP: 12,\n BCTRLS_DOWN: 13,\n BCTRLS_LEFT: 14,\n BCTRLS_RIGHT: 15,\n BCTRLS_PS1: 16,\n BCTRLS_PS2: 17,\n BCTRLS_PS3: 18,\n BCTRLS_PS4: 19,\n BCTRLS_PS5: 20,\n BCTRLS_PS6: 21,\n BCTRLS_PS7: 22,\n BCTRLS_PS8: 23,\n BCTRLS_PS9: 24,\n BCTRLS_PS10: 25,\n KNOB_LEFT: 26,\n KNOB_RIGHT: 27,\n KNOB_PUSH: 28,\n ACTRLS_SLEEP: 29\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.DACModelEnum = {\n UNSPECIFIED_MODEL: 0,\n TAS57XX: 1,\n TAS5713: 2,\n AC101: 3,\n WM8978: 4,\n ES8388: 5,\n I2S: 6\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.DeviceTypeEnum = {\n UNSPECIFIED_TYPE: 0,\n DEVTYPE_SPI: 1,\n DEVTYPE_I2C: 2,\n DEVTYPE__RMII: 3\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.DisplayDriverEnum = {\n UNSPECIFIED_DRIVER: 0,\n SSD1306: 1,\n SSD1322: 2,\n SSD1326: 3,\n SSD1327: 4,\n SH1106: 5,\n SSD1675: 6,\n ST7735: 7,\n ST7789: 8,\n ILI9341: 9,\n ILI9341_24: 10,\n SSD1351: 11\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.PortEnum = {\n UNSPECIFIED_SYSTPORT: 0,\n SYSTEM: 1,\n DAC: 2\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.EthModelEnum = {\n UNSPECIFIED_ETHMODEL: 0,\n LAN8720: 1,\n DM9051: 2,\n W5500: 3\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.GPIOExpModelEnum = {\n UNSPECIFIED_EXP: 0,\n PCA9535: 1,\n PCA85XX: 2,\n MCP23017: 3,\n MCP23S17: 4\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.HostEnum = {\n UNSPECIFIED_HOST: 0,\n HOST0: 1,\n HOST1: 2\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.I2CPortEnum = {\n UNSPECIFIED_PORT: 0,\n I2CPORT0: 1,\n I2CPORT1: 2\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.MCKEnum = {\n UNSPECIFIED_MCK: 0,\n MCK0: 1,\n MCK1: 2,\n MCK2: 3\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.BatteryChannelEnum = {\n UNSPECIFIED_CH: 0,\n CH0: 1,\n CH1: 2,\n CH2: 3,\n CH3: 4,\n CH4: 5,\n CH5: 6,\n CH6: 7,\n CH7: 8\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.BatteryAttenEnum = {\n UNSPECIFIED_ATT: 0,\n ATT_0: 1,\n ATT_1: 2,\n ATT_2: 3,\n ATT_3: 4\n};\n\n/**\n * @enum {number}\n */\nproto.Conf.EthType = {\n UNSPECIFIED_ETH: 0,\n SPI: 1,\n RMII: 2\n};\n\ngoog.object.extend(exports, proto.Conf);\n","// source: nanopb.proto\n/**\n * @fileoverview\n * @enhanceable\n * @suppress {missingRequire} reports error on implicit type usages.\n * @suppress {messageConventions} JS Compiler reports an error if a variable or\n * field starts with 'MSG_' and isn't a translatable message.\n * @public\n */\n// GENERATED CODE -- DO NOT EDIT!\n/* eslint-disable */\n// @ts-nocheck\n\nvar jspb = require('google-protobuf');\nvar goog = jspb;\nvar global = (function() {\n if (this) { return this; }\n if (typeof window !== 'undefined') { return window; }\n if (typeof global !== 'undefined') { return global; }\n if (typeof self !== 'undefined') { return self; }\n return Function('return this')();\n}.call(null));\n\nvar google_protobuf_descriptor_pb = require('google-protobuf/google/protobuf/descriptor_pb.js');\ngoog.object.extend(proto, google_protobuf_descriptor_pb);\ngoog.exportSymbol('proto.DescriptorSize', null, global);\ngoog.exportSymbol('proto.FieldType', null, global);\ngoog.exportSymbol('proto.IntSize', null, global);\ngoog.exportSymbol('proto.NanoPBOptions', null, global);\ngoog.exportSymbol('proto.TypenameMangling', null, global);\ngoog.exportSymbol('proto.nanopb', null, global);\ngoog.exportSymbol('proto.nanopbEnumopt', null, global);\ngoog.exportSymbol('proto.nanopbFileopt', null, global);\ngoog.exportSymbol('proto.nanopbMsgopt', null, global);\n/**\n * Generated by JsPbCodeGenerator.\n * @param {Array=} opt_data Optional initial data array, typically from a\n * server response, or constructed directly in Javascript. The array is used\n * in place and becomes part of the constructed object. It is not cloned.\n * If no data is provided, the constructed object will be empty, but still\n * valid.\n * @extends {jspb.Message}\n * @constructor\n */\nproto.NanoPBOptions = function(opt_data) {\n jspb.Message.initialize(this, opt_data, 0, -1, proto.NanoPBOptions.repeatedFields_, null);\n};\ngoog.inherits(proto.NanoPBOptions, jspb.Message);\nif (goog.DEBUG && !COMPILED) {\n /**\n * @public\n * @override\n */\n proto.NanoPBOptions.displayName = 'proto.NanoPBOptions';\n}\n\n/**\n * List of repeated fields within this message type.\n * @private {!Array}\n * @const\n */\nproto.NanoPBOptions.repeatedFields_ = [24,26];\n\n\n\nif (jspb.Message.GENERATE_TO_OBJECT) {\n/**\n * Creates an object representation of this proto.\n * Field names that are reserved in JavaScript and will be renamed to pb_name.\n * Optional fields that are not set will be set to undefined.\n * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n * For the list of reserved names please see:\n * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n * @param {boolean=} opt_includeInstance Deprecated. whether to include the\n * JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @return {!Object}\n */\nproto.NanoPBOptions.prototype.toObject = function(opt_includeInstance) {\n return proto.NanoPBOptions.toObject(opt_includeInstance, this);\n};\n\n\n/**\n * Static version of the {@see toObject} method.\n * @param {boolean|undefined} includeInstance Deprecated. Whether to include\n * the JSPB instance for transitional soy proto support:\n * http://goto/soy-param-migration\n * @param {!proto.NanoPBOptions} msg The msg instance to transform.\n * @return {!Object}\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.NanoPBOptions.toObject = function(includeInstance, msg) {\n var f, obj = {\n maxSize: (f = jspb.Message.getField(msg, 1)) == null ? undefined : f,\n maxLength: (f = jspb.Message.getField(msg, 14)) == null ? undefined : f,\n maxCount: (f = jspb.Message.getField(msg, 2)) == null ? undefined : f,\n intSize: jspb.Message.getFieldWithDefault(msg, 7, 0),\n type: jspb.Message.getFieldWithDefault(msg, 3, 0),\n longNames: jspb.Message.getBooleanFieldWithDefault(msg, 4, true),\n packedStruct: jspb.Message.getBooleanFieldWithDefault(msg, 5, false),\n packedEnum: jspb.Message.getBooleanFieldWithDefault(msg, 10, false),\n skipMessage: jspb.Message.getBooleanFieldWithDefault(msg, 6, false),\n noUnions: jspb.Message.getBooleanFieldWithDefault(msg, 8, false),\n msgid: (f = jspb.Message.getField(msg, 9)) == null ? undefined : f,\n anonymousOneof: jspb.Message.getBooleanFieldWithDefault(msg, 11, false),\n proto3: jspb.Message.getBooleanFieldWithDefault(msg, 12, false),\n proto3SingularMsgs: jspb.Message.getBooleanFieldWithDefault(msg, 21, false),\n enumToString: jspb.Message.getBooleanFieldWithDefault(msg, 13, false),\n fixedLength: jspb.Message.getBooleanFieldWithDefault(msg, 15, false),\n fixedCount: jspb.Message.getBooleanFieldWithDefault(msg, 16, false),\n submsgCallback: jspb.Message.getBooleanFieldWithDefault(msg, 22, false),\n mangleNames: jspb.Message.getFieldWithDefault(msg, 17, 0),\n callbackDatatype: jspb.Message.getFieldWithDefault(msg, 18, \"pb_callback_t\"),\n callbackFunction: jspb.Message.getFieldWithDefault(msg, 19, \"pb_default_field_callback\"),\n descriptorsize: jspb.Message.getFieldWithDefault(msg, 20, 0),\n defaultHas: jspb.Message.getBooleanFieldWithDefault(msg, 23, false),\n includeList: (f = jspb.Message.getRepeatedField(msg, 24)) == null ? undefined : f,\n excludeList: (f = jspb.Message.getRepeatedField(msg, 26)) == null ? undefined : f,\n pb_package: (f = jspb.Message.getField(msg, 25)) == null ? undefined : f,\n typeOverride: (f = jspb.Message.getField(msg, 27)) == null ? undefined : f,\n sortByTag: jspb.Message.getBooleanFieldWithDefault(msg, 28, true)\n };\n\n if (includeInstance) {\n obj.$jspbMessageInstance = msg;\n }\n return obj;\n};\n}\n\n\n/**\n * Deserializes binary data (in protobuf wire format).\n * @param {jspb.ByteSource} bytes The bytes to deserialize.\n * @return {!proto.NanoPBOptions}\n */\nproto.NanoPBOptions.deserializeBinary = function(bytes) {\n var reader = new jspb.BinaryReader(bytes);\n var msg = new proto.NanoPBOptions;\n return proto.NanoPBOptions.deserializeBinaryFromReader(msg, reader);\n};\n\n\n/**\n * Deserializes binary data (in protobuf wire format) from the\n * given reader into the given message object.\n * @param {!proto.NanoPBOptions} msg The message object to deserialize into.\n * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n * @return {!proto.NanoPBOptions}\n */\nproto.NanoPBOptions.deserializeBinaryFromReader = function(msg, reader) {\n while (reader.nextField()) {\n if (reader.isEndGroup()) {\n break;\n }\n var field = reader.getFieldNumber();\n switch (field) {\n case 1:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxSize(value);\n break;\n case 14:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxLength(value);\n break;\n case 2:\n var value = /** @type {number} */ (reader.readInt32());\n msg.setMaxCount(value);\n break;\n case 7:\n var value = /** @type {!proto.IntSize} */ (reader.readEnum());\n msg.setIntSize(value);\n break;\n case 3:\n var value = /** @type {!proto.FieldType} */ (reader.readEnum());\n msg.setType(value);\n break;\n case 4:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setLongNames(value);\n break;\n case 5:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPackedStruct(value);\n break;\n case 10:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setPackedEnum(value);\n break;\n case 6:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSkipMessage(value);\n break;\n case 8:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setNoUnions(value);\n break;\n case 9:\n var value = /** @type {number} */ (reader.readUint32());\n msg.setMsgid(value);\n break;\n case 11:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setAnonymousOneof(value);\n break;\n case 12:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setProto3(value);\n break;\n case 21:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setProto3SingularMsgs(value);\n break;\n case 13:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setEnumToString(value);\n break;\n case 15:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setFixedLength(value);\n break;\n case 16:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setFixedCount(value);\n break;\n case 22:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSubmsgCallback(value);\n break;\n case 17:\n var value = /** @type {!proto.TypenameMangling} */ (reader.readEnum());\n msg.setMangleNames(value);\n break;\n case 18:\n var value = /** @type {string} */ (reader.readString());\n msg.setCallbackDatatype(value);\n break;\n case 19:\n var value = /** @type {string} */ (reader.readString());\n msg.setCallbackFunction(value);\n break;\n case 20:\n var value = /** @type {!proto.DescriptorSize} */ (reader.readEnum());\n msg.setDescriptorsize(value);\n break;\n case 23:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setDefaultHas(value);\n break;\n case 24:\n var value = /** @type {string} */ (reader.readString());\n msg.addInclude(value);\n break;\n case 26:\n var value = /** @type {string} */ (reader.readString());\n msg.addExclude(value);\n break;\n case 25:\n var value = /** @type {string} */ (reader.readString());\n msg.setPackage(value);\n break;\n case 27:\n var value = /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (reader.readEnum());\n msg.setTypeOverride(value);\n break;\n case 28:\n var value = /** @type {boolean} */ (reader.readBool());\n msg.setSortByTag(value);\n break;\n default:\n reader.skipField();\n break;\n }\n }\n return msg;\n};\n\n\n/**\n * Serializes the message to binary data (in protobuf wire format).\n * @return {!Uint8Array}\n */\nproto.NanoPBOptions.prototype.serializeBinary = function() {\n var writer = new jspb.BinaryWriter();\n proto.NanoPBOptions.serializeBinaryToWriter(this, writer);\n return writer.getResultBuffer();\n};\n\n\n/**\n * Serializes the given message to binary data (in protobuf wire\n * format), writing to the given BinaryWriter.\n * @param {!proto.NanoPBOptions} message\n * @param {!jspb.BinaryWriter} writer\n * @suppress {unusedLocalVariables} f is only used for nested messages\n */\nproto.NanoPBOptions.serializeBinaryToWriter = function(message, writer) {\n var f = undefined;\n f = /** @type {number} */ (jspb.Message.getField(message, 1));\n if (f != null) {\n writer.writeInt32(\n 1,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 14));\n if (f != null) {\n writer.writeInt32(\n 14,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 2));\n if (f != null) {\n writer.writeInt32(\n 2,\n f\n );\n }\n f = /** @type {!proto.IntSize} */ (jspb.Message.getField(message, 7));\n if (f != null) {\n writer.writeEnum(\n 7,\n f\n );\n }\n f = /** @type {!proto.FieldType} */ (jspb.Message.getField(message, 3));\n if (f != null) {\n writer.writeEnum(\n 3,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 4));\n if (f != null) {\n writer.writeBool(\n 4,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 5));\n if (f != null) {\n writer.writeBool(\n 5,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 10));\n if (f != null) {\n writer.writeBool(\n 10,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 6));\n if (f != null) {\n writer.writeBool(\n 6,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 8));\n if (f != null) {\n writer.writeBool(\n 8,\n f\n );\n }\n f = /** @type {number} */ (jspb.Message.getField(message, 9));\n if (f != null) {\n writer.writeUint32(\n 9,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 11));\n if (f != null) {\n writer.writeBool(\n 11,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 12));\n if (f != null) {\n writer.writeBool(\n 12,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 21));\n if (f != null) {\n writer.writeBool(\n 21,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 13));\n if (f != null) {\n writer.writeBool(\n 13,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 15));\n if (f != null) {\n writer.writeBool(\n 15,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 16));\n if (f != null) {\n writer.writeBool(\n 16,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 22));\n if (f != null) {\n writer.writeBool(\n 22,\n f\n );\n }\n f = /** @type {!proto.TypenameMangling} */ (jspb.Message.getField(message, 17));\n if (f != null) {\n writer.writeEnum(\n 17,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 18));\n if (f != null) {\n writer.writeString(\n 18,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 19));\n if (f != null) {\n writer.writeString(\n 19,\n f\n );\n }\n f = /** @type {!proto.DescriptorSize} */ (jspb.Message.getField(message, 20));\n if (f != null) {\n writer.writeEnum(\n 20,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 23));\n if (f != null) {\n writer.writeBool(\n 23,\n f\n );\n }\n f = message.getIncludeList();\n if (f.length > 0) {\n writer.writeRepeatedString(\n 24,\n f\n );\n }\n f = message.getExcludeList();\n if (f.length > 0) {\n writer.writeRepeatedString(\n 26,\n f\n );\n }\n f = /** @type {string} */ (jspb.Message.getField(message, 25));\n if (f != null) {\n writer.writeString(\n 25,\n f\n );\n }\n f = /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (jspb.Message.getField(message, 27));\n if (f != null) {\n writer.writeEnum(\n 27,\n f\n );\n }\n f = /** @type {boolean} */ (jspb.Message.getField(message, 28));\n if (f != null) {\n writer.writeBool(\n 28,\n f\n );\n }\n};\n\n\n/**\n * optional int32 max_size = 1;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxSize = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxSize = function(value) {\n return jspb.Message.setField(this, 1, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxSize = function() {\n return jspb.Message.setField(this, 1, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxSize = function() {\n return jspb.Message.getField(this, 1) != null;\n};\n\n\n/**\n * optional int32 max_length = 14;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxLength = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxLength = function(value) {\n return jspb.Message.setField(this, 14, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxLength = function() {\n return jspb.Message.setField(this, 14, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxLength = function() {\n return jspb.Message.getField(this, 14) != null;\n};\n\n\n/**\n * optional int32 max_count = 2;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMaxCount = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMaxCount = function(value) {\n return jspb.Message.setField(this, 2, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMaxCount = function() {\n return jspb.Message.setField(this, 2, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMaxCount = function() {\n return jspb.Message.getField(this, 2) != null;\n};\n\n\n/**\n * optional IntSize int_size = 7;\n * @return {!proto.IntSize}\n */\nproto.NanoPBOptions.prototype.getIntSize = function() {\n return /** @type {!proto.IntSize} */ (jspb.Message.getFieldWithDefault(this, 7, 0));\n};\n\n\n/**\n * @param {!proto.IntSize} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setIntSize = function(value) {\n return jspb.Message.setField(this, 7, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearIntSize = function() {\n return jspb.Message.setField(this, 7, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasIntSize = function() {\n return jspb.Message.getField(this, 7) != null;\n};\n\n\n/**\n * optional FieldType type = 3;\n * @return {!proto.FieldType}\n */\nproto.NanoPBOptions.prototype.getType = function() {\n return /** @type {!proto.FieldType} */ (jspb.Message.getFieldWithDefault(this, 3, 0));\n};\n\n\n/**\n * @param {!proto.FieldType} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setType = function(value) {\n return jspb.Message.setField(this, 3, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearType = function() {\n return jspb.Message.setField(this, 3, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasType = function() {\n return jspb.Message.getField(this, 3) != null;\n};\n\n\n/**\n * optional bool long_names = 4;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getLongNames = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, true));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setLongNames = function(value) {\n return jspb.Message.setField(this, 4, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearLongNames = function() {\n return jspb.Message.setField(this, 4, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasLongNames = function() {\n return jspb.Message.getField(this, 4) != null;\n};\n\n\n/**\n * optional bool packed_struct = 5;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getPackedStruct = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackedStruct = function(value) {\n return jspb.Message.setField(this, 5, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackedStruct = function() {\n return jspb.Message.setField(this, 5, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackedStruct = function() {\n return jspb.Message.getField(this, 5) != null;\n};\n\n\n/**\n * optional bool packed_enum = 10;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getPackedEnum = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 10, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackedEnum = function(value) {\n return jspb.Message.setField(this, 10, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackedEnum = function() {\n return jspb.Message.setField(this, 10, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackedEnum = function() {\n return jspb.Message.getField(this, 10) != null;\n};\n\n\n/**\n * optional bool skip_message = 6;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSkipMessage = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSkipMessage = function(value) {\n return jspb.Message.setField(this, 6, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSkipMessage = function() {\n return jspb.Message.setField(this, 6, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSkipMessage = function() {\n return jspb.Message.getField(this, 6) != null;\n};\n\n\n/**\n * optional bool no_unions = 8;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getNoUnions = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 8, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setNoUnions = function(value) {\n return jspb.Message.setField(this, 8, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearNoUnions = function() {\n return jspb.Message.setField(this, 8, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasNoUnions = function() {\n return jspb.Message.getField(this, 8) != null;\n};\n\n\n/**\n * optional uint32 msgid = 9;\n * @return {number}\n */\nproto.NanoPBOptions.prototype.getMsgid = function() {\n return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 9, 0));\n};\n\n\n/**\n * @param {number} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMsgid = function(value) {\n return jspb.Message.setField(this, 9, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMsgid = function() {\n return jspb.Message.setField(this, 9, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMsgid = function() {\n return jspb.Message.getField(this, 9) != null;\n};\n\n\n/**\n * optional bool anonymous_oneof = 11;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getAnonymousOneof = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 11, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setAnonymousOneof = function(value) {\n return jspb.Message.setField(this, 11, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearAnonymousOneof = function() {\n return jspb.Message.setField(this, 11, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasAnonymousOneof = function() {\n return jspb.Message.getField(this, 11) != null;\n};\n\n\n/**\n * optional bool proto3 = 12;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getProto3 = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 12, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setProto3 = function(value) {\n return jspb.Message.setField(this, 12, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearProto3 = function() {\n return jspb.Message.setField(this, 12, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasProto3 = function() {\n return jspb.Message.getField(this, 12) != null;\n};\n\n\n/**\n * optional bool proto3_singular_msgs = 21;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getProto3SingularMsgs = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 21, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setProto3SingularMsgs = function(value) {\n return jspb.Message.setField(this, 21, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearProto3SingularMsgs = function() {\n return jspb.Message.setField(this, 21, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasProto3SingularMsgs = function() {\n return jspb.Message.getField(this, 21) != null;\n};\n\n\n/**\n * optional bool enum_to_string = 13;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getEnumToString = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 13, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setEnumToString = function(value) {\n return jspb.Message.setField(this, 13, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearEnumToString = function() {\n return jspb.Message.setField(this, 13, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasEnumToString = function() {\n return jspb.Message.getField(this, 13) != null;\n};\n\n\n/**\n * optional bool fixed_length = 15;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getFixedLength = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 15, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setFixedLength = function(value) {\n return jspb.Message.setField(this, 15, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearFixedLength = function() {\n return jspb.Message.setField(this, 15, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasFixedLength = function() {\n return jspb.Message.getField(this, 15) != null;\n};\n\n\n/**\n * optional bool fixed_count = 16;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getFixedCount = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 16, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setFixedCount = function(value) {\n return jspb.Message.setField(this, 16, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearFixedCount = function() {\n return jspb.Message.setField(this, 16, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasFixedCount = function() {\n return jspb.Message.getField(this, 16) != null;\n};\n\n\n/**\n * optional bool submsg_callback = 22;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSubmsgCallback = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 22, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSubmsgCallback = function(value) {\n return jspb.Message.setField(this, 22, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSubmsgCallback = function() {\n return jspb.Message.setField(this, 22, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSubmsgCallback = function() {\n return jspb.Message.getField(this, 22) != null;\n};\n\n\n/**\n * optional TypenameMangling mangle_names = 17;\n * @return {!proto.TypenameMangling}\n */\nproto.NanoPBOptions.prototype.getMangleNames = function() {\n return /** @type {!proto.TypenameMangling} */ (jspb.Message.getFieldWithDefault(this, 17, 0));\n};\n\n\n/**\n * @param {!proto.TypenameMangling} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setMangleNames = function(value) {\n return jspb.Message.setField(this, 17, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearMangleNames = function() {\n return jspb.Message.setField(this, 17, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasMangleNames = function() {\n return jspb.Message.getField(this, 17) != null;\n};\n\n\n/**\n * optional string callback_datatype = 18;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getCallbackDatatype = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 18, \"pb_callback_t\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setCallbackDatatype = function(value) {\n return jspb.Message.setField(this, 18, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearCallbackDatatype = function() {\n return jspb.Message.setField(this, 18, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasCallbackDatatype = function() {\n return jspb.Message.getField(this, 18) != null;\n};\n\n\n/**\n * optional string callback_function = 19;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getCallbackFunction = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 19, \"pb_default_field_callback\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setCallbackFunction = function(value) {\n return jspb.Message.setField(this, 19, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearCallbackFunction = function() {\n return jspb.Message.setField(this, 19, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasCallbackFunction = function() {\n return jspb.Message.getField(this, 19) != null;\n};\n\n\n/**\n * optional DescriptorSize descriptorsize = 20;\n * @return {!proto.DescriptorSize}\n */\nproto.NanoPBOptions.prototype.getDescriptorsize = function() {\n return /** @type {!proto.DescriptorSize} */ (jspb.Message.getFieldWithDefault(this, 20, 0));\n};\n\n\n/**\n * @param {!proto.DescriptorSize} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setDescriptorsize = function(value) {\n return jspb.Message.setField(this, 20, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearDescriptorsize = function() {\n return jspb.Message.setField(this, 20, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasDescriptorsize = function() {\n return jspb.Message.getField(this, 20) != null;\n};\n\n\n/**\n * optional bool default_has = 23;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getDefaultHas = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 23, false));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setDefaultHas = function(value) {\n return jspb.Message.setField(this, 23, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearDefaultHas = function() {\n return jspb.Message.setField(this, 23, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasDefaultHas = function() {\n return jspb.Message.getField(this, 23) != null;\n};\n\n\n/**\n * repeated string include = 24;\n * @return {!Array}\n */\nproto.NanoPBOptions.prototype.getIncludeList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 24));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setIncludeList = function(value) {\n return jspb.Message.setField(this, 24, value || []);\n};\n\n\n/**\n * @param {string} value\n * @param {number=} opt_index\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.addInclude = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 24, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearIncludeList = function() {\n return this.setIncludeList([]);\n};\n\n\n/**\n * repeated string exclude = 26;\n * @return {!Array}\n */\nproto.NanoPBOptions.prototype.getExcludeList = function() {\n return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 26));\n};\n\n\n/**\n * @param {!Array} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setExcludeList = function(value) {\n return jspb.Message.setField(this, 26, value || []);\n};\n\n\n/**\n * @param {string} value\n * @param {number=} opt_index\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.addExclude = function(value, opt_index) {\n return jspb.Message.addToRepeatedField(this, 26, value, opt_index);\n};\n\n\n/**\n * Clears the list making it empty but non-null.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearExcludeList = function() {\n return this.setExcludeList([]);\n};\n\n\n/**\n * optional string package = 25;\n * @return {string}\n */\nproto.NanoPBOptions.prototype.getPackage = function() {\n return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 25, \"\"));\n};\n\n\n/**\n * @param {string} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setPackage = function(value) {\n return jspb.Message.setField(this, 25, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearPackage = function() {\n return jspb.Message.setField(this, 25, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasPackage = function() {\n return jspb.Message.getField(this, 25) != null;\n};\n\n\n/**\n * optional google.protobuf.FieldDescriptorProto.Type type_override = 27;\n * @return {!proto.google.protobuf.FieldDescriptorProto.Type}\n */\nproto.NanoPBOptions.prototype.getTypeOverride = function() {\n return /** @type {!proto.google.protobuf.FieldDescriptorProto.Type} */ (jspb.Message.getFieldWithDefault(this, 27, 1));\n};\n\n\n/**\n * @param {!proto.google.protobuf.FieldDescriptorProto.Type} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setTypeOverride = function(value) {\n return jspb.Message.setField(this, 27, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearTypeOverride = function() {\n return jspb.Message.setField(this, 27, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasTypeOverride = function() {\n return jspb.Message.getField(this, 27) != null;\n};\n\n\n/**\n * optional bool sort_by_tag = 28;\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.getSortByTag = function() {\n return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 28, true));\n};\n\n\n/**\n * @param {boolean} value\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.setSortByTag = function(value) {\n return jspb.Message.setField(this, 28, value);\n};\n\n\n/**\n * Clears the field making it undefined.\n * @return {!proto.NanoPBOptions} returns this\n */\nproto.NanoPBOptions.prototype.clearSortByTag = function() {\n return jspb.Message.setField(this, 28, undefined);\n};\n\n\n/**\n * Returns whether this field is set.\n * @return {boolean}\n */\nproto.NanoPBOptions.prototype.hasSortByTag = function() {\n return jspb.Message.getField(this, 28) != null;\n};\n\n\n/**\n * @enum {number}\n */\nproto.FieldType = {\n FT_DEFAULT: 0,\n FT_CALLBACK: 1,\n FT_POINTER: 4,\n FT_STATIC: 2,\n FT_IGNORE: 3,\n FT_INLINE: 5\n};\n\n/**\n * @enum {number}\n */\nproto.IntSize = {\n IS_DEFAULT: 0,\n IS_8: 8,\n IS_16: 16,\n IS_32: 32,\n IS_64: 64\n};\n\n/**\n * @enum {number}\n */\nproto.TypenameMangling = {\n M_NONE: 0,\n M_STRIP_PACKAGE: 1,\n M_FLATTEN: 2,\n M_PACKAGE_INITIALS: 3\n};\n\n/**\n * @enum {number}\n */\nproto.DescriptorSize = {\n DS_AUTO: 0,\n DS_1: 1,\n DS_2: 2,\n DS_4: 4,\n DS_8: 8\n};\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbFileopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbFileopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbFileopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FileOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbFileopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FileOptions.extensions[1010] = proto.nanopbFileopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbMsgopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbMsgopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbMsgopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.MessageOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbMsgopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.MessageOptions.extensions[1010] = proto.nanopbMsgopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopbEnumopt`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopbEnumopt = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopbEnumopt: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.EnumOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopbEnumopt,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.EnumOptions.extensions[1010] = proto.nanopbEnumopt;\n\n\n/**\n * A tuple of {field number, class constructor} for the extension\n * field named `nanopb`.\n * @type {!jspb.ExtensionFieldInfo}\n */\nproto.nanopb = new jspb.ExtensionFieldInfo(\n 1010,\n {nanopb: 0},\n proto.NanoPBOptions,\n /** @type {?function((boolean|undefined),!jspb.Message=): !Object} */ (\n proto.NanoPBOptions.toObject),\n 0);\n\ngoogle_protobuf_descriptor_pb.FieldOptions.extensionsBinary[1010] = new jspb.ExtensionFieldBinaryInfo(\n proto.nanopb,\n jspb.BinaryReader.prototype.readMessage,\n jspb.BinaryWriter.prototype.writeMessage,\n proto.NanoPBOptions.serializeBinaryToWriter,\n proto.NanoPBOptions.deserializeBinaryFromReader,\n false);\n// This registers the extension field with the extended class, so that\n// toObject() will function correctly.\ngoogle_protobuf_descriptor_pb.FieldOptions.extensions[1010] = proto.nanopb;\n\ngoog.object.extend(exports, proto);\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nrequire(\"bootstrap\");\r\nrequire(\"./sass/main.scss\");\r\nrequire(\"./assets/images/favicon-32x32.png\");\r\nrequire(\"./js/custom.ts\");\r\n","\"use strict\";\r\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n}));\r\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n});\r\nvar __importStar = (this && this.__importStar) || function (mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n};\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __importDefault = (this && this.__importDefault) || function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n};\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar he = require('he');\r\n// var Promise = require('es6-promise').Promise;\r\n// @ts-ignore\r\nconst js_cookie_1 = __importDefault(require(\"js-cookie\"));\r\nconst c = __importStar(require(\"./proto/configuration_pb.js\"));\r\nconst bootstrap = __importStar(require(\"bootstrap\"));\r\nconsole.log(c);\r\n// Function to reset a StatusObject\r\nfunction resetStatusObject() {\r\n return {\r\n netmask: undefined,\r\n ip: undefined,\r\n ssid: undefined,\r\n urc: undefined,\r\n rssi: undefined,\r\n gw: undefined,\r\n bt_status: undefined,\r\n bt_sub_status: undefined,\r\n loaded: undefined,\r\n total: undefined,\r\n ota_pct: undefined,\r\n ota_dsc: undefined,\r\n recovery: undefined\r\n };\r\n}\r\nfunction resetNetworkConnection() {\r\n return {\r\n auth: undefined,\r\n pwd: undefined,\r\n dhcpname: undefined,\r\n Action: undefined,\r\n ip: undefined,\r\n ssid: undefined,\r\n rssi: undefined,\r\n gw: undefined,\r\n netmask: undefined,\r\n urc: 0\r\n };\r\n}\r\nwindow.hideSurrounding = function (obj) {\r\n $(obj).parent().parent().hide();\r\n};\r\nfunction hFlash() {\r\n // reset file upload selection if any;\r\n $('#flashfilename').val = null;\r\n flashState.StartOTA();\r\n}\r\nwindow.hFlash = function () {\r\n hFlash();\r\n};\r\nfunction handleReboot(link) {\r\n if (link == 'reboot_ota') {\r\n $('#reboot_ota_nav').removeClass('active').prop(\"disabled\", true);\r\n delayReboot(500, '', 'reboot_ota');\r\n }\r\n else {\r\n $('#reboot_nav').removeClass('active');\r\n delayReboot(500, '', link);\r\n }\r\n}\r\nwindow.handleReboot = function (link) {\r\n handleReboot(link);\r\n};\r\nObject.assign(String.prototype, {\r\n format(...args) {\r\n return this.replace(/{(\\d+)}/g, function (match, number) {\r\n const index = parseInt(number, 10); // Convert string to number\r\n return typeof args[index] !== 'undefined' ? args[index] : match;\r\n });\r\n },\r\n});\r\nObject.assign(String.prototype, {\r\n encodeHTML() {\r\n return he.encode(this).replace(/\\n/g, '
');\r\n },\r\n});\r\nObject.assign(Date.prototype, {\r\n toLocalShort() {\r\n const opt = { dateStyle: 'short', timeStyle: 'short' };\r\n return this.toLocaleString(undefined, opt);\r\n },\r\n});\r\nfunction get_control_option_value(obj) {\r\n let ctrl, id, val, opt;\r\n if (typeof (obj) === 'string') {\r\n id = obj;\r\n ctrl = $(`#${id}`);\r\n }\r\n else {\r\n id = $(obj).attr('id');\r\n ctrl = $(obj);\r\n }\r\n if (ctrl.attr('type') === 'checkbox') {\r\n opt = ctrl.prop('checked') ? id.replace('cmd_opt_', '') : '';\r\n val = true;\r\n }\r\n else {\r\n opt = id.replace('cmd_opt_', '');\r\n val = ctrl.val();\r\n if (typeof val === 'string') {\r\n val = `${val.includes(\" \") ? '\"' : ''}${val}${val.includes(\" \") ? '\"' : ''}`;\r\n }\r\n else if (typeof val !== 'number') {\r\n val = val.toString();\r\n }\r\n }\r\n return { opt, val };\r\n}\r\nfunction handleNVSVisible() {\r\n let nvs_previous_checked = isEnabled(js_cookie_1.default.get(\"show-nvs\"));\r\n const checkBoxElement = $('input#show-nvs')[0];\r\n checkBoxElement.checked = nvs_previous_checked;\r\n if (checkBoxElement.checked || recovery) {\r\n $('*[href*=\"-nvs\"]').show();\r\n }\r\n else {\r\n $('*[href*=\"-nvs\"]').hide();\r\n }\r\n}\r\nfunction concatenateOptions(options) {\r\n let commandLine = ' ';\r\n for (const [option, value] of Object.entries(options)) {\r\n if (option !== 'n' && option !== 'o') {\r\n commandLine += `-${option} `;\r\n if (value !== true) {\r\n commandLine += `${value} `;\r\n }\r\n }\r\n }\r\n return commandLine;\r\n}\r\nfunction isEnabled(val) {\r\n return val != undefined && typeof val === 'string' && val.match(\"[Yy1]\").length > 0;\r\n}\r\nvar NVSType;\r\n(function (NVSType) {\r\n NVSType[NVSType[\"NVS_TYPE_U8\"] = 1] = \"NVS_TYPE_U8\";\r\n NVSType[NVSType[\"NVS_TYPE_I8\"] = 17] = \"NVS_TYPE_I8\";\r\n NVSType[NVSType[\"NVS_TYPE_U16\"] = 2] = \"NVS_TYPE_U16\";\r\n NVSType[NVSType[\"NVS_TYPE_I16\"] = 18] = \"NVS_TYPE_I16\";\r\n NVSType[NVSType[\"NVS_TYPE_U32\"] = 4] = \"NVS_TYPE_U32\";\r\n NVSType[NVSType[\"NVS_TYPE_I32\"] = 20] = \"NVS_TYPE_I32\";\r\n NVSType[NVSType[\"NVS_TYPE_U64\"] = 8] = \"NVS_TYPE_U64\";\r\n NVSType[NVSType[\"NVS_TYPE_I64\"] = 24] = \"NVS_TYPE_I64\";\r\n NVSType[NVSType[\"NVS_TYPE_STR\"] = 33] = \"NVS_TYPE_STR\";\r\n NVSType[NVSType[\"NVS_TYPE_BLOB\"] = 66] = \"NVS_TYPE_BLOB\";\r\n NVSType[NVSType[\"NVS_TYPE_ANY\"] = 255] = \"NVS_TYPE_ANY\";\r\n})(NVSType || (NVSType = {}));\r\n;\r\nconst btIcons = {\r\n bt_playing: { label: '', icon: 'media_bluetooth_on' },\r\n bt_disconnected: { label: '', icon: 'media_bluetooth_off' },\r\n bt_neutral: { label: '', icon: 'bluetooth' },\r\n bt_connecting: { label: '', icon: 'bluetooth_searching' },\r\n bt_connected: { label: '', icon: 'bluetooth_connected' },\r\n bt_disabled: { label: '', icon: 'bluetooth_disabled' },\r\n play_arrow: { label: '', icon: 'play_circle_filled' },\r\n pause: { label: '', icon: 'pause_circle' },\r\n stop: { label: '', icon: 'stop_circle' },\r\n '': { label: '', icon: '' }\r\n};\r\nconst batIcons = [\r\n { icon: \"battery_0_bar\", label: '▪', ranges: [{ f: 5.8, t: 6.8 }, { f: 8.8, t: 10.2 }] },\r\n { icon: \"battery_2_bar\", label: '▪▪', ranges: [{ f: 6.8, t: 7.4 }, { f: 10.2, t: 11.1 }] },\r\n { icon: \"battery_3_bar\", label: '▪▪▪', ranges: [{ f: 7.4, t: 7.5 }, { f: 11.1, t: 11.25 }] },\r\n { icon: \"battery_4_bar\", label: '▪▪▪▪', ranges: [{ f: 7.5, t: 7.8 }, { f: 11.25, t: 11.7 }] }\r\n];\r\nconst btStateIcons = [\r\n { desc: 'Idle', sub: ['bt_neutral'] },\r\n { desc: 'Discovering', sub: ['bt_connecting'] },\r\n { desc: 'Discovered', sub: ['bt_connecting'] },\r\n { desc: 'Unconnected', sub: ['bt_disconnected'] },\r\n { desc: 'Connecting', sub: ['bt_connecting'] },\r\n {\r\n desc: 'Connected',\r\n sub: ['bt_connected', 'play_arrow', 'bt_playing', 'pause', 'stop'],\r\n },\r\n { desc: 'Disconnecting', sub: ['bt_disconnected'] },\r\n];\r\nconst connectReturnCode = {\r\n OK: 0,\r\n FAIL: 1,\r\n DISC: 2,\r\n LOST: 3,\r\n RESTORE: 4,\r\n ETH: 5\r\n};\r\nconst taskStates = [\r\n 'eRunning',\r\n /*! < A task is querying the state of itself, so must be running. */\r\n 'eReady',\r\n /*! < The task being queried is in a read or pending ready list. */\r\n 'eBlocked',\r\n /*! < The task being queried is in the Blocked state. */\r\n 'eSuspended',\r\n /*! < The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */\r\n 'eDeleted'\r\n];\r\nlet flashState = {\r\n NONE: 0,\r\n REBOOT_TO_RECOVERY: 2,\r\n SET_FWURL: 5,\r\n FLASHING: 6,\r\n DONE: 7,\r\n UPLOADING: 8,\r\n ERROR: 9,\r\n UPLOADCOMPLETE: 10,\r\n _state: -1,\r\n olderRecovery: false,\r\n statusText: '',\r\n flashURL: '',\r\n flashFileName: '',\r\n statusPercent: 0,\r\n Completed: false,\r\n recovery: false,\r\n prevRecovery: false,\r\n updateModal: new bootstrap.Modal(document.getElementById('otadiv'), {}),\r\n reset: function () {\r\n this.olderRecovery = false;\r\n this.statusText = '';\r\n this.statusPercent = -1;\r\n this.flashURL = '';\r\n this.flashFileName = undefined;\r\n this.UpdateProgress();\r\n $('#rTable tr.release').removeClass('table-success table-warning');\r\n $('.flact').prop('disabled', false);\r\n $('#flashfilename')[0].value = null;\r\n $('#fw-url-input')[0].value = null;\r\n if (!this.isStateError()) {\r\n $('span#flash-status').html('');\r\n $('#fwProgressLabel').parent().removeClass('bg-danger');\r\n }\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n isStateUploadComplete: function () {\r\n return this._state == this.UPLOADCOMPLETE;\r\n },\r\n isStateError: function () {\r\n return this._state == this.ERROR;\r\n },\r\n isStateNone: function () {\r\n return this._state == this.NONE;\r\n },\r\n isStateRebootRecovery: function () {\r\n return this._state == this.REBOOT_TO_RECOVERY;\r\n },\r\n isStateSetUrl: function () {\r\n return this._state == this.SET_FWURL;\r\n },\r\n isStateFlashing: function () {\r\n return this._state == this.FLASHING;\r\n },\r\n isStateDone: function () {\r\n return this._state == this.DONE;\r\n },\r\n isStateUploading: function () {\r\n return this._state == this.UPLOADING;\r\n },\r\n init: function () {\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n SetStateError: function () {\r\n this._state = this.ERROR;\r\n $('#fwProgressLabel').parent().addClass('bg-danger');\r\n return this;\r\n },\r\n SetStateNone: function () {\r\n this._state = this.NONE;\r\n return this;\r\n },\r\n SetStateRebootRecovery: function () {\r\n this._state = this.REBOOT_TO_RECOVERY;\r\n // Reboot system to recovery mode\r\n this.SetStatusText('Starting recovery mode.');\r\n $.ajax({\r\n url: '/recovery.json',\r\n context: this,\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n var _a;\r\n this.setOTAError(`Unexpected error while trying to restart to recovery. (status=${(_a = xhr.status) !== null && _a !== void 0 ? _a : ''}, error=${thrownError !== null && thrownError !== void 0 ? thrownError : ''} ) `);\r\n },\r\n complete: function (response) {\r\n this.SetStatusText('Waiting for system to boot.');\r\n },\r\n });\r\n return this;\r\n },\r\n SetStateSetUrl: function () {\r\n this._state = this.SET_FWURL;\r\n this.statusText = 'Sending firmware download location.';\r\n let confData = {\r\n fwurl: {\r\n value: this.flashURL,\r\n type: 33,\r\n }\r\n };\r\n post_config(confData);\r\n return this;\r\n },\r\n SetStateFlashing: function () {\r\n this._state = this.FLASHING;\r\n return this;\r\n },\r\n SetStateDone: function () {\r\n this._state = this.DONE;\r\n this.reset();\r\n return this;\r\n },\r\n SetStateUploading: function () {\r\n this._state = this.UPLOADING;\r\n return this.SetStatusText('Sending file to device.');\r\n },\r\n SetStateUploadComplete: function () {\r\n this._state = this.UPLOADCOMPLETE;\r\n return this;\r\n },\r\n isFlashExecuting: function () {\r\n return true === (this._state != this.UPLOADING && (this.statusText !== '' || this.statusPercent >= 0));\r\n },\r\n toString: function () {\r\n let keys = Object.keys(this);\r\n return keys.find(x => this[x] === this._state);\r\n },\r\n setOTATargets: function () {\r\n this.flashURL = '';\r\n this.flashFileName = '';\r\n this.flashURL = $('#fw-url-input').val();\r\n let fileInputctrl = $('#flashfilename')[0];\r\n let fileInput = fileInputctrl.files;\r\n if (fileInput.length > 0) {\r\n this.flashFileName = fileInput[0];\r\n }\r\n if (this.flashFileName.length == 0 && this.flashURL.length == 0) {\r\n this.setOTAError('Invalid url or file. Cannot start OTA');\r\n }\r\n return this;\r\n },\r\n setOTAError: function (message) {\r\n this.SetStateError().SetStatusPercent(0).SetStatusText(message).reset();\r\n return this;\r\n },\r\n ShowDialog: function () {\r\n if (!this.isStateNone()) {\r\n this.updateModal.show();\r\n $('.flact').prop('disabled', true);\r\n }\r\n return this;\r\n },\r\n SetStatusPercent: function (pct) {\r\n var pctChanged = (this.statusPercent != pct);\r\n this.statusPercent = pct;\r\n if (pctChanged) {\r\n if (!this.isStateUploading() && !this.isStateFlashing()) {\r\n this.SetStateFlashing();\r\n }\r\n if (pct == 100) {\r\n if (this.isStateFlashing()) {\r\n this.SetStateDone();\r\n }\r\n else if (this.isStateUploading()) {\r\n this.statusPercent = 0;\r\n this.SetStateFlashing();\r\n }\r\n }\r\n this.UpdateProgress().ShowDialog();\r\n }\r\n return this;\r\n },\r\n SetStatusText: function (txt) {\r\n var changed = (this.statusText != txt);\r\n this.statusText = txt;\r\n if (changed) {\r\n $('span#flash-status').html(this.statusText);\r\n this.ShowDialog();\r\n }\r\n return this;\r\n },\r\n UpdateProgress: function () {\r\n $('.progress-bar')\r\n .css('width', this.statusPercent + '%')\r\n .attr('aria-valuenow', this.statusPercent)\r\n .text(this.statusPercent + '%');\r\n $('.progress-bar').html((this.isStateDone() ? 100 : this.statusPercent) + '%');\r\n return this;\r\n },\r\n StartOTA: function () {\r\n this.logEvent(this.StartOTA.name);\r\n $('#fwProgressLabel').parent().removeClass('bg-danger');\r\n this.setOTATargets();\r\n if (this.isStateError()) {\r\n return this;\r\n }\r\n if (!recovery) {\r\n this.SetStateRebootRecovery();\r\n }\r\n else {\r\n this.SetStateFlashing().TargetReadyStartOTA();\r\n }\r\n return this;\r\n },\r\n UploadLocalFile: function () {\r\n this.SetStateUploading();\r\n const xhttp = new XMLHttpRequest();\r\n var boundHandleUploadProgressEvent = this.HandleUploadProgressEvent.bind(this);\r\n var boundsetOTAError = this.setOTAError.bind(this);\r\n xhttp.upload.addEventListener(\"progress\", boundHandleUploadProgressEvent, false);\r\n xhttp.onreadystatechange = function () {\r\n if (xhttp.readyState === 4) {\r\n if (xhttp.status === 0 || xhttp.status === 404) {\r\n boundsetOTAError(`Upload Failed. Recovery version might not support uploading. Please use web update instead.`);\r\n }\r\n }\r\n };\r\n xhttp.open('POST', '/flash.json', true);\r\n xhttp.send(this.flashFileName);\r\n },\r\n TargetReadyStartOTA: function () {\r\n if (recovery && this.prevRecovery && !this.isStateRebootRecovery() && !this.isStateFlashing()) {\r\n // this should only execute once, while being in a valid state\r\n return this;\r\n }\r\n this.logEvent(this.TargetReadyStartOTA.name);\r\n if (!recovery) {\r\n console.error('Event TargetReadyStartOTA fired in the wrong mode ');\r\n return this;\r\n }\r\n this.prevRecovery = true;\r\n if (this.flashFileName !== '') {\r\n this.UploadLocalFile();\r\n }\r\n else if (this.flashURL != '') {\r\n this.SetStateSetUrl();\r\n }\r\n else {\r\n this.setOTAError('Invalid URL or file name while trying to start the OTa process');\r\n }\r\n },\r\n HandleUploadProgressEvent: function (data) {\r\n this.logEvent(this.HandleUploadProgressEvent.name);\r\n this.SetStateUploading().SetStatusPercent(Math.round(data.loaded / data.total * 100)).SetStatusText('Uploading file to device');\r\n },\r\n EventTargetStatus: function (data) {\r\n var _a, _b;\r\n if (!this.isStateNone()) {\r\n this.logEvent(this.EventTargetStatus.name);\r\n }\r\n if ((_a = data.ota_pct) !== null && _a !== void 0 ? _a : -1 >= 0) {\r\n this.olderRecovery = true;\r\n this.SetStatusPercent(data.ota_pct);\r\n }\r\n if (((_b = data.ota_dsc) !== null && _b !== void 0 ? _b : '') != '') {\r\n this.olderRecovery = true;\r\n this.SetStatusText(data.ota_dsc);\r\n }\r\n if (data.recovery != undefined) {\r\n this.recovery = data.recovery === 1 ? true : false;\r\n }\r\n if (this.isStateRebootRecovery() && this.recovery) {\r\n this.TargetReadyStartOTA();\r\n }\r\n },\r\n EventOTAMessageClass: function (data) {\r\n this.logEvent(this.EventOTAMessageClass.name);\r\n var otaData = JSON.parse(data);\r\n this.SetStatusPercent(otaData.ota_pct).SetStatusText(otaData.ota_dsc);\r\n },\r\n logEvent: function (fun) {\r\n console.log(`${fun}, flash state ${this.toString()}, recovery: ${this.recovery}, ota pct: ${this.statusPercent}, ota desc: ${this.statusText}`);\r\n }\r\n};\r\nlet presetsloaded = false;\r\nlet is_i2c_locked = false;\r\nlet statusInterval = 2000;\r\nlet messageInterval = 2500;\r\nfunction post_config(data) {\r\n let confPayload = {\r\n timestamp: Date.now(),\r\n config: data\r\n };\r\n $.ajax({\r\n url: '/config.json',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(confPayload),\r\n error: handleExceptionResponse,\r\n });\r\n}\r\nfunction parseSqueezeliteCommandLine(commandLine) {\r\n const options = {};\r\n let output, name;\r\n let otherValues = '';\r\n const argRegex = /(\"[^\"]+\"|'[^']+'|\\S+)/g;\r\n const args = commandLine.match(argRegex) || [];\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n if (arg.startsWith('-')) {\r\n const option = arg.slice(1);\r\n if (option === '') {\r\n otherValues += args.slice(i).join(' ');\r\n break;\r\n }\r\n let value = \"\";\r\n if (i + 1 < args.length && !args[i + 1].startsWith('-')) {\r\n value = args[i + 1].replace(/\"/g, '').replace(/'/g, '');\r\n i++;\r\n }\r\n options[option] = value;\r\n }\r\n else {\r\n otherValues += arg + ' ';\r\n }\r\n i++;\r\n }\r\n otherValues = otherValues.trim();\r\n output = getOutput(options);\r\n name = getName(options);\r\n let otherOptions = { btname: null, n: null };\r\n // Assign 'o' and 'n' options to otherOptions if present\r\n if (options.o && output.toUpperCase() === 'BT') {\r\n let temp = parseSqueezeliteCommandLine(options.o);\r\n if (temp.name) {\r\n otherOptions.btname = temp.name;\r\n }\r\n delete options.o;\r\n }\r\n if (options.n) {\r\n otherOptions.n = options.n;\r\n delete options.n;\r\n }\r\n return { name, output, options, otherValues, otherOptions };\r\n}\r\nfunction getOutput(options) {\r\n let output;\r\n if (options.o) {\r\n output = options.o.replace(/\"/g, '').replace(/'/g, '');\r\n /* set output as the first alphanumerical word in the command line */\r\n if (output.indexOf(' ') > 0) {\r\n output = output.substring(0, output.indexOf(' '));\r\n }\r\n }\r\n return output;\r\n}\r\nfunction getName(options) {\r\n let name;\r\n /* if n option present, assign to name variable */\r\n if (options.n) {\r\n name = options.n.replace(/\"/g, '').replace(/'/g, '');\r\n }\r\n return name;\r\n}\r\nfunction isConnected() {\r\n return ConnectedTo.hasOwnProperty('ip') && ConnectedTo.ip != '0.0.0.0' && ConnectedTo.ip != '';\r\n}\r\nfunction getIcon(icons) {\r\n return isConnected() ? icons.icon : icons.label;\r\n}\r\nfunction handlebtstate(data) {\r\n var _a;\r\n let icon = { label: '', icon: '' };\r\n let tt = '';\r\n if (data.bt_status !== undefined && data.bt_sub_status !== undefined) {\r\n const iconIndex = (_a = btStateIcons[data.bt_status]) === null || _a === void 0 ? void 0 : _a.sub[data.bt_sub_status];\r\n if (iconIndex) {\r\n icon = btIcons[iconIndex];\r\n tt = btStateIcons[data.bt_status].desc;\r\n }\r\n else {\r\n icon = btIcons.bt_connected;\r\n tt = 'Output status';\r\n }\r\n }\r\n $('#o_type').attr('title', tt);\r\n $('#o_bt').html(isConnected() ? icon.label : icon.icon); // Note: Assuming `isConnected()` is defined elsewhere.\r\n}\r\nfunction handleTemplateTypeRadio(outtype) {\r\n $('#o_type').children('span').css({ display: 'none' });\r\n let changed = false;\r\n if (outtype !== output) {\r\n changed = true;\r\n output = outtype;\r\n }\r\n $('#' + output).prop('checked', true);\r\n $('#o_' + output).css({ display: 'inline' });\r\n if (changed) {\r\n Object.entries(commandDefaults[output]).forEach(([key, value]) => {\r\n $(`#cmd_opt_${key}`).val(value);\r\n });\r\n }\r\n}\r\nfunction handleExceptionResponse(xhr, _ajaxOptions, thrownError) {\r\n console.log(xhr.status);\r\n console.log(thrownError);\r\n if (thrownError !== '') {\r\n showLocalMessage(thrownError, 'MESSAGING_ERROR');\r\n }\r\n}\r\nfunction HideCmdMessage(cmdname) {\r\n $('#toast_' + cmdname)\r\n .removeClass('table-success')\r\n .removeClass('table-warning')\r\n .removeClass('table-danger')\r\n .addClass('table-success')\r\n .removeClass('show');\r\n $('#msg_' + cmdname).html('');\r\n}\r\nfunction showCmdMessage(cmdname, msgtype, msgtext, append = false) {\r\n let color = 'table-success';\r\n if (msgtype === 'MESSAGING_WARNING') {\r\n color = 'table-warning';\r\n }\r\n else if (msgtype === 'MESSAGING_ERROR') {\r\n color = 'table-danger';\r\n }\r\n $('#toast_' + cmdname)\r\n .removeClass('table-success')\r\n .removeClass('table-warning')\r\n .removeClass('table-danger')\r\n .addClass(color)\r\n .addClass('show');\r\n let escapedtext = msgtext\r\n .substring(0, msgtext.length - 1)\r\n .encodeHTML()\r\n .replace(/\\n/g, '
');\r\n escapedtext =\r\n ($('#msg_' + cmdname).html().length > 0 && append\r\n ? $('#msg_' + cmdname).html() + '
'\r\n : '') + escapedtext;\r\n $('#msg_' + cmdname).html(escapedtext);\r\n}\r\nlet releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';\r\nlet recovery = false;\r\nlet messagesHeld = false;\r\nlet commandBTSinkName = '';\r\nconst commandHeader = 'squeezelite ';\r\nconst commandDefaults = {\r\n i2s: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"96000\", o: \"I2S\" },\r\n spdif: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"48000\", o: \"SPDIF\" },\r\n bt: { b: \"500:2000\", C: \"30\", W: \"\", Z: \"44100\", o: \"BT\" },\r\n};\r\nlet validOptions = {\r\n codecs: ['flac', 'pcm', 'mp3', 'ogg', 'aac', 'wma', 'alac', 'dsd', 'mad', 'mpg']\r\n};\r\n//let blockFlashButton = false;\r\nlet apList = null;\r\n//let selectedSSID = '';\r\n//let checkStatusInterval = null;\r\nlet messagecount = 0;\r\nlet messageseverity = 'MESSAGING_INFO';\r\nlet SystemConfig;\r\nlet LastCommandsState = NaN;\r\nvar output = '';\r\nlet hostName = '';\r\nlet versionName = 'Squeezelite-ESP32';\r\nlet prevmessage = '';\r\nlet project_name = versionName;\r\nlet depth = 16;\r\nlet board_model = '';\r\nlet platform_name = versionName;\r\nlet preset_name = '';\r\nlet btSinkNamesOptSel = '#cfg-audio-bt_source-sink_name';\r\nlet ConnectedTo;\r\nlet ConnectingToSSID;\r\nlet lmsBaseUrl = \"\";\r\nlet prevLMSIP = '';\r\nconst ConnectingToActions = {\r\n 'CONN': 0, 'MAN': 1, 'STS': 2,\r\n};\r\nfunction delay(promise, duration) {\r\n return new Promise((resolve, reject) => {\r\n promise.then(value => setTimeout(() => resolve(value), duration), reason => setTimeout(() => reject(reason), duration));\r\n });\r\n}\r\nfunction getConfigJson(slimMode) {\r\n const config = {};\r\n $('input.nvs').each(function (_index, element) {\r\n const entry = element;\r\n const nvsTypeAttr = entry.attributes.getNamedItem('nvs_type');\r\n if (!slimMode && nvsTypeAttr) {\r\n const nvsType = parseInt(nvsTypeAttr.value, 10);\r\n if (entry.id !== '') {\r\n const value = (nvsType <= NVSType.NVS_TYPE_I64) ? parseInt(entry.value, 10) : entry.value;\r\n config[entry.id] = {\r\n value: value,\r\n type: nvsType,\r\n };\r\n }\r\n }\r\n else {\r\n if (entry.id !== '') {\r\n config[entry.id] = entry.value;\r\n }\r\n }\r\n });\r\n // In the following, we assume that `#nvs-new-key` and `#nvs-new-value`\r\n // correspond to input elements and thus their values are always strings.\r\n const key = $('#nvs-new-key').val();\r\n const val = $('#nvs-new-value').val();\r\n if (key && key !== '') {\r\n if (!slimMode) {\r\n config[key] = {\r\n value: val,\r\n type: NVSType.NVS_TYPE_I8, // Assuming a default type here\r\n };\r\n }\r\n else {\r\n config[key] = val;\r\n }\r\n }\r\n return config;\r\n}\r\nfunction handleHWPreset(allfields, reboot) {\r\n const selJson = JSON.parse(allfields[0].value);\r\n const cmd = allfields[0].getAttribute(\"cmdname\");\r\n console.log(`selected model: ${selJson.name}`);\r\n let confPayload = {\r\n timestamp: Date.now(),\r\n config: { model_config: { value: selJson.name, type: 33 } } // Assuming 33 is some sort of default type\r\n };\r\n for (const [name, value] of Object.entries(selJson.config)) {\r\n const storedval = (typeof value === 'string' || value instanceof String) ? value : JSON.stringify(value);\r\n confPayload.config[name] = {\r\n value: storedval.toString(),\r\n type: NVSType.NVS_TYPE_STR,\r\n };\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Setting ${name}=${storedval} `, true);\r\n }\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Committing `, true);\r\n $.ajax({\r\n url: '/config.json',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(confPayload),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, _ajaxOptions, thrownError);\r\n showCmdMessage(cmd, 'MESSAGING_ERROR', `Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status} `, true);\r\n },\r\n success: function (response) {\r\n showCmdMessage(cmd, 'MESSAGING_INFO', `Saving complete `, true);\r\n console.log(response);\r\n if (reboot) {\r\n delayReboot(2500, cmd);\r\n }\r\n },\r\n });\r\n}\r\n// pull json file from https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/b462691f69e2ad31ac95c547af6ec97afb0f53db/squeezelite-esp32-presets.json and\r\nfunction loadPresets() {\r\n if ($(\"#cfg-hw-preset-model_config\").length == 0)\r\n return;\r\n if (presetsloaded)\r\n return;\r\n presetsloaded = true;\r\n $('#cfg-hw-preset-model_config').html('');\r\n $.getJSON('https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/', { _: new Date().getTime() }, function (data) {\r\n $.each(data, function (key, val) {\r\n $('#cfg-hw-preset-model_config').append(``);\r\n if (preset_name !== '' && preset_name == val.name) {\r\n $('#cfg-hw-preset-model_config').val(preset_name);\r\n }\r\n });\r\n if (preset_name !== '') {\r\n $('#prev_preset').show().val(preset_name);\r\n }\r\n }).fail(function (jqxhr, textStatus, error) {\r\n const err = textStatus + ', ' + error;\r\n console.log('Request Failed: ' + err);\r\n });\r\n}\r\nfunction delayReboot(duration, cmdname, ota = 'reboot') {\r\n const url = `/${ota}.json`;\r\n $('tbody#tasks').empty();\r\n $('#tasks_sect').css('visibility', 'collapse');\r\n delay(Promise.resolve({ cmdname: cmdname, url: url }), duration)\r\n .then(function (data) {\r\n // Your existing logic here\r\n console.log('now triggering reboot');\r\n $(\"button[onclick*='handleReboot']\").addClass('rebooting');\r\n $.ajax({\r\n // Your existing AJAX call setup here\r\n complete: function () {\r\n console.log('reboot call completed');\r\n delay(Promise.resolve(data), 6000)\r\n .then(function (rdata) {\r\n // Your existing logic here\r\n });\r\n },\r\n });\r\n });\r\n}\r\nfunction saveAutoexec1(apply) {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Saving.\\n', false);\r\n let commandLine = `${commandHeader} -o ${output} `;\r\n $('.sqcmd').each(function () {\r\n let { opt, val } = get_control_option_value($(this));\r\n if ((opt && opt.length > 0) && typeof (val) == 'boolean' || typeof (val) === 'string' && val.length > 0) {\r\n const optStr = opt === ':' ? opt : (` -${opt} `);\r\n val = typeof (val) == 'boolean' ? '' : val;\r\n commandLine += `${optStr} ${val}`;\r\n }\r\n });\r\n const resample = $('#cmd_opt_R input[name=resample]:checked');\r\n if (resample.length > 0 && resample.attr('suffix') !== '') {\r\n commandLine += resample.attr('suffix');\r\n // now check resample_i option and if checked, add suffix to command line\r\n if ($('#resample_i').is(\":checked\") && resample.attr('aint') == 'true') {\r\n commandLine += $('#resample_i').attr('suffix');\r\n }\r\n }\r\n if (output === 'bt') {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Remember to configure the Bluetooth audio device name.\\n', true);\r\n }\r\n // commandLine += concatenateOptions(options);\r\n const data = {\r\n timestamp: Date.now(),\r\n config: {\r\n autoexec1: { value: commandLine, type: NVSType.NVS_TYPE_STR }\r\n }\r\n };\r\n $.ajax({\r\n url: '/config.json',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(data),\r\n error: handleExceptionResponse,\r\n complete: function (response) {\r\n if (response.responseText &&\r\n JSON.parse(response.responseText).result === 'OK') {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Done.\\n', true);\r\n if (apply) {\r\n delayReboot(1500, 'cfg-audio-tmpl');\r\n }\r\n }\r\n else if (JSON.parse(response.responseText).result) {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_WARNING', JSON.parse(response.responseText).Result + '\\n', true);\r\n }\r\n else {\r\n showCmdMessage('cfg-audio-tmpl', 'MESSAGING_ERROR', response.statusText + '\\n');\r\n }\r\n console.log(response.responseText);\r\n },\r\n });\r\n console.log('sent data:', JSON.stringify(data));\r\n}\r\nfunction handleDisconnect() {\r\n $.ajax({\r\n url: '/connect.json',\r\n dataType: 'text',\r\n method: 'DELETE',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n });\r\n}\r\nfunction setPlatformFilter(val) {\r\n if ($('.upf').filter(function () { return $(this).text().toUpperCase() === val.toUpperCase(); }).length > 0) {\r\n $('#splf').val(val).trigger('input');\r\n return true;\r\n }\r\n return false;\r\n}\r\nfunction handleConnect() {\r\n ConnectingToSSID.ssid = $('#manual_ssid').val().toString();\r\n ConnectingToSSID.pwd = $('#manual_pwd').val().toString();\r\n ConnectingToSSID.dhcpname = $('#dhcp-name2').val().toString();\r\n $(\"*[class*='connecting']\").hide();\r\n $('#ssid-wait').text(ConnectingToSSID.ssid);\r\n $('.connecting').show();\r\n $.ajax({\r\n url: '/connect.json',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n ssid: ConnectingToSSID.ssid,\r\n pwd: ConnectingToSSID.pwd\r\n }),\r\n error: handleExceptionResponse,\r\n });\r\n // now we can re-set the intervals regardless of result\r\n}\r\nfunction renderError(opt, error) {\r\n const fieldname = `cmd_opt_${opt}`;\r\n let errorFieldName = `${fieldname}-error`;\r\n let errorField = $(`#${errorFieldName}`);\r\n let field = $(`#${fieldname}`);\r\n if (!errorField || errorField.length == 0) {\r\n field.after(`
`);\r\n errorField = $(`#${errorFieldName}`);\r\n }\r\n if (error.length == 0) {\r\n errorField.hide();\r\n field.removeClass('is-invalid');\r\n field.addClass('is-valid');\r\n errorField.text('');\r\n }\r\n else {\r\n errorField.show();\r\n errorField.text(error);\r\n field.removeClass('is-valid');\r\n field.addClass('is-invalid');\r\n }\r\n return errorField;\r\n}\r\n$(function () {\r\n $('.material-icons').each(function (_index, entry) {\r\n entry.setAttribute('data-icon', entry.textContent || '');\r\n });\r\n setIcons(true);\r\n handleNVSVisible();\r\n flashState.init();\r\n $('#fw-url-input').on('input', function () {\r\n const stringVal = $(this).val().toString();\r\n if (stringVal.length > 8 && (stringVal.startsWith('http://') || stringVal.startsWith('https://'))) {\r\n $('#start-flash').show();\r\n }\r\n else {\r\n $('#start-flash').hide();\r\n }\r\n });\r\n $('.upSrch').on('input', function () {\r\n const inputField = this;\r\n const val = inputField.value;\r\n $(\"#rTable tr\").removeClass(inputField.id + '_hide');\r\n if (val.length > 0) {\r\n $(`#rTable td:nth-child(${$(inputField).parent().index() + 1})`).filter(function () {\r\n return !$(this).text().toUpperCase().includes(val.toUpperCase());\r\n }).parent().addClass(this.id + '_hide');\r\n }\r\n $('[class*=\"_hide\"]').hide();\r\n $('#rTable tr').not('[class*=\"_hide\"]').show();\r\n });\r\n setTimeout(refreshAP, 1500);\r\n /* add validation for cmd_opt_c, which accepts a comma separated list.\r\n getting known codecs from validOptions.codecs array\r\n use bootstrap classes to highlight the error with an overlay message */\r\n $('#options input').on('input', function () {\r\n const inputField = this;\r\n const { opt, val } = get_control_option_value(this);\r\n if (opt === 'c' || opt === 'e') {\r\n const fieldname = `cmd_opt_${opt}_codec-error`;\r\n const values = val.toString().split(',').map(function (item) {\r\n return item.trim();\r\n });\r\n /* get a list of invalid codecs */\r\n const invalid = values.filter(function (item) {\r\n return !validOptions.codecs.includes(item);\r\n });\r\n renderError(opt, invalid.length > 0 ? `Invalid codec(s) ${invalid.join(', ')}` : '');\r\n }\r\n /* add validation for cmd_opt_m, which accepts a mac_address */\r\n if (opt === 'm') {\r\n const mac_regex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;\r\n renderError(opt, mac_regex.test(val.toString()) ? '' : 'Invalid MAC address');\r\n }\r\n if (opt === 'r') {\r\n const rateRegex = /^(\\d+\\.?\\d*|\\.\\d+)-(\\d+\\.?\\d*|\\.\\d+)$|^(\\d+\\.?\\d*)$|^(\\d+\\.?\\d*,)+\\d+\\.?\\d*$/;\r\n renderError(opt, rateRegex.test(val.toString()) ? '' : `Invalid rate(s) ${val}. Acceptable format: |-|,,`);\r\n }\r\n });\r\n $('#WifiConnectDialog')[0].addEventListener('shown.bs.modal', function (event) {\r\n $(\"*[class*='connecting']\").hide();\r\n if (event === null || event === void 0 ? void 0 : event.relatedTarget) {\r\n ConnectingToSSID.Action = ConnectingToActions.CONN;\r\n if ($(event.relatedTarget).children('td:eq(1)').text() == ConnectedTo.ssid) {\r\n ConnectingToSSID.Action = ConnectingToActions.STS;\r\n }\r\n else {\r\n if (!$(event.relatedTarget).is(':last-child')) {\r\n ConnectingToSSID.ssid = $(event.relatedTarget).children('td:eq(1)').text();\r\n $('#manual_ssid').val(ConnectingToSSID.ssid);\r\n }\r\n else {\r\n ConnectingToSSID.Action = ConnectingToActions.MAN;\r\n ConnectingToSSID.ssid = '';\r\n $('#manual_ssid').val(ConnectingToSSID.ssid);\r\n }\r\n }\r\n }\r\n if (ConnectingToSSID.Action !== ConnectingToActions.STS) {\r\n $('.connecting-init').show();\r\n $('#manual_ssid').trigger('focus');\r\n }\r\n else {\r\n handleWifiDialog();\r\n }\r\n });\r\n $('#WifiConnectDialog')[0].addEventListener('hidden.bs.modal', function () {\r\n $('#WifiConnectDialog input').val('');\r\n });\r\n $('#uCnfrm')[0].addEventListener('shown.bs.modal', function () {\r\n $('#selectedFWURL').text($('#fw-url-input').val().toString());\r\n });\r\n $('input#show-commands')[0].checked = LastCommandsState === 1;\r\n $('a[href^=\"#tab-commands\"]').hide();\r\n $('#load-nvs').on('click', function () {\r\n $('#nvsfilename').trigger('click');\r\n });\r\n $('#nvsfilename').on('change', function () {\r\n const _this = this;\r\n if (typeof window.FileReader !== 'function') {\r\n throw \"The file API isn't supported on this browser.\";\r\n }\r\n if (!_this.files) {\r\n throw 'This browser does not support the `files` property of the file input.';\r\n }\r\n if (!_this.files[0]) {\r\n return undefined;\r\n }\r\n const file = _this.files[0];\r\n let fr = new FileReader();\r\n fr.onload = function (e) {\r\n let data;\r\n try {\r\n data = JSON.parse(e.target.result.toString());\r\n }\r\n catch (ex) {\r\n alert('Parsing failed!\\r\\n ' + ex);\r\n }\r\n $('input.nvs').each(function (_index, entry) {\r\n $(this).parent().removeClass('bg-warning').removeClass('bg-success');\r\n if (data[entry.id]) {\r\n if (data[entry.id] !== entry.value) {\r\n console.log('Changed ' + entry.id + ' ' + entry.value + '==>' + data[entry.id]);\r\n $(this).parent().addClass('bg-warning');\r\n $(this).val(data[entry.id]);\r\n }\r\n else {\r\n $(this).parent().addClass('bg-success');\r\n }\r\n }\r\n });\r\n var changed = $(\"input.nvs\").children('.bg-warning');\r\n if (changed) {\r\n alert('Highlighted values were changed. Press Commit to change on the device');\r\n }\r\n };\r\n fr.readAsText(file);\r\n _this.value = null;\r\n });\r\n $('#clear-syslog').on('click', function () {\r\n messagecount = 0;\r\n messageseverity = 'MESSAGING_INFO';\r\n $('#msgcnt').text('');\r\n $('#syslogTable').html('');\r\n });\r\n $('#ok-credits').on('click', function () {\r\n $('#credits').slideUp('fast', function () { });\r\n $('#app').slideDown('fast', function () { });\r\n });\r\n $('#acredits').on('click', function (event) {\r\n event.preventDefault();\r\n $('#app').slideUp('fast', function () { });\r\n $('#credits').slideDown('fast', function () { });\r\n });\r\n $('input#show-commands').on('click', function () {\r\n const _this = this;\r\n _this.checked = _this.checked ? true : false;\r\n if (_this.checked) {\r\n $('a[href^=\"#tab-commands\"]').show();\r\n LastCommandsState = 1;\r\n }\r\n else {\r\n LastCommandsState = 0;\r\n $('a[href^=\"#tab-commands\"]').hide();\r\n }\r\n });\r\n $('#disable-squeezelite').on('click', function () {\r\n // this.checked = this.checked ? 1 : 0;\r\n // $('#disable-squeezelite').prop('checked')\r\n const _this = this;\r\n if (_this.checked) {\r\n // Store the current value before overwriting it\r\n const currentValue = $('#cmd_opt_s').val();\r\n $('#cmd_opt_s').data('originalValue', currentValue);\r\n // Overwrite the value with '-disable'\r\n $('#cmd_opt_s').val('-disable');\r\n }\r\n else {\r\n // Retrieve the original value\r\n const originalValue = $('#cmd_opt_s').data('originalValue');\r\n // Restore the original value if it exists, otherwise set it to an empty string\r\n $('#cmd_opt_s').val(originalValue ? originalValue : '');\r\n }\r\n });\r\n $('input#show-nvs').on('click', function () {\r\n const _this = this;\r\n _this.checked = _this.checked ? true : false;\r\n js_cookie_1.default.set(\"show-nvs\", _this.checked ? 'Y' : 'N');\r\n handleNVSVisible();\r\n });\r\n $('#btn_reboot_recovery').on('click', function () {\r\n handleReboot('recovery');\r\n });\r\n $('#btn_reboot').on('click', function () {\r\n handleReboot('reboot');\r\n });\r\n $('#btn_flash').on('click', function () {\r\n hFlash();\r\n });\r\n $('#save-autoexec1').on('click', function () {\r\n saveAutoexec1(false);\r\n });\r\n $('#commit-autoexec1').on('click', function () {\r\n saveAutoexec1(true);\r\n });\r\n $('#btn_disconnect').on('click', function () {\r\n ConnectedTo = resetNetworkConnection();\r\n refreshAPHTML2();\r\n $.ajax({\r\n url: '/connect.json',\r\n dataType: 'text',\r\n method: 'DELETE',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify({\r\n timestamp: Date.now(),\r\n }),\r\n });\r\n });\r\n $('#btnJoin').on('click', function () {\r\n handleConnect();\r\n });\r\n $('#reboot_nav').on('click', function () {\r\n handleReboot('reboot');\r\n });\r\n $('#reboot_ota_nav').on('click', function () {\r\n handleReboot('reboot_ota');\r\n });\r\n $('#save-as-nvs').on('click', function () {\r\n const config = getConfigJson(true);\r\n const a = document.createElement('a');\r\n a.href = URL.createObjectURL(new Blob([JSON.stringify(config, null, 2)], {\r\n type: 'text/plain',\r\n }));\r\n a.setAttribute('download', 'nvs_config_' + hostName + '_' + Date.now() + 'json');\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n });\r\n $('#save-nvs').on('click', function () {\r\n post_config(getConfigJson(false));\r\n });\r\n $('#fwUpload').on('click', function () {\r\n const fileInput = document.getElementById('flashfilename').files;\r\n if (fileInput.length === 0) {\r\n alert('No file selected!');\r\n }\r\n else {\r\n $('#fw-url-input').value = null;\r\n flashState.StartOTA();\r\n }\r\n });\r\n $('[name=output-tmpl]').on('click', function () {\r\n const outputType = this.id;\r\n handleTemplateTypeRadio(outputType);\r\n });\r\n $('#chkUpdates').on('click', function () {\r\n $('#rTable').html('');\r\n $.getJSON(releaseURL, function (data) {\r\n let i = 0;\r\n const branches = [];\r\n data.forEach(function (release) {\r\n const namecomponents = release.name.split('#');\r\n const branch = namecomponents[3];\r\n if (!branches.includes(branch)) {\r\n branches.push(branch);\r\n }\r\n });\r\n let fwb = '';\r\n branches.forEach(function (branch) {\r\n fwb += '';\r\n });\r\n $('#fwbranch').append(fwb);\r\n data.forEach(function (release) {\r\n let url = '';\r\n release.assets.forEach(function (asset) {\r\n if (asset.name.match(/\\.bin$/)) {\r\n url = asset.browser_download_url;\r\n }\r\n });\r\n const namecomponents = release.name.split('#');\r\n const ver = namecomponents[0];\r\n const cfg = namecomponents[2];\r\n const branch = namecomponents[3];\r\n var bits = ver.substr(ver.lastIndexOf('-') + 1);\r\n bits = (bits == '32' || bits == '16') ? bits : '';\r\n let body = release.body;\r\n body = body.replace(/'/gi, '\"');\r\n body = body.replace(/[\\s\\S]+(### Revision Log[\\s\\S]+)### ESP-IDF Version Used[\\s\\S]+/, '$1');\r\n body = body.replace(/- \\(.+?\\) /g, '- ').encodeHTML();\r\n $('#rTable').append(`\r\n ${ver}${new Date(release.created_at).toLocalShort()}\r\n ${cfg}${branch}${bits}`);\r\n });\r\n if (i > 7) {\r\n $('#releaseTable').append(\"\" +\r\n \"\" +\r\n \"\" +\r\n '' +\r\n '');\r\n $('#showallbutton').on('click', function () {\r\n $('tr.hide').removeClass('hide');\r\n $('tr#showall').addClass('hide');\r\n });\r\n }\r\n $('#searchfw').css('display', 'inline');\r\n if (!setPlatformFilter(platform_name)) {\r\n setPlatformFilter(project_name);\r\n }\r\n $('#rTable tr.release').on('click', function () {\r\n var url = this.getAttribute('fwurl');\r\n if (lmsBaseUrl) {\r\n url = url.replace(/.*\\/download\\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');\r\n }\r\n $('#fw-url-input').val(url);\r\n $('#start-flash').show();\r\n $('#rTable tr.release').removeClass('table-success table-warning');\r\n $(this).addClass('table-success table-warning');\r\n });\r\n }).fail(function () {\r\n alert('failed to fetch release history!');\r\n });\r\n });\r\n $('#fwcheck').on('click', function () {\r\n $('#releaseTable').html('');\r\n $('#fwbranch').empty();\r\n $.getJSON(releaseURL, function (data) {\r\n let i = 0;\r\n const branches = [];\r\n data.forEach(function (release) {\r\n const namecomponents = release.name.split('#');\r\n const branch = namecomponents[3];\r\n if (!branches.includes(branch)) {\r\n branches.push(branch);\r\n }\r\n });\r\n let fwb;\r\n branches.forEach(function (branch) {\r\n fwb += ``;\r\n });\r\n $('#fwbranch').append(fwb);\r\n data.forEach(function (release) {\r\n let url = '';\r\n release.assets.forEach(function (asset) {\r\n if (asset.name.match(/\\.bin$/)) {\r\n url = asset.browser_download_url;\r\n }\r\n });\r\n const namecomponents = release.name.split('#');\r\n const ver = namecomponents[0];\r\n const idf = namecomponents[1];\r\n const cfg = namecomponents[2];\r\n const branch = namecomponents[3];\r\n let body = release.body;\r\n body = body.replace(/'/gi, '\"');\r\n body = body.replace(/[\\s\\S]+(### Revision Log[\\s\\S]+)### ESP-IDF Version Used[\\s\\S]+/, '$1');\r\n body = body.replace(/- \\(.+?\\) /g, '- ');\r\n const trclass = i++ > 6 ? ' hide' : '';\r\n $('#releaseTable').append(`${ver}${new Date(release.created_at).toLocalShort()}${cfg}${idf}${branch}`);\r\n });\r\n if (i > 7) {\r\n $('#releaseTable').append(``);\r\n $('#showallbutton').on('click', function () {\r\n $('tr.hide').removeClass('hide');\r\n $('tr#showall').addClass('hide');\r\n });\r\n }\r\n $('#searchfw').css('display', 'inline');\r\n }).fail(function () {\r\n alert('failed to fetch release history!');\r\n });\r\n });\r\n $('#updateAP').on('click', function () {\r\n refreshAP();\r\n console.log('refresh AP');\r\n });\r\n // first time the page loads: attempt to get the connection status and start the wifi scan\r\n getConfig();\r\n getCommands();\r\n getMessages();\r\n checkStatus();\r\n});\r\n// eslint-disable-next-line no-unused-vars\r\nwindow.setURL = function (button) {\r\n let url = button.dataset.url;\r\n $('[data-bs-url^=\"http\"]')\r\n .addClass('btn-success')\r\n .removeClass('btn-danger');\r\n $('[data-bs-url=\"' + url + '\"]')\r\n .addClass('btn-danger')\r\n .removeClass('btn-success');\r\n // if user can proxy download through LMS, modify the URL\r\n if (lmsBaseUrl) {\r\n url = url.replace(/.*\\/download\\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');\r\n }\r\n $('#fwurl').val(url);\r\n};\r\nfunction rssiToIcon(rssi) {\r\n if (rssi >= -55) {\r\n return { label: '****', icon: `signal_wifi_statusbar_4_bar` };\r\n }\r\n else if (rssi >= -60) {\r\n return { label: '***', icon: `network_wifi_3_bar` };\r\n }\r\n else if (rssi >= -65) {\r\n return { label: '**', icon: `network_wifi_2_bar` };\r\n }\r\n else if (rssi >= -70) {\r\n return { label: '*', icon: `network_wifi_1_bar` };\r\n }\r\n else {\r\n return { label: '.', icon: `signal_wifi_statusbar_null` };\r\n }\r\n}\r\nfunction refreshAP() {\r\n if ((ConnectedTo === null || ConnectedTo === void 0 ? void 0 : ConnectedTo.urc) === connectReturnCode.ETH)\r\n return;\r\n $.ajaxSetup({\r\n timeout: 3000 //Time in milliseconds\r\n });\r\n $.getJSON('/scan.json', function () {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n yield sleep(2000);\r\n $.getJSON('/ap.json', function (data) {\r\n if (data.length > 0) {\r\n // sort by signal strength\r\n data.sort(function (a, b) {\r\n const x = a.rssi;\r\n const y = b.rssi;\r\n // eslint-disable-next-line no-nested-ternary\r\n return x < y ? 1 : x > y ? -1 : 0;\r\n });\r\n apList = data;\r\n refreshAPHTML2(apList);\r\n }\r\n });\r\n });\r\n });\r\n}\r\nfunction formatAP(ssid, rssi, auth) {\r\n const rssi_icon = rssiToIcon(rssi);\r\n const auth_icon = { label: auth == 0 ? '🔓' : '🔒', icon: auth == 0 ? 'no_encryption' : 'lock' };\r\n return `${ssid}\r\n ${getIcon(rssi_icon)}\r\n \t\r\n ${getIcon(auth_icon)}\r\n `;\r\n}\r\nfunction refreshAPHTML2(data) {\r\n var _a;\r\n let h = '';\r\n $('#wifiTable tr td:first-of-type').text('');\r\n $('#wifiTable tr').removeClass('table-success table-warning');\r\n if (data) {\r\n data.forEach(function (e) {\r\n h += formatAP(e.ssid, e.rssi, e.auth);\r\n });\r\n $('#wifiTable').html(h);\r\n }\r\n if ($('.manual_add').length == 0) {\r\n $('#wifiTable').append(formatAP('Manual add', 0, 0));\r\n $('#wifiTable tr:last').addClass('table-light text-dark').addClass('manual_add');\r\n }\r\n if (ConnectedTo.ssid && (ConnectedTo.urc === connectReturnCode.OK || ConnectedTo.urc === connectReturnCode.RESTORE)) {\r\n const wifiSelector = `#wifiTable td:contains(\"${ConnectedTo.ssid}\")`;\r\n if ($(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).length == 0) {\r\n $('#wifiTable').prepend(`${formatAP(ConnectedTo.ssid, (_a = ConnectedTo.rssi) !== null && _a !== void 0 ? _a : 0, 0)}`);\r\n }\r\n $(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).siblings().first().html('✓').parent().addClass((ConnectedTo.urc === connectReturnCode.OK ? 'table-success' : 'table-warning'));\r\n $('span#foot-if').html(`SSID: ${ConnectedTo.ssid}, IP: ${ConnectedTo.ip}`);\r\n const rssiIconObj = rssiToIcon(ConnectedTo.rssi); // Assume this returns an object like { label: 'some_label', icon: 'some_icon_name' }\r\n const iconTextContent = getIcon(rssiIconObj); // Function to get the text content for the material icon\r\n // Set the icon text content\r\n $('#wifiStsIcon').text(iconTextContent);\r\n // Update the aria-label and custom icon attribute\r\n $('#wifiStsIcon').attr('aria-label', rssiIconObj.label);\r\n $('#wifiStsIcon').attr('icon', rssiIconObj.icon);\r\n }\r\n else if ((ConnectedTo === null || ConnectedTo === void 0 ? void 0 : ConnectedTo.urc) !== connectReturnCode.ETH) {\r\n $('span#foot-if').html('');\r\n }\r\n}\r\nfunction refreshETH() {\r\n if (ConnectedTo.urc === connectReturnCode.ETH) {\r\n $('span#foot-if').html(`Network: Ethernet, IP: ${ConnectedTo.ip}`);\r\n }\r\n}\r\nfunction showTask(task) {\r\n console.debug(`${this.toLocaleString()}\\t${task.nme}\\t${task.cpu}\\t${taskStates[task.st]}\\t${task.minstk}\\t${task.bprio}\\t${task.cprio}\\t${task.num}`);\r\n $('tbody#tasks').append(`${task.num}${task.nme}${task.cpu}${taskStates[task.st]}${task.minstk}${task.bprio}${task.cprio}`);\r\n}\r\nfunction btExists(name) {\r\n return getBTSinkOpt(name).length > 0;\r\n}\r\nfunction getBTSinkOpt(name) {\r\n return $(`${btSinkNamesOptSel} option:contains('${name}')`);\r\n}\r\nfunction getMessages() {\r\n $.ajaxSetup({\r\n timeout: messageInterval //Time in milliseconds\r\n });\r\n $.getJSON('/messages.json', function (data) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n for (const msg of data) {\r\n const msgAge = msg.current_time - msg.sent_time;\r\n var msgTime = new Date();\r\n msgTime.setTime(msgTime.getTime() - msgAge);\r\n switch (msg.class) {\r\n case 'MESSAGING_CLASS_OTA':\r\n flashState.EventOTAMessageClass(msg.message);\r\n break;\r\n case 'MESSAGING_CLASS_STATS':\r\n // for task states, check structure : task_state_t\r\n var statsData = JSON.parse(msg.message);\r\n console.debug(msgTime.toLocalShort() +\r\n ' - Number of running tasks: ' +\r\n statsData.ntasks);\r\n console.debug(`${msgTime.toLocalShort()}\\tname\\tcpu\\tstate\\tminstk\\tbprio\\tcprio\\tnum`);\r\n if (statsData.tasks) {\r\n const taskList = statsData.tasks;\r\n if ($('#tasks_sect').css('visibility') === 'collapse') {\r\n $('#tasks_sect').css('visibility', 'visible');\r\n }\r\n $('tbody#tasks').html('');\r\n statsData.taskList\r\n .sort(function (a, b) {\r\n return b.cpu - a.cpu;\r\n })\r\n .forEach(showTask, msgTime);\r\n }\r\n else if ($('#tasks_sect').css('visibility') === 'visible') {\r\n $('tbody#tasks').empty();\r\n $('#tasks_sect').css('visibility', 'collapse');\r\n }\r\n break;\r\n case 'MESSAGING_CLASS_SYSTEM':\r\n showMessage(msg, msgTime);\r\n break;\r\n case 'MESSAGING_CLASS_CFGCMD':\r\n var msgparts = msg.message.split(/([^\\n]*)\\n(.*)/gs);\r\n showCmdMessage(msgparts[1], msg.type, msgparts[2], true);\r\n break;\r\n case 'MESSAGING_CLASS_BT':\r\n if ($(btSinkNamesOptSel).is('input')) {\r\n const sinkNameCtrl = $(btSinkNamesOptSel)[0];\r\n var attr = sinkNameCtrl.attributes;\r\n var attrs = '';\r\n for (var j = 0; j < attr.length; j++) {\r\n if (attr.item(j).name != \"type\") {\r\n attrs += `${attr.item(j).name} = \"${attr.item(j).value}\" `;\r\n }\r\n }\r\n var curOpt = sinkNameCtrl.value;\r\n $(btSinkNamesOptSel).replaceWith(` `);\r\n }\r\n JSON.parse(msg.message).forEach(function (btEntry) {\r\n // [{\\n\\t\\t\\\"name\\\":\\t\\\"SMSL BT4.2\\\",\\n\\t\\t\\\"rssi\\\":\\t-64\\n\\t}]\r\n //\r\n // \r\n if (!btExists(btEntry.name)) {\r\n $(btSinkNamesOptSel).append(``);\r\n showMessage({\r\n type: msg.type,\r\n message: `BT Audio device found: ${btEntry.name} RSSI: ${btEntry.rssi} `,\r\n class: '',\r\n sent_time: 0,\r\n current_time: 0\r\n }, msgTime);\r\n }\r\n getBTSinkOpt(btEntry.name).attr('data-bs-description', `${btEntry.name} (${btEntry.rssi}dB)`)\r\n .attr('rssi', btEntry.rssi)\r\n .attr('value', btEntry.name)\r\n .text(`${btEntry.name} [${btEntry.rssi}dB]`).trigger('change');\r\n });\r\n // Get the options as an array\r\n const btEntries = Array.from($(btSinkNamesOptSel).find('option'));\r\n // Sort the options based on the 'rssi' attribute\r\n btEntries.sort(function (a, b) {\r\n const rssiA = parseInt($(a).attr('rssi'), 10);\r\n const rssiB = parseInt($(b).attr('rssi'), 10);\r\n console.log(`${rssiA} < ${rssiB} ? `);\r\n return rssiB - rssiA; // Sort by descending RSSI values\r\n });\r\n // Clear the select element and append the sorted options\r\n $(btSinkNamesOptSel).empty().append(btEntries);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n setTimeout(getMessages, messageInterval);\r\n });\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n if (xhr.status == 404) {\r\n $('.orec').hide(); // system commands won't be available either\r\n messagesHeld = true;\r\n }\r\n else {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n }\r\n if (xhr.status == 0 && xhr.readyState == 0) {\r\n // probably a timeout. Target is rebooting? \r\n setTimeout(getMessages, messageInterval * 2); // increase duration if a failure happens\r\n }\r\n else if (!messagesHeld) {\r\n // 404 here means we rebooted to an old recovery\r\n setTimeout(getMessages, messageInterval); // increase duration if a failure happens\r\n }\r\n });\r\n /*\r\n Minstk is minimum stack space left\r\n Bprio is base priority\r\n cprio is current priority\r\n nme is name\r\n st is task state. I provided a \"typedef\" that you can use to convert to text\r\n cpu is cpu percent used\r\n */\r\n}\r\nfunction handleRecoveryMode(data) {\r\n var _a;\r\n const locRecovery = (_a = data.recovery) !== null && _a !== void 0 ? _a : 0;\r\n if (locRecovery === 1) {\r\n recovery = true;\r\n $('.recovery_element').show();\r\n $('.ota_element').hide();\r\n $('#boot-button').html('Reboot');\r\n $('#boot-form').attr('action', '/reboot_ota.json');\r\n }\r\n else {\r\n if (!recovery && messagesHeld) {\r\n messagesHeld = false;\r\n setTimeout(getMessages, messageInterval); // increase duration if a failure happens\r\n }\r\n recovery = false;\r\n $('.recovery_element').hide();\r\n $('.ota_element').show();\r\n $('#boot-button').html('Recovery');\r\n $('#boot-form').attr('action', '/recovery.json');\r\n }\r\n}\r\nfunction hasConnectionChanged(data) {\r\n // gw: \"192.168.10.1\"\r\n // ip: \"192.168.10.225\"\r\n // netmask: \"255.255.255.0\"\r\n // ssid: \"MyTestSSID\"\r\n return (data.urc !== ConnectedTo.urc ||\r\n data.ssid !== ConnectedTo.ssid ||\r\n data.gw !== ConnectedTo.gw ||\r\n data.netmask !== ConnectedTo.netmask ||\r\n data.ip !== ConnectedTo.ip || data.rssi !== ConnectedTo.rssi);\r\n}\r\nfunction handleWifiDialog(data) {\r\n if ($('#WifiConnectDialog').is(':visible')) {\r\n if (ConnectedTo.ip) {\r\n $('#ipAddress').text(ConnectedTo.ip);\r\n }\r\n if (ConnectedTo.ssid) {\r\n $('#connectedToSSID').text(ConnectedTo.ssid);\r\n }\r\n if (ConnectedTo.gw) {\r\n $('#gateway').text(ConnectedTo.gw);\r\n }\r\n if (ConnectedTo.netmask) {\r\n $('#netmask').text(ConnectedTo.netmask);\r\n }\r\n if (ConnectingToSSID.Action === undefined || (ConnectingToSSID.Action && ConnectingToSSID.Action == ConnectingToActions.STS)) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-status').show();\r\n }\r\n if (SystemConfig.ap_ssid) {\r\n $('#apName').text(SystemConfig.ap_ssid.value);\r\n }\r\n if (SystemConfig.ap_pwd) {\r\n $('#apPass').text(SystemConfig.ap_pwd.value);\r\n }\r\n if (!data) {\r\n return;\r\n }\r\n else {\r\n switch (data.urc) {\r\n case connectReturnCode.OK:\r\n if (data.ssid && data.ssid === ConnectingToSSID.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-success').show();\r\n ConnectingToSSID.Action = ConnectingToActions.STS;\r\n }\r\n break;\r\n case connectReturnCode.FAIL:\r\n // \r\n if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid == data.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-fail').show();\r\n }\r\n break;\r\n case connectReturnCode.LOST:\r\n break;\r\n case connectReturnCode.RESTORE:\r\n if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid != data.ssid) {\r\n $(\"*[class*='connecting']\").hide();\r\n $('.connecting-fail').show();\r\n }\r\n break;\r\n case connectReturnCode.DISC:\r\n // that's a manual disconnect\r\n // if ($('#wifi-status').is(':visible')) {\r\n // $('#wifi-status').slideUp('fast', function() {});\r\n // $('span#foot-wifi').html('');\r\n // } \r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n}\r\nfunction setIcons(offline) {\r\n $('.material-icons').each(function (_index, entry) {\r\n const htmlEntry = entry;\r\n htmlEntry.textContent = htmlEntry.getAttribute(offline ? 'aria-label' : 'data-icon') || '';\r\n });\r\n}\r\nfunction assignStatusToNetworkConnection(data) {\r\n var _a;\r\n const connection = {\r\n urc: (_a = data.urc) !== null && _a !== void 0 ? _a : 0,\r\n auth: undefined,\r\n pwd: undefined,\r\n dhcpname: undefined,\r\n Action: undefined,\r\n ip: data.ip,\r\n ssid: data.ssid,\r\n rssi: data.rssi,\r\n gw: data.gw,\r\n netmask: data.netmask\r\n };\r\n return connection;\r\n}\r\nfunction handleNetworkStatus(data) {\r\n setIcons(!isConnected());\r\n if (hasConnectionChanged(data) || !data.urc) {\r\n ConnectedTo = assignStatusToNetworkConnection(data);\r\n $(\".if_eth\").hide();\r\n $('.if_wifi').hide();\r\n if (!data.urc || ConnectedTo.urc != connectReturnCode.ETH) {\r\n $('.if_wifi').show();\r\n refreshAPHTML2();\r\n }\r\n else {\r\n $(\".if_eth\").show();\r\n refreshETH();\r\n }\r\n }\r\n handleWifiDialog(data);\r\n}\r\nfunction batteryToIcon(voltage) {\r\n /* Assuming Li-ion 18650s as a power source, 3.9V per cell, or above is treated\r\n as full charge (>75% of capacity). 3.4V is empty. The gauge is loosely\r\n following the graph here:\r\n https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages\r\n using the 0.2C discharge profile for the rest of the values.\r\n */\r\n for (const iconEntry of batIcons) {\r\n for (const entryRanges of iconEntry.ranges) {\r\n if (inRange(voltage, entryRanges.f, entryRanges.t)) {\r\n return { label: iconEntry.label, icon: iconEntry.icon };\r\n }\r\n }\r\n }\r\n return { label: '▪▪▪▪', icon: \"battery_full\" };\r\n}\r\nfunction checkStatus() {\r\n $.ajaxSetup({\r\n timeout: statusInterval //Time in milliseconds\r\n });\r\n $.getJSON('/status.json', function (data) {\r\n var _a;\r\n handleRecoveryMode(data);\r\n handleNVSVisible();\r\n handleNetworkStatus(data);\r\n handlebtstate(data);\r\n flashState.EventTargetStatus(data);\r\n if (data.depth) {\r\n depth = data.depth;\r\n if (depth == 16) {\r\n $('#cmd_opt_R').show();\r\n }\r\n else {\r\n $('#cmd_opt_R').hide();\r\n }\r\n }\r\n if (data.project_name && data.project_name !== '') {\r\n project_name = data.project_name;\r\n }\r\n if (data.platform_name && data.platform_name !== '') {\r\n platform_name = data.platform_name;\r\n }\r\n if (board_model === '')\r\n board_model = project_name;\r\n if (board_model === '')\r\n board_model = 'Squeezelite-ESP32';\r\n if (data.version && data.version !== '') {\r\n versionName = data.version;\r\n $(\"#navtitle\").html(`${board_model}${recovery ? '
[recovery]' : ''}`);\r\n $('span#foot-fw').html(`fw: ${versionName}, mode: ${recovery ? \"Recovery\" : project_name}`);\r\n }\r\n else {\r\n $('span#flash-status').html('');\r\n }\r\n if (data.Voltage) {\r\n const bat_icon = batteryToIcon(data.Voltage);\r\n $('#battery').html(`${getIcon(bat_icon)}`);\r\n $('#battery').attr(\"aria-label\", bat_icon.label);\r\n $('#battery').attr(\"data-icon\", bat_icon.icon);\r\n $('#battery').show();\r\n }\r\n else {\r\n $('#battery').hide();\r\n }\r\n if (((_a = data.message) !== null && _a !== void 0 ? _a : '') != '' && prevmessage != data.message) {\r\n // supporting older recovery firmwares - messages will come from the status.json structure\r\n prevmessage = data.message;\r\n showLocalMessage(data.message, 'MESSAGING_INFO');\r\n }\r\n is_i2c_locked = data.is_i2c_locked;\r\n if (is_i2c_locked) {\r\n $('flds-cfg-hw-preset').hide();\r\n }\r\n else {\r\n $('flds-cfg-hw-preset').show();\r\n }\r\n $(\"button[onclick*='handleReboot']\").removeClass('rebooting');\r\n if (typeof lmsBaseUrl == \"undefined\" || data.lms_ip != prevLMSIP && data.lms_ip && data.lms_port) {\r\n const baseUrl = 'http://' + data.lms_ip + ':' + data.lms_port;\r\n prevLMSIP = data.lms_ip;\r\n $.ajax({\r\n url: baseUrl + '/plugins/SqueezeESP32/firmware/-check.bin',\r\n type: 'HEAD',\r\n dataType: 'text',\r\n cache: false,\r\n error: function () {\r\n // define the value, so we don't check it any more.\r\n lmsBaseUrl = '';\r\n },\r\n success: function () {\r\n lmsBaseUrl = baseUrl;\r\n }\r\n });\r\n }\r\n $('#o_jack').css({ display: Number(data.Jack) ? 'inline' : 'none' });\r\n setTimeout(checkStatus, statusInterval);\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n if (xhr.status == 0 && xhr.readyState == 0) {\r\n // probably a timeout. Target is rebooting? \r\n setTimeout(checkStatus, messageInterval * 2); // increase duration if a failure happens\r\n }\r\n else {\r\n setTimeout(checkStatus, messageInterval); // increase duration if a failure happens\r\n }\r\n });\r\n}\r\n// eslint-disable-next-line no-unused-vars\r\nwindow.runCommand = function (button, reboot) {\r\n let cmdstring = button.getAttribute('cmdname');\r\n showCmdMessage(cmdstring, 'MESSAGING_INFO', 'Executing.', false);\r\n const fields = document.getElementById('flds-' + cmdstring);\r\n const allfields = fields === null || fields === void 0 ? void 0 : fields.querySelectorAll('select,input');\r\n if (cmdstring === 'cfg-hw-preset')\r\n return handleHWPreset(allfields, reboot);\r\n cmdstring += ' ';\r\n if (fields) {\r\n for (const field of allfields) {\r\n let qts = '';\r\n let opt = '';\r\n const isSelect = field.tagName === 'SELECT';\r\n const hasValue = field.getAttribute('hasvalue') === 'true';\r\n const validVal = (isSelect && field.value !== '--') || (!isSelect && field.value !== '');\r\n if (!hasValue || (hasValue && validVal)) {\r\n const longopts = field.getAttribute('longopts');\r\n const shortopts = field.getAttribute('shortopts');\r\n if (longopts !== null && longopts !== 'undefined') {\r\n opt += '--' + longopts;\r\n }\r\n else if (shortopts !== null && shortopts !== 'undefined') {\r\n opt = '-' + shortopts;\r\n }\r\n if (hasValue) {\r\n qts = /\\s/.test(field.value) ? '\"' : '';\r\n cmdstring += `${opt} ${qts}${field.value}${qts} `;\r\n }\r\n else {\r\n // this is a checkbox\r\n if (field.checked) {\r\n cmdstring += `${opt} `;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n console.log(cmdstring);\r\n const data = {\r\n timestamp: Date.now(),\r\n command: cmdstring\r\n };\r\n $.ajax({\r\n url: '/commands.json',\r\n dataType: 'text',\r\n method: 'POST',\r\n cache: false,\r\n contentType: 'application/json; charset=utf-8',\r\n data: JSON.stringify(data),\r\n error: function (xhr, _ajaxOptions, thrownError) {\r\n var cmd = JSON.parse(this.data).command;\r\n if (xhr.status == 404) {\r\n showCmdMessage(cmd.substr(0, cmd.indexOf(' ')), 'MESSAGING_ERROR', `${recovery ? 'Limited recovery mode active. Unsupported action ' : 'Unexpected error while processing command'}`, true);\r\n }\r\n else {\r\n handleExceptionResponse(xhr, _ajaxOptions, thrownError);\r\n showCmdMessage(cmd.substr(0, cmd.indexOf(' ') - 1), 'MESSAGING_ERROR', `Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status}`, true);\r\n }\r\n },\r\n success: function (response) {\r\n $('.orec').show();\r\n console.log(response);\r\n if (JSON.parse(response).Result === 'Success' &&\r\n reboot) {\r\n delayReboot(2500, button.getAttribute('cmdname'));\r\n }\r\n },\r\n });\r\n};\r\nfunction getLongOps(data, name, longopts) {\r\n return data[name] !== undefined ? data[name][longopts] : \"\";\r\n}\r\nfunction getCommands() {\r\n $.ajaxSetup({\r\n timeout: 7000 //Time in milliseconds\r\n });\r\n $.getJSON('/commands.json', function (data) {\r\n console.log(data);\r\n $('.orec').show();\r\n data.commands.forEach(function (command) {\r\n if ($('#flds-' + command.name).length === 0) {\r\n const cmdParts = command.name.split('-');\r\n const isConfig = cmdParts[0] === 'cfg';\r\n const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1];\r\n let innerhtml = '';\r\n innerhtml += `
${command.help.encodeHTML().replace(/\\n/g, '
')}
`;\r\n if (command.argtable) {\r\n command.argtable.forEach(function (arg) {\r\n let placeholder = arg.datatype || '';\r\n const ctrlname = command.name + '-' + arg.longopts;\r\n const curvalue = getLongOps(data.values, command.name, arg.longopts);\r\n let attributes = `hasvalue=${arg.hasvalue} `;\r\n attributes += 'longopts=\"' + arg.longopts + '\" ';\r\n attributes += 'shortopts=\"' + arg.shortopts + '\" ';\r\n attributes += 'checkbox=' + arg.checkbox + ' ';\r\n attributes += 'cmdname=\"' + command.name + '\" ';\r\n attributes +=\r\n `id=\"${ctrlname}\" name=\"${ctrlname}\" hasvalue=\"${arg.hasvalue}\" `;\r\n let extraclass = arg.mincount > 0 ? 'bg-success' : '';\r\n if (arg.glossary === 'hidden') {\r\n attributes += ' style=\"visibility: hidden;\"';\r\n }\r\n if (arg.checkbox) {\r\n innerhtml += `
`;\r\n }\r\n else {\r\n innerhtml += `
`;\r\n if (placeholder.includes('|')) {\r\n extraclass = placeholder.startsWith('+') ? ' multiple ' : '';\r\n placeholder = placeholder\r\n .replace('<', '')\r\n .replace('=', '')\r\n .replace('>', '');\r\n innerhtml += `';\r\n }\r\n else {\r\n innerhtml += ``;\r\n }\r\n }\r\n innerhtml += `${arg.checkbox ? '
' : ''}Previous value: ${arg.checkbox ? (curvalue ? 'Checked' : 'Unchecked') : (curvalue || '')}${arg.checkbox ? '' : '
'}`;\r\n });\r\n }\r\n innerhtml += `
\r\n
\r\n
\r\n Result\r\n
\r\n
\r\n
`;\r\n if (isConfig) {\r\n innerhtml +=\r\n `\r\n`;\r\n }\r\n else {\r\n innerhtml += ``;\r\n }\r\n innerhtml += '
';\r\n if (isConfig) {\r\n $(targetDiv).append(innerhtml);\r\n }\r\n else {\r\n $('#commands-list').append(innerhtml);\r\n }\r\n }\r\n });\r\n $(\".sclk\").off('click').on('click', function () { window.runCommand(this, false); });\r\n $(\".cclk\").off('click').on('click', function () { window.runCommand(this, true); });\r\n data.commands.forEach(function (command) {\r\n $('[cmdname=' + command.name + ']:input').val('');\r\n $('[cmdname=' + command.name + ']:checkbox').prop('checked', false);\r\n if (command.argtable) {\r\n command.argtable.forEach(function (arg) {\r\n const ctrlselector = '#' + command.name + '-' + arg.longopts;\r\n if (arg.checkbox) {\r\n $(ctrlselector)[0].checked = getLongOps(data, command.name, arg.longopts);\r\n }\r\n else {\r\n let ctrlValue = getLongOps(data, command.name, arg.longopts);\r\n if (ctrlValue !== undefined) {\r\n $(ctrlselector)\r\n .val(ctrlValue.toString())\r\n .trigger('change');\r\n }\r\n if ($(ctrlselector)[0].value.length === 0 &&\r\n (arg.datatype || '').includes('|')) {\r\n $(ctrlselector)[0].value = '--';\r\n }\r\n }\r\n });\r\n }\r\n });\r\n loadPresets();\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n if (xhr.status == 404) {\r\n $('.orec').hide();\r\n }\r\n else {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n }\r\n $('#commands-list').empty();\r\n });\r\n}\r\nfunction getConfig() {\r\n $.ajaxSetup({\r\n timeout: 7000 //Time in milliseconds\r\n });\r\n $.getJSON('/config.json', function (entries) {\r\n $('#nvsTable tr').remove();\r\n const data = (entries.config ? entries.config : entries);\r\n SystemConfig = data;\r\n commandBTSinkName = '';\r\n Object.keys(data)\r\n .sort()\r\n .forEach(function (key) {\r\n let val = data[key].value;\r\n if (key === 'autoexec1') {\r\n /* call new function to parse the squeezelite options */\r\n processSqueezeliteCommandLine(val);\r\n }\r\n else if (key === 'host_name') {\r\n val = val.replaceAll('\"', '');\r\n $('input#dhcp-name1').val(val);\r\n $('input#dhcp-name2').val(val);\r\n if ($('#cmd_opt_n').length == 0) {\r\n $('#cmd_opt_n').val(val);\r\n }\r\n document.title = val;\r\n hostName = val;\r\n }\r\n else if (key === 'rel_api') {\r\n releaseURL = val;\r\n }\r\n else if (key === 'enable_airplay') {\r\n $(\"#s_airplay\").css({ display: isEnabled(val) ? 'inline' : 'none' });\r\n }\r\n else if (key === 'enable_cspot') {\r\n $(\"#s_cspot\").css({ display: isEnabled(val) ? 'inline' : 'none' });\r\n }\r\n else if (key == 'preset_name') {\r\n preset_name = val;\r\n }\r\n else if (key == 'board_model') {\r\n board_model = val;\r\n }\r\n $('tbody#nvsTable').append(`${key}`);\r\n $('input#' + key).val(data[key].value);\r\n });\r\n if (commandBTSinkName.length > 0) {\r\n // persist the sink name found in the autoexec1 command line\r\n $('#cfg-audio-bt_source-sink_name').val(commandBTSinkName);\r\n }\r\n $('tbody#nvsTable').append(\"\");\r\n if (entries.gpio) {\r\n $('#pins').show();\r\n $('tbody#gpiotable tr').remove();\r\n entries.gpio.forEach(function (gpioEntry) {\r\n $('tbody#gpiotable').append(`${gpioEntry.group}${gpioEntry.name}${gpioEntry.gpio}${gpioEntry.fixed ? 'Fixed' : 'Configuration'}`);\r\n });\r\n }\r\n else {\r\n $('#pins').hide();\r\n }\r\n }).fail(function (xhr, ajaxOptions, thrownError) {\r\n handleExceptionResponse(xhr, ajaxOptions, thrownError);\r\n });\r\n}\r\nfunction processSqueezeliteCommandLine(val) {\r\n const parsed = parseSqueezeliteCommandLine(val);\r\n if (parsed.output.toUpperCase().startsWith('I2S')) {\r\n handleTemplateTypeRadio('i2s');\r\n }\r\n else if (parsed.output.toUpperCase().startsWith('SPDIF')) {\r\n handleTemplateTypeRadio('spdif');\r\n }\r\n else if (parsed.output.toUpperCase().startsWith('BT')) {\r\n if (parsed.otherOptions.btname) {\r\n commandBTSinkName = parsed.otherOptions.btname;\r\n }\r\n handleTemplateTypeRadio('bt');\r\n }\r\n Object.keys(parsed.options).forEach(function (key) {\r\n const option = parsed.options[key];\r\n if (!$(`#cmd_opt_${key}`).hasOwnProperty('checked')) {\r\n $(`#cmd_opt_${key}`).val(option);\r\n }\r\n else {\r\n if (typeof option === 'boolean') {\r\n $(`#cmd_opt_${key}`)[0].checked = option;\r\n }\r\n }\r\n });\r\n if (parsed.options.hasOwnProperty('u')) {\r\n // parse -u v[:i] and check the appropriate radio button with id #resample_v\r\n const [resampleValue, resampleInterpolation] = parsed.options.u.split(':');\r\n $(`#resample_${resampleValue}`).prop('checked', true);\r\n // if resampleinterpolation is set, check resample_i checkbox\r\n if (resampleInterpolation) {\r\n $('#resample_i').prop('checked', true);\r\n }\r\n }\r\n if (parsed.options.hasOwnProperty('s')) {\r\n // parse -u v[:i] and check the appropriate radio button with id #resample_v\r\n if (parsed.options.s === '-disable') {\r\n $('#disable-squeezelite')[0].checked = true;\r\n }\r\n else {\r\n $('#disable-squeezelite')[0].checked = false;\r\n }\r\n }\r\n}\r\nfunction showLocalMessage(message, severity) {\r\n const msg = {\r\n message: message,\r\n type: severity,\r\n class: '',\r\n sent_time: 0,\r\n current_time: 0\r\n };\r\n showMessage(msg, new Date());\r\n}\r\nfunction showMessage(msg, msgTime) {\r\n let color = 'table-success';\r\n if (msg.type === 'MESSAGING_WARNING') {\r\n color = 'table-warning';\r\n if (messageseverity === 'MESSAGING_INFO') {\r\n messageseverity = 'MESSAGING_WARNING';\r\n }\r\n }\r\n else if (msg.type === 'MESSAGING_ERROR') {\r\n if (messageseverity === 'MESSAGING_INFO' ||\r\n messageseverity === 'MESSAGING_WARNING') {\r\n messageseverity = 'MESSAGING_ERROR';\r\n }\r\n color = 'table-danger';\r\n }\r\n if (++messagecount > 0) {\r\n $('#msgcnt').removeClass('badge-success');\r\n $('#msgcnt').removeClass('badge-warning');\r\n $('#msgcnt').removeClass('badge-danger');\r\n $('#msgcnt').addClass({\r\n MESSAGING_INFO: 'badge-success',\r\n MESSAGING_WARNING: 'badge-warning',\r\n MESSAGING_ERROR: 'badge-danger',\r\n }[messageseverity]);\r\n $('#msgcnt').text(messagecount);\r\n }\r\n $('#syslogTable').append(\"\" +\r\n '' +\r\n msgTime.toLocalShort() +\r\n '' +\r\n '' +\r\n msg.message.encodeHTML() +\r\n '' +\r\n '');\r\n}\r\nfunction inRange(x, min, max) {\r\n return (x - min) * (x - max) <= 0;\r\n}\r\nfunction sleep(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n}\r\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t826: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunksqueezelite_esp32\"] = self[\"webpackChunksqueezelite_esp32\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [987], () => (__webpack_require__(607)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","jspb","require","goog","global","this","window","self","Function","call","nanopb_pb","object","extend","proto","exportSymbol","Conf","GPIO","opt_data","Message","initialize","inherits","DEBUG","COMPILED","displayName","I2CBus","DACDev","SPDIFDev","DispOffsets","DispCommon","I2CDisplay","SPIDisplay","SPIBus","DisplayDev","oneofGroups_","GPIOExp","WS2812","LEDStrip","Rotary","ButtonActions","Button","EthCommon","EthSPI","EthRMII","Eth","Battery","Gpios","Dev","repeatedFields_","SleepService","Artwork","Metadata","Services","Config","GENERATE_TO_OBJECT","prototype","toObject","opt_includeInstance","includeInstance","msg","obj","pin","getFieldWithDefault","level","$jspbMessageInstance","deserializeBinary","bytes","reader","BinaryReader","deserializeBinaryFromReader","nextField","isEndGroup","getFieldNumber","value","readInt32","setPin","setLevel","skipField","serializeBinary","writer","BinaryWriter","serializeBinaryToWriter","getResultBuffer","message","f","undefined","getPin","writeInt32","getField","setProto3IntField","getLevel","setField","clearLevel","hasLevel","port","speed","sda","getSda","scl","getScl","readEnum","setPort","setSpeed","readMessage","setSda","setScl","getPort","writeEnum","getSpeed","writeMessage","setProto3EnumField","getWrapperField","setWrapperField","clearSda","hasSda","clearScl","hasScl","bck","getBck","ws","getWs","dout","getDout","mck","mute","getMute","model","i2c","getI2c","setBck","setWs","setDout","setMck","setMute","setModel","setI2c","getMck","getModel","clearBck","hasBck","clearWs","hasWs","clearDout","hasDout","clearMute","hasMute","clearI2c","hasI2c","dc","getDc","data","getData","clk","getClk","setDc","setData","setClk","clearDc","hasDc","clearData","hasData","clearClk","hasClk","height","width","setHeight","setWidth","getHeight","getWidth","hflip","getBooleanFieldWithDefault","vflip","driver","bitdepth","back","getBack","reset","getReset","ready","getReady","offsets","getOffsets","readBool","setHflip","setVflip","setDriver","setBitdepth","setBack","setReset","setReady","setOffsets","getHflip","writeBool","getVflip","getDriver","getBitdepth","setProto3BooleanField","clearBack","hasBack","clearReset","hasReset","clearReady","hasReady","clearOffsets","hasOffsets","address","setAddress","getAddress","cs","getCs","rotate","setCs","setRotate","getRotate","clearCs","hasCs","mosi","getMosi","miso","getMiso","host","setMosi","setMiso","setHost","getHost","clearMosi","hasMosi","clearMiso","hasMiso","DisptypeCase","DISPTYPE_NOT_SET","I2C","SPI","getDisptypeCase","computeOneofCase","type","common","getCommon","spi","getSpi","setType","setCommon","setSpi","getType","clearCommon","hasCommon","setOneofWrapperField","clearSpi","hasSpi","addr","base","count","intr","getIntr","setAddr","setBase","setCount","setIntr","getAddr","getBase","getCount","clearIntr","hasIntr","length","gpio","getGpio","setLength","setGpio","getLength","clearGpio","hasGpio","ws2812","getWs2812","setWs2812","clearWs2812","hasWs2812","a","getA","b","getB","sw","getSw","knobonly","volume","longpress","setA","setB","setSw","setKnobonly","setVolume","setLongpress","getKnobonly","getVolume","getLongpress","clearA","hasA","clearB","hasB","clearSw","hasSw","pressed","released","setPressed","setReleased","getPressed","getReleased","pull","debounce","shifter","getShifter","longduration","normal","getNormal","shifted","getShifted","longshifted","getLongshifted","setPull","setDebounce","setShifter","setLongduration","setNormal","setShifted","setLongshifted","getPull","getDebounce","getLongduration","clearShifter","hasShifter","clearNormal","hasNormal","clearLongpress","hasLongpress","clearShifted","hasShifted","clearLongshifted","hasLongshifted","rst","getRst","setRst","clearRst","hasRst","mdc","getMdc","mdio","getMdio","setMdc","setMdio","clearMdc","hasMdc","clearMdio","hasMdio","EthtypeCase","ETHTYPE_NOT_SET","RMII","getEthtypeCase","rmii","getRmii","setRmii","clearRmii","hasRmii","channel","scale","getFloatingPointFieldWithDefault","cells","atten","setChannel","readFloat","setScale","setCells","setAtten","getChannel","getScale","writeFloat","getCells","getAtten","setProto3FloatField","greenled","getGreenled","redled","getRedled","audiojack","getAudiojack","amp","getAmp","power","getPower","ir","getIr","jack","getJack","spkfault","getSpkfault","vcc","getVcc","gnd","getGnd","setGreenled","setRedled","setAudiojack","setAmp","setPower","setIr","setJack","setSpkfault","setVcc","setGnd","clearGreenled","hasGreenled","clearRedled","hasRedled","clearAudiojack","hasAudiojack","clearAmp","hasAmp","clearPower","hasPower","clearIr","hasIr","clearJack","hasJack","clearSpkfault","hasSpkfault","clearVcc","hasVcc","clearGnd","hasGnd","dac","getDac","spdif","getSpdif","display","getDisplay","gpioExp","getGpioExp","ledStrip","getLedStrip","rotary","getRotary","buttonsList","toObjectList","getButtonsList","eth","getEth","battery","getBattery","setDac","setSpdif","setDisplay","setGpioExp","setLedStrip","setRotary","addButtons","setEth","setBattery","writeRepeatedMessage","clearDac","hasDac","clearSpdif","hasSpdif","clearDisplay","hasDisplay","clearGpioExp","hasGpioExp","clearLedStrip","hasLedStrip","clearRotary","hasRotary","getRepeatedWrapperField","setButtonsList","setRepeatedWrapperField","opt_value","opt_index","addToRepeatedWrapperField","clearButtonsList","clearEth","hasEth","clearBattery","hasBattery","delay","spurious","sleep","getSleep","wakeList","getWakeList","rtcList","getRtcList","batt","readUint32","setDelay","setSpurious","setSleep","addWake","addRtc","setBatt","getDelay","writeUint32","getSpurious","getBatt","clearSleep","hasSleep","setWakeList","clearWakeList","setRtcList","clearRtcList","enabled","resize","setEnabled","setResize","getEnabled","getResize","format","pause","artwork","getArtwork","readString","setFormat","setPause","setArtwork","getFormat","writeString","getPause","setProto3StringField","clearArtwork","hasArtwork","metadata","getMetadata","setMetadata","clearMetadata","hasMetadata","gpios","getGpios","dev","getDev","services","getServices","deviceName","setGpios","setDev","setServices","setDeviceName","getDeviceName","clearGpios","hasGpios","clearDev","hasDev","clearServices","hasServices","ButtonAction","ACTRLS_NONE","ACTRLS_POWER","ACTRLS_VOLUP","ACTRLS_VOLDOWN","ACTRLS_TOGGLE","ACTRLS_PLAY","ACTRLS_PAUSE","ACTRLS_STOP","ACTRLS_REW","ACTRLS_FWD","ACTRLS_PREV","ACTRLS_NEXT","BCTRLS_UP","BCTRLS_DOWN","BCTRLS_LEFT","BCTRLS_RIGHT","BCTRLS_PS1","BCTRLS_PS2","BCTRLS_PS3","BCTRLS_PS4","BCTRLS_PS5","BCTRLS_PS6","BCTRLS_PS7","BCTRLS_PS8","BCTRLS_PS9","BCTRLS_PS10","KNOB_LEFT","KNOB_RIGHT","KNOB_PUSH","ACTRLS_SLEEP","DACModelEnum","UNSPECIFIED_MODEL","TAS57XX","TAS5713","AC101","WM8978","ES8388","I2S","DeviceTypeEnum","UNSPECIFIED_TYPE","DEVTYPE_SPI","DEVTYPE_I2C","DEVTYPE__RMII","DisplayDriverEnum","UNSPECIFIED_DRIVER","SSD1306","SSD1322","SSD1326","SSD1327","SH1106","SSD1675","ST7735","ST7789","ILI9341","ILI9341_24","SSD1351","PortEnum","UNSPECIFIED_SYSTPORT","SYSTEM","DAC","EthModelEnum","UNSPECIFIED_ETHMODEL","LAN8720","DM9051","W5500","GPIOExpModelEnum","UNSPECIFIED_EXP","PCA9535","PCA85XX","MCP23017","MCP23S17","HostEnum","UNSPECIFIED_HOST","HOST0","HOST1","I2CPortEnum","UNSPECIFIED_PORT","I2CPORT0","I2CPORT1","MCKEnum","UNSPECIFIED_MCK","MCK0","MCK1","MCK2","BatteryChannelEnum","UNSPECIFIED_CH","CH0","CH1","CH2","CH3","CH4","CH5","CH6","CH7","BatteryAttenEnum","UNSPECIFIED_ATT","ATT_0","ATT_1","ATT_2","ATT_3","EthType","UNSPECIFIED_ETH","exports","google_protobuf_descriptor_pb","NanoPBOptions","maxSize","maxLength","maxCount","intSize","longNames","packedStruct","packedEnum","skipMessage","noUnions","msgid","anonymousOneof","proto3","proto3SingularMsgs","enumToString","fixedLength","fixedCount","submsgCallback","mangleNames","callbackDatatype","callbackFunction","descriptorsize","defaultHas","includeList","getRepeatedField","excludeList","pb_package","typeOverride","sortByTag","setMaxSize","setMaxLength","setMaxCount","setIntSize","setLongNames","setPackedStruct","setPackedEnum","setSkipMessage","setNoUnions","setMsgid","setAnonymousOneof","setProto3","setProto3SingularMsgs","setEnumToString","setFixedLength","setFixedCount","setSubmsgCallback","setMangleNames","setCallbackDatatype","setCallbackFunction","setDescriptorsize","setDefaultHas","addInclude","addExclude","setPackage","setTypeOverride","setSortByTag","getIncludeList","writeRepeatedString","getExcludeList","getMaxSize","clearMaxSize","hasMaxSize","getMaxLength","clearMaxLength","hasMaxLength","getMaxCount","clearMaxCount","hasMaxCount","getIntSize","clearIntSize","hasIntSize","clearType","hasType","getLongNames","clearLongNames","hasLongNames","getPackedStruct","clearPackedStruct","hasPackedStruct","getPackedEnum","clearPackedEnum","hasPackedEnum","getSkipMessage","clearSkipMessage","hasSkipMessage","getNoUnions","clearNoUnions","hasNoUnions","getMsgid","clearMsgid","hasMsgid","getAnonymousOneof","clearAnonymousOneof","hasAnonymousOneof","getProto3","clearProto3","hasProto3","getProto3SingularMsgs","clearProto3SingularMsgs","hasProto3SingularMsgs","getEnumToString","clearEnumToString","hasEnumToString","getFixedLength","clearFixedLength","hasFixedLength","getFixedCount","clearFixedCount","hasFixedCount","getSubmsgCallback","clearSubmsgCallback","hasSubmsgCallback","getMangleNames","clearMangleNames","hasMangleNames","getCallbackDatatype","clearCallbackDatatype","hasCallbackDatatype","getCallbackFunction","clearCallbackFunction","hasCallbackFunction","getDescriptorsize","clearDescriptorsize","hasDescriptorsize","getDefaultHas","clearDefaultHas","hasDefaultHas","setIncludeList","addToRepeatedField","clearIncludeList","setExcludeList","clearExcludeList","getPackage","clearPackage","hasPackage","getTypeOverride","clearTypeOverride","hasTypeOverride","getSortByTag","clearSortByTag","hasSortByTag","FieldType","FT_DEFAULT","FT_CALLBACK","FT_POINTER","FT_STATIC","FT_IGNORE","FT_INLINE","IntSize","IS_DEFAULT","IS_8","IS_16","IS_32","IS_64","TypenameMangling","M_NONE","M_STRIP_PACKAGE","M_FLATTEN","M_PACKAGE_INITIALS","DescriptorSize","DS_AUTO","DS_1","DS_2","DS_4","DS_8","nanopbFileopt","ExtensionFieldInfo","FileOptions","extensionsBinary","ExtensionFieldBinaryInfo","extensions","nanopbMsgopt","MessageOptions","nanopbEnumopt","EnumOptions","nanopb","FieldOptions","__createBinding","Object","create","o","m","k","k2","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__setModuleDefault","v","__importStar","mod","result","hasOwnProperty","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","next","e","rejected","done","then","apply","__importDefault","he","js_cookie_1","c","bootstrap","hFlash","$","val","flashState","StartOTA","handleReboot","link","removeClass","prop","delayReboot","get_control_option_value","ctrl","id","opt","attr","replace","includes","toString","handleNVSVisible","nvs_previous_checked","isEnabled","default","checkBoxElement","checked","recovery","show","hide","match","NVSType","console","log","hideSurrounding","parent","assign","String","args","number","index","parseInt","encodeHTML","encode","Date","toLocalShort","toLocaleString","dateStyle","timeStyle","btIcons","bt_playing","label","icon","bt_disconnected","bt_neutral","bt_connecting","bt_connected","bt_disabled","play_arrow","stop","batIcons","ranges","t","btStateIcons","sub","connectReturnCode","OK","FAIL","DISC","LOST","RESTORE","ETH","taskStates","NONE","REBOOT_TO_RECOVERY","SET_FWURL","FLASHING","DONE","UPLOADING","ERROR","UPLOADCOMPLETE","_state","olderRecovery","statusText","flashURL","flashFileName","statusPercent","Completed","prevRecovery","updateModal","Modal","document","getElementById","UpdateProgress","isStateError","html","isStateUploadComplete","isStateNone","isStateRebootRecovery","isStateSetUrl","isStateFlashing","isStateDone","isStateUploading","init","SetStateError","addClass","SetStateNone","SetStateRebootRecovery","SetStatusText","ajax","url","context","dataType","method","cache","contentType","JSON","stringify","timestamp","now","error","xhr","_ajaxOptions","thrownError","_a","setOTAError","status","complete","response","SetStateSetUrl","post_config","fwurl","SetStateFlashing","SetStateDone","SetStateUploading","SetStateUploadComplete","isFlashExecuting","keys","find","x","setOTATargets","fileInput","files","SetStatusPercent","ShowDialog","pct","pctChanged","txt","changed","css","text","logEvent","name","TargetReadyStartOTA","UploadLocalFile","xhttp","XMLHttpRequest","boundHandleUploadProgressEvent","HandleUploadProgressEvent","bind","boundsetOTAError","upload","addEventListener","onreadystatechange","readyState","open","send","Math","round","loaded","total","EventTargetStatus","_b","ota_pct","ota_dsc","EventOTAMessageClass","otaData","parse","fun","presetsloaded","is_i2c_locked","messageInterval","confPayload","config","handleExceptionResponse","parseSqueezeliteCommandLine","commandLine","options","output","otherValues","i","arg","startsWith","option","slice","join","trim","indexOf","substring","getOutput","n","getName","otherOptions","btname","toUpperCase","temp","isConnected","ConnectedTo","ip","getIcon","icons","handleTemplateTypeRadio","outtype","children","entries","commandDefaults","forEach","key","showLocalMessage","showCmdMessage","cmdname","msgtype","msgtext","append","color","escapedtext","releaseURL","messagesHeld","commandBTSinkName","i2s","C","W","Z","bt","SystemConfig","validOptions","codecs","apList","messagecount","messageseverity","LastCommandsState","NaN","ConnectingToSSID","hostName","versionName","prevmessage","project_name","depth","board_model","platform_name","preset_name","btSinkNamesOptSel","lmsBaseUrl","prevLMSIP","ConnectingToActions","promise","duration","setTimeout","reason","getConfigJson","slimMode","each","_index","element","entry","nvsTypeAttr","attributes","getNamedItem","nvsType","NVS_TYPE_I64","NVS_TYPE_I8","ota","empty","rdata","saveAutoexec1","resample","is","autoexec1","NVS_TYPE_STR","responseText","Result","setPlatformFilter","filter","trigger","renderError","fieldname","errorFieldName","errorField","field","after","rssiToIcon","rssi","refreshAP","urc","ajaxSetup","timeout","getJSON","ms","sort","y","refreshAPHTML2","formatAP","ssid","auth","rssi_icon","auth_icon","h","wifiSelector","prepend","siblings","first","rssiIconObj","iconTextContent","showTask","task","debug","nme","cpu","st","minstk","bprio","cprio","num","getBTSinkOpt","getMessages","msgAge","current_time","sent_time","msgTime","setTime","getTime","class","statsData","ntasks","tasks","taskList","showMessage","msgparts","split","sinkNameCtrl","attrs","j","item","curOpt","replaceWith","btEntry","btEntries","Array","from","rssiA","rssiB","fail","ajaxOptions","handleWifiDialog","gw","netmask","Action","STS","ap_ssid","ap_pwd","setIcons","offline","htmlEntry","textContent","getAttribute","handleNetworkStatus","hasConnectionChanged","pwd","dhcpname","assignStatusToNetworkConnection","checkStatus","handleRecoveryMode","tt","bt_status","bt_sub_status","iconIndex","handlebtstate","version","Voltage","bat_icon","voltage","iconEntry","entryRanges","min","max","batteryToIcon","lms_ip","lms_port","baseUrl","success","Number","Jack","getLongOps","longopts","severity","MESSAGING_INFO","MESSAGING_WARNING","MESSAGING_ERROR","setAttribute","on","stringVal","inputField","not","invalid","map","test","event","relatedTarget","CONN","MAN","_this","FileReader","file","fr","onload","target","ex","alert","readAsText","slideUp","slideDown","preventDefault","currentValue","originalValue","set","createElement","href","URL","createObjectURL","Blob","body","appendChild","click","removeChild","branches","release","branch","push","fwb","assets","asset","browser_download_url","namecomponents","ver","cfg","bits","substr","lastIndexOf","created_at","idf","trclass","remove","parsed","resampleValue","resampleInterpolation","u","s","processSqueezeliteCommandLine","replaceAll","title","gpioEntry","fixed","group","commands","command","cmdParts","isConfig","targetDiv","innerhtml","help","argtable","placeholder","datatype","ctrlname","curvalue","values","hasvalue","shortopts","checkbox","extraclass","mincount","glossary","choice","off","runCommand","ctrlselector","ctrlValue","_","jqxhr","textStatus","err","setURL","button","dataset","reboot","cmdstring","fields","allfields","querySelectorAll","selJson","cmd","model_config","storedval","handleHWPreset","qts","isSelect","tagName","hasValue","validVal","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","O","chunkIds","fn","priority","notFulfilled","Infinity","every","splice","r","d","definition","g","globalThis","Symbol","toStringTag","nmd","paths","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/components/wifi-manager/webapp/dist/js/node_vendors.bundle.js b/components/wifi-manager/webapp/dist/js/node_vendors.bundle.js new file mode 100644 index 00000000..e0f3b89d --- /dev/null +++ b/components/wifi-manager/webapp/dist/js/node_vendors.bundle.js @@ -0,0 +1,2 @@ +(self.webpackChunksqueezelite_esp32=self.webpackChunksqueezelite_esp32||[]).push([[987],{4537:e=>{"use strict";e.exports=function(e,t){var o=new Array(arguments.length-1),r=0,n=2,i=!0;for(;n{"use strict";var o=t;o.length=function(e){var t=e.length;if(!t)return 0;for(var o=0;--t%4>1&&"="===e.charAt(t);)++o;return Math.ceil(3*e.length)/4-o};for(var r=new Array(64),n=new Array(123),i=0;i<64;)n[r[i]=i<26?i+65:i<52?i+71:i<62?i-4:i-59|43]=i++;o.encode=function(e,t,o){for(var n,i=null,s=[],a=0,p=0;t>2],n=(3&l)<<4,p=1;break;case 1:s[a++]=r[n|l>>4],n=(15&l)<<2,p=2;break;case 2:s[a++]=r[n|l>>6],s[a++]=r[63&l],p=0}a>8191&&((i||(i=[])).push(String.fromCharCode.apply(String,s)),a=0)}return p&&(s[a++]=r[n],s[a++]=61,1===p&&(s[a++]=61)),i?(a&&i.push(String.fromCharCode.apply(String,s.slice(0,a))),i.join("")):String.fromCharCode.apply(String,s.slice(0,a))};var s="invalid encoding";o.decode=function(e,t,o){for(var r,i=o,a=0,p=0;p1)break;if(void 0===(l=n[l]))throw Error(s);switch(a){case 0:r=l,a=1;break;case 1:t[o++]=r<<2|(48&l)>>4,r=l,a=2;break;case 2:t[o++]=(15&r)<<4|(60&l)>>2,r=l,a=3;break;case 3:t[o++]=(3&r)<<6|l,a=0}}if(1===a)throw Error(s);return o-i},o.test=function(e){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}},5124:e=>{"use strict";function t(e,o){"string"==typeof e&&(o=e,e=void 0);var r=[];function n(e){if("string"!=typeof e){var o=i();if(t.verbose&&console.log("codegen: "+o),o="return "+o,e){for(var s=Object.keys(e),a=new Array(s.length+1),p=new Array(s.length),l=0;l{"use strict";function t(){this._listeners={}}e.exports=t,t.prototype.on=function(e,t,o){return(this._listeners[e]||(this._listeners[e]=[])).push({fn:t,ctx:o||this}),this},t.prototype.off=function(e,t){if(void 0===e)this._listeners={};else if(void 0===t)this._listeners[e]=[];else for(var o=this._listeners[e],r=0;r{"use strict";e.exports=i;var r=o(4537),n=o(7199)("fs");function i(e,t,o){return"function"==typeof t?(o=t,t={}):t||(t={}),o?!t.xhr&&n&&n.readFile?n.readFile(e,(function(r,n){return r&&"undefined"!=typeof XMLHttpRequest?i.xhr(e,t,o):r?o(r):o(null,t.binary?n:n.toString("utf8"))})):i.xhr(e,t,o):r(i,this,e,t)}i.xhr=function(e,t,o){var r=new XMLHttpRequest;r.onreadystatechange=function(){if(4===r.readyState){if(0!==r.status&&200!==r.status)return o(Error("status "+r.status));if(t.binary){var e=r.response;if(!e){e=[];for(var n=0;n{"use strict";function t(e){return"undefined"!=typeof Float32Array?function(){var t=new Float32Array([-0]),o=new Uint8Array(t.buffer),r=128===o[3];function n(e,r,n){t[0]=e,r[n]=o[0],r[n+1]=o[1],r[n+2]=o[2],r[n+3]=o[3]}function i(e,r,n){t[0]=e,r[n]=o[3],r[n+1]=o[2],r[n+2]=o[1],r[n+3]=o[0]}function s(e,r){return o[0]=e[r],o[1]=e[r+1],o[2]=e[r+2],o[3]=e[r+3],t[0]}function a(e,r){return o[3]=e[r],o[2]=e[r+1],o[1]=e[r+2],o[0]=e[r+3],t[0]}e.writeFloatLE=r?n:i,e.writeFloatBE=r?i:n,e.readFloatLE=r?s:a,e.readFloatBE=r?a:s}():function(){function t(e,t,o,r){var n=t<0?1:0;if(n&&(t=-t),0===t)e(1/t>0?0:2147483648,o,r);else if(isNaN(t))e(2143289344,o,r);else if(t>34028234663852886e22)e((n<<31|2139095040)>>>0,o,r);else if(t<11754943508222875e-54)e((n<<31|Math.round(t/1401298464324817e-60))>>>0,o,r);else{var i=Math.floor(Math.log(t)/Math.LN2);e((n<<31|i+127<<23|8388607&Math.round(t*Math.pow(2,-i)*8388608))>>>0,o,r)}}function s(e,t,o){var r=e(t,o),n=2*(r>>31)+1,i=r>>>23&255,s=8388607&r;return 255===i?s?NaN:n*(1/0):0===i?1401298464324817e-60*n*s:n*Math.pow(2,i-150)*(s+8388608)}e.writeFloatLE=t.bind(null,o),e.writeFloatBE=t.bind(null,r),e.readFloatLE=s.bind(null,n),e.readFloatBE=s.bind(null,i)}(),"undefined"!=typeof Float64Array?function(){var t=new Float64Array([-0]),o=new Uint8Array(t.buffer),r=128===o[7];function n(e,r,n){t[0]=e,r[n]=o[0],r[n+1]=o[1],r[n+2]=o[2],r[n+3]=o[3],r[n+4]=o[4],r[n+5]=o[5],r[n+6]=o[6],r[n+7]=o[7]}function i(e,r,n){t[0]=e,r[n]=o[7],r[n+1]=o[6],r[n+2]=o[5],r[n+3]=o[4],r[n+4]=o[3],r[n+5]=o[2],r[n+6]=o[1],r[n+7]=o[0]}function s(e,r){return o[0]=e[r],o[1]=e[r+1],o[2]=e[r+2],o[3]=e[r+3],o[4]=e[r+4],o[5]=e[r+5],o[6]=e[r+6],o[7]=e[r+7],t[0]}function a(e,r){return o[7]=e[r],o[6]=e[r+1],o[5]=e[r+2],o[4]=e[r+3],o[3]=e[r+4],o[2]=e[r+5],o[1]=e[r+6],o[0]=e[r+7],t[0]}e.writeDoubleLE=r?n:i,e.writeDoubleBE=r?i:n,e.readDoubleLE=r?s:a,e.readDoubleBE=r?a:s}():function(){function t(e,t,o,r,n,i){var s=r<0?1:0;if(s&&(r=-r),0===r)e(0,n,i+t),e(1/r>0?0:2147483648,n,i+o);else if(isNaN(r))e(0,n,i+t),e(2146959360,n,i+o);else if(r>17976931348623157e292)e(0,n,i+t),e((s<<31|2146435072)>>>0,n,i+o);else{var a;if(r<22250738585072014e-324)e((a=r/5e-324)>>>0,n,i+t),e((s<<31|a/4294967296)>>>0,n,i+o);else{var p=Math.floor(Math.log(r)/Math.LN2);1024===p&&(p=1023),e(4503599627370496*(a=r*Math.pow(2,-p))>>>0,n,i+t),e((s<<31|p+1023<<20|1048576*a&1048575)>>>0,n,i+o)}}}function s(e,t,o,r,n){var i=e(r,n+t),s=e(r,n+o),a=2*(s>>31)+1,p=s>>>20&2047,l=4294967296*(1048575&s)+i;return 2047===p?l?NaN:a*(1/0):0===p?5e-324*a*l:a*Math.pow(2,p-1075)*(l+4503599627370496)}e.writeDoubleLE=t.bind(null,o,0,4),e.writeDoubleBE=t.bind(null,r,4,0),e.readDoubleLE=s.bind(null,n,0,4),e.readDoubleBE=s.bind(null,i,4,0)}(),e}function o(e,t,o){t[o]=255&e,t[o+1]=e>>>8&255,t[o+2]=e>>>16&255,t[o+3]=e>>>24}function r(e,t,o){t[o]=e>>>24,t[o+1]=e>>>16&255,t[o+2]=e>>>8&255,t[o+3]=255&e}function n(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}function i(e,t){return(e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3])>>>0}e.exports=t(t)},7199:module=>{"use strict";function inquire(moduleName){try{var mod=eval("quire".replace(/^/,"re"))(moduleName);if(mod&&(mod.length||Object.keys(mod).length))return mod}catch(e){}return null}module.exports=inquire},8626:(e,t)=>{"use strict";var o=t,r=o.isAbsolute=function(e){return/^(?:\/|\w+:)/.test(e)},n=o.normalize=function(e){var t=(e=e.replace(/\\/g,"/").replace(/\/{2,}/g,"/")).split("/"),o=r(e),n="";o&&(n=t.shift()+"/");for(var i=0;i0&&".."!==t[i-1]?t.splice(--i,2):o?t.splice(i,1):++i:"."===t[i]?t.splice(i,1):++i;return n+t.join("/")};o.resolve=function(e,t,o){return o||(t=n(t)),r(t)?t:(o||(e=n(e)),(e=e.replace(/(?:\/|^)[^/]+$/,"")).length?n(e+"/"+t):t)}},6662:e=>{"use strict";e.exports=function(e,t,o){var r=o||8192,n=r>>>1,i=null,s=r;return function(o){if(o<1||o>n)return e(o);s+o>r&&(i=e(r),s=0);var a=t.call(i,s,s+=o);return 7&s&&(s=1+(7|s)),a}}},4997:(e,t)=>{"use strict";var o=t;o.length=function(e){for(var t=0,o=0,r=0;r191&&r<224?i[s++]=(31&r)<<6|63&e[t++]:r>239&&r<365?(r=((7&r)<<18|(63&e[t++])<<12|(63&e[t++])<<6|63&e[t++])-65536,i[s++]=55296+(r>>10),i[s++]=56320+(1023&r)):i[s++]=(15&r)<<12|(63&e[t++])<<6|63&e[t++],s>8191&&((n||(n=[])).push(String.fromCharCode.apply(String,i)),s=0);return n?(s&&n.push(String.fromCharCode.apply(String,i.slice(0,s))),n.join("")):String.fromCharCode.apply(String,i.slice(0,s))},o.write=function(e,t,o){for(var r,n,i=o,s=0;s>6|192,t[o++]=63&r|128):55296==(64512&r)&&56320==(64512&(n=e.charCodeAt(s+1)))?(r=65536+((1023&r)<<10)+(1023&n),++s,t[o++]=r>>18|240,t[o++]=r>>12&63|128,t[o++]=r>>6&63|128,t[o++]=63&r|128):(t[o++]=r>>12|224,t[o++]=r>>6&63|128,t[o++]=63&r|128);return o-i}},3138:(e,t,o)=>{"use strict";o.r(t),o.d(t,{Alert:()=>jt,Button:()=>Ft,Carousel:()=>po,Collapse:()=>To,Dropdown:()=>Yo,Modal:()=>Mr,Offcanvas:()=>$r,Popover:()=>bn,ScrollSpy:()=>Dn,Tab:()=>Jn,Toast:()=>ui,Tooltip:()=>dn});var r={};o.r(r),o.d(r,{afterMain:()=>T,afterRead:()=>v,afterWrite:()=>A,applyStyles:()=>P,arrow:()=>Q,auto:()=>p,basePlacements:()=>l,beforeMain:()=>E,beforeRead:()=>m,beforeWrite:()=>O,bottom:()=>i,clippingParents:()=>c,computeStyles:()=>re,createPopper:()=>Pe,createPopperBase:()=>xe,createPopperLite:()=>Ce,detectOverflow:()=>_e,end:()=>u,eventListeners:()=>ie,flip:()=>ve,hide:()=>Te,left:()=>a,main:()=>S,modifierPhases:()=>D,offset:()=>Oe,placements:()=>y,popper:()=>f,popperGenerator:()=>Re,popperOffsets:()=>we,preventOverflow:()=>Ae,read:()=>_,reference:()=>h,right:()=>s,start:()=>g,top:()=>n,variationPlacements:()=>b,viewport:()=>d,write:()=>w});var n="top",i="bottom",s="right",a="left",p="auto",l=[n,i,s,a],g="start",u="end",c="clippingParents",d="viewport",f="popper",h="reference",b=l.reduce((function(e,t){return e.concat([t+"-"+g,t+"-"+u])}),[]),y=[].concat(l,[p]).reduce((function(e,t){return e.concat([t,t+"-"+g,t+"-"+u])}),[]),m="beforeRead",_="read",v="afterRead",E="beforeMain",S="main",T="afterMain",O="beforeWrite",w="write",A="afterWrite",D=[m,_,v,E,S,T,O,w,A];function j(e){return e?(e.nodeName||"").toLowerCase():null}function M(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function F(e){return e instanceof M(e).Element||e instanceof Element}function R(e){return e instanceof M(e).HTMLElement||e instanceof HTMLElement}function x(e){return"undefined"!=typeof ShadowRoot&&(e instanceof M(e).ShadowRoot||e instanceof ShadowRoot)}const P={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var o=t.styles[e]||{},r=t.attributes[e]||{},n=t.elements[e];R(n)&&j(n)&&(Object.assign(n.style,o),Object.keys(r).forEach((function(e){var t=r[e];!1===t?n.removeAttribute(e):n.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,o={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,o.popper),t.styles=o,t.elements.arrow&&Object.assign(t.elements.arrow.style,o.arrow),function(){Object.keys(t.elements).forEach((function(e){var r=t.elements[e],n=t.attributes[e]||{},i=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:o[e]).reduce((function(e,t){return e[t]="",e}),{});R(r)&&j(r)&&(Object.assign(r.style,i),Object.keys(n).forEach((function(e){r.removeAttribute(e)})))}))}},requires:["computeStyles"]};function C(e){return e.split("-")[0]}var B=Math.max,N=Math.min,L=Math.round;function I(){var e=navigator.userAgentData;return null!=e&&e.brands&&Array.isArray(e.brands)?e.brands.map((function(e){return e.brand+"/"+e.version})).join(" "):navigator.userAgent}function U(){return!/^((?!chrome|android).)*safari/i.test(I())}function k(e,t,o){void 0===t&&(t=!1),void 0===o&&(o=!1);var r=e.getBoundingClientRect(),n=1,i=1;t&&R(e)&&(n=e.offsetWidth>0&&L(r.width)/e.offsetWidth||1,i=e.offsetHeight>0&&L(r.height)/e.offsetHeight||1);var s=(F(e)?M(e):window).visualViewport,a=!U()&&o,p=(r.left+(a&&s?s.offsetLeft:0))/n,l=(r.top+(a&&s?s.offsetTop:0))/i,g=r.width/n,u=r.height/i;return{width:g,height:u,top:l,right:p+g,bottom:l+u,left:p,x:p,y:l}}function W(e){var t=k(e),o=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-o)<=1&&(o=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:o,height:r}}function H(e,t){var o=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(o&&x(o)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function V(e){return M(e).getComputedStyle(e)}function q(e){return["table","td","th"].indexOf(j(e))>=0}function z(e){return((F(e)?e.ownerDocument:e.document)||window.document).documentElement}function G(e){return"html"===j(e)?e:e.assignedSlot||e.parentNode||(x(e)?e.host:null)||z(e)}function $(e){return R(e)&&"fixed"!==V(e).position?e.offsetParent:null}function Y(e){for(var t=M(e),o=$(e);o&&q(o)&&"static"===V(o).position;)o=$(o);return o&&("html"===j(o)||"body"===j(o)&&"static"===V(o).position)?t:o||function(e){var t=/firefox/i.test(I());if(/Trident/i.test(I())&&R(e)&&"fixed"===V(e).position)return null;var o=G(e);for(x(o)&&(o=o.host);R(o)&&["html","body"].indexOf(j(o))<0;){var r=V(o);if("none"!==r.transform||"none"!==r.perspective||"paint"===r.contain||-1!==["transform","perspective"].indexOf(r.willChange)||t&&"filter"===r.willChange||t&&r.filter&&"none"!==r.filter)return o;o=o.parentNode}return null}(e)||t}function K(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function J(e,t,o){return B(e,N(t,o))}function X(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function Z(e,t){return t.reduce((function(t,o){return t[o]=e,t}),{})}const Q={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,o=e.state,r=e.name,p=e.options,g=o.elements.arrow,u=o.modifiersData.popperOffsets,c=C(o.placement),d=K(c),f=[a,s].indexOf(c)>=0?"height":"width";if(g&&u){var h=function(e,t){return X("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:Z(e,l))}(p.padding,o),b=W(g),y="y"===d?n:a,m="y"===d?i:s,_=o.rects.reference[f]+o.rects.reference[d]-u[d]-o.rects.popper[f],v=u[d]-o.rects.reference[d],E=Y(g),S=E?"y"===d?E.clientHeight||0:E.clientWidth||0:0,T=_/2-v/2,O=h[y],w=S-b[f]-h[m],A=S/2-b[f]/2+T,D=J(O,A,w),j=d;o.modifiersData[r]=((t={})[j]=D,t.centerOffset=D-A,t)}},effect:function(e){var t=e.state,o=e.options.element,r=void 0===o?"[data-popper-arrow]":o;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&H(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ee(e){return e.split("-")[1]}var te={top:"auto",right:"auto",bottom:"auto",left:"auto"};function oe(e){var t,o=e.popper,r=e.popperRect,p=e.placement,l=e.variation,g=e.offsets,c=e.position,d=e.gpuAcceleration,f=e.adaptive,h=e.roundOffsets,b=e.isFixed,y=g.x,m=void 0===y?0:y,_=g.y,v=void 0===_?0:_,E="function"==typeof h?h({x:m,y:v}):{x:m,y:v};m=E.x,v=E.y;var S=g.hasOwnProperty("x"),T=g.hasOwnProperty("y"),O=a,w=n,A=window;if(f){var D=Y(o),j="clientHeight",F="clientWidth";if(D===M(o)&&"static"!==V(D=z(o)).position&&"absolute"===c&&(j="scrollHeight",F="scrollWidth"),p===n||(p===a||p===s)&&l===u)w=i,v-=(b&&D===A&&A.visualViewport?A.visualViewport.height:D[j])-r.height,v*=d?1:-1;if(p===a||(p===n||p===i)&&l===u)O=s,m-=(b&&D===A&&A.visualViewport?A.visualViewport.width:D[F])-r.width,m*=d?1:-1}var R,x=Object.assign({position:c},f&&te),P=!0===h?function(e,t){var o=e.x,r=e.y,n=t.devicePixelRatio||1;return{x:L(o*n)/n||0,y:L(r*n)/n||0}}({x:m,y:v},M(o)):{x:m,y:v};return m=P.x,v=P.y,d?Object.assign({},x,((R={})[w]=T?"0":"",R[O]=S?"0":"",R.transform=(A.devicePixelRatio||1)<=1?"translate("+m+"px, "+v+"px)":"translate3d("+m+"px, "+v+"px, 0)",R)):Object.assign({},x,((t={})[w]=T?v+"px":"",t[O]=S?m+"px":"",t.transform="",t))}const re={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,o=e.options,r=o.gpuAcceleration,n=void 0===r||r,i=o.adaptive,s=void 0===i||i,a=o.roundOffsets,p=void 0===a||a,l={placement:C(t.placement),variation:ee(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:n,isFixed:"fixed"===t.options.strategy};null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,oe(Object.assign({},l,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:s,roundOffsets:p})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,oe(Object.assign({},l,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:p})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}};var ne={passive:!0};const ie={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,o=e.instance,r=e.options,n=r.scroll,i=void 0===n||n,s=r.resize,a=void 0===s||s,p=M(t.elements.popper),l=[].concat(t.scrollParents.reference,t.scrollParents.popper);return i&&l.forEach((function(e){e.addEventListener("scroll",o.update,ne)})),a&&p.addEventListener("resize",o.update,ne),function(){i&&l.forEach((function(e){e.removeEventListener("scroll",o.update,ne)})),a&&p.removeEventListener("resize",o.update,ne)}},data:{}};var se={left:"right",right:"left",bottom:"top",top:"bottom"};function ae(e){return e.replace(/left|right|bottom|top/g,(function(e){return se[e]}))}var pe={start:"end",end:"start"};function le(e){return e.replace(/start|end/g,(function(e){return pe[e]}))}function ge(e){var t=M(e);return{scrollLeft:t.pageXOffset,scrollTop:t.pageYOffset}}function ue(e){return k(z(e)).left+ge(e).scrollLeft}function ce(e){var t=V(e),o=t.overflow,r=t.overflowX,n=t.overflowY;return/auto|scroll|overlay|hidden/.test(o+n+r)}function de(e){return["html","body","#document"].indexOf(j(e))>=0?e.ownerDocument.body:R(e)&&ce(e)?e:de(G(e))}function fe(e,t){var o;void 0===t&&(t=[]);var r=de(e),n=r===(null==(o=e.ownerDocument)?void 0:o.body),i=M(r),s=n?[i].concat(i.visualViewport||[],ce(r)?r:[]):r,a=t.concat(s);return n?a:a.concat(fe(G(s)))}function he(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function be(e,t,o){return t===d?he(function(e,t){var o=M(e),r=z(e),n=o.visualViewport,i=r.clientWidth,s=r.clientHeight,a=0,p=0;if(n){i=n.width,s=n.height;var l=U();(l||!l&&"fixed"===t)&&(a=n.offsetLeft,p=n.offsetTop)}return{width:i,height:s,x:a+ue(e),y:p}}(e,o)):F(t)?function(e,t){var o=k(e,!1,"fixed"===t);return o.top=o.top+e.clientTop,o.left=o.left+e.clientLeft,o.bottom=o.top+e.clientHeight,o.right=o.left+e.clientWidth,o.width=e.clientWidth,o.height=e.clientHeight,o.x=o.left,o.y=o.top,o}(t,o):he(function(e){var t,o=z(e),r=ge(e),n=null==(t=e.ownerDocument)?void 0:t.body,i=B(o.scrollWidth,o.clientWidth,n?n.scrollWidth:0,n?n.clientWidth:0),s=B(o.scrollHeight,o.clientHeight,n?n.scrollHeight:0,n?n.clientHeight:0),a=-r.scrollLeft+ue(e),p=-r.scrollTop;return"rtl"===V(n||o).direction&&(a+=B(o.clientWidth,n?n.clientWidth:0)-i),{width:i,height:s,x:a,y:p}}(z(e)))}function ye(e,t,o,r){var n="clippingParents"===t?function(e){var t=fe(G(e)),o=["absolute","fixed"].indexOf(V(e).position)>=0&&R(e)?Y(e):e;return F(o)?t.filter((function(e){return F(e)&&H(e,o)&&"body"!==j(e)})):[]}(e):[].concat(t),i=[].concat(n,[o]),s=i[0],a=i.reduce((function(t,o){var n=be(e,o,r);return t.top=B(n.top,t.top),t.right=N(n.right,t.right),t.bottom=N(n.bottom,t.bottom),t.left=B(n.left,t.left),t}),be(e,s,r));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}function me(e){var t,o=e.reference,r=e.element,p=e.placement,l=p?C(p):null,c=p?ee(p):null,d=o.x+o.width/2-r.width/2,f=o.y+o.height/2-r.height/2;switch(l){case n:t={x:d,y:o.y-r.height};break;case i:t={x:d,y:o.y+o.height};break;case s:t={x:o.x+o.width,y:f};break;case a:t={x:o.x-r.width,y:f};break;default:t={x:o.x,y:o.y}}var h=l?K(l):null;if(null!=h){var b="y"===h?"height":"width";switch(c){case g:t[h]=t[h]-(o[b]/2-r[b]/2);break;case u:t[h]=t[h]+(o[b]/2-r[b]/2)}}return t}function _e(e,t){void 0===t&&(t={});var o=t,r=o.placement,a=void 0===r?e.placement:r,p=o.strategy,g=void 0===p?e.strategy:p,u=o.boundary,b=void 0===u?c:u,y=o.rootBoundary,m=void 0===y?d:y,_=o.elementContext,v=void 0===_?f:_,E=o.altBoundary,S=void 0!==E&&E,T=o.padding,O=void 0===T?0:T,w=X("number"!=typeof O?O:Z(O,l)),A=v===f?h:f,D=e.rects.popper,j=e.elements[S?A:v],M=ye(F(j)?j:j.contextElement||z(e.elements.popper),b,m,g),R=k(e.elements.reference),x=me({reference:R,element:D,strategy:"absolute",placement:a}),P=he(Object.assign({},D,x)),C=v===f?P:R,B={top:M.top-C.top+w.top,bottom:C.bottom-M.bottom+w.bottom,left:M.left-C.left+w.left,right:C.right-M.right+w.right},N=e.modifiersData.offset;if(v===f&&N){var L=N[a];Object.keys(B).forEach((function(e){var t=[s,i].indexOf(e)>=0?1:-1,o=[n,i].indexOf(e)>=0?"y":"x";B[e]+=L[o]*t}))}return B}const ve={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,o=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var u=o.mainAxis,c=void 0===u||u,d=o.altAxis,f=void 0===d||d,h=o.fallbackPlacements,m=o.padding,_=o.boundary,v=o.rootBoundary,E=o.altBoundary,S=o.flipVariations,T=void 0===S||S,O=o.allowedAutoPlacements,w=t.options.placement,A=C(w),D=h||(A===w||!T?[ae(w)]:function(e){if(C(e)===p)return[];var t=ae(e);return[le(e),t,le(t)]}(w)),j=[w].concat(D).reduce((function(e,o){return e.concat(C(o)===p?function(e,t){void 0===t&&(t={});var o=t,r=o.placement,n=o.boundary,i=o.rootBoundary,s=o.padding,a=o.flipVariations,p=o.allowedAutoPlacements,g=void 0===p?y:p,u=ee(r),c=u?a?b:b.filter((function(e){return ee(e)===u})):l,d=c.filter((function(e){return g.indexOf(e)>=0}));0===d.length&&(d=c);var f=d.reduce((function(t,o){return t[o]=_e(e,{placement:o,boundary:n,rootBoundary:i,padding:s})[C(o)],t}),{});return Object.keys(f).sort((function(e,t){return f[e]-f[t]}))}(t,{placement:o,boundary:_,rootBoundary:v,padding:m,flipVariations:T,allowedAutoPlacements:O}):o)}),[]),M=t.rects.reference,F=t.rects.popper,R=new Map,x=!0,P=j[0],B=0;B=0,k=U?"width":"height",W=_e(t,{placement:N,boundary:_,rootBoundary:v,altBoundary:E,padding:m}),H=U?I?s:a:I?i:n;M[k]>F[k]&&(H=ae(H));var V=ae(H),q=[];if(c&&q.push(W[L]<=0),f&&q.push(W[H]<=0,W[V]<=0),q.every((function(e){return e}))){P=N,x=!1;break}R.set(N,q)}if(x)for(var z=function(e){var t=j.find((function(t){var o=R.get(t);if(o)return o.slice(0,e).every((function(e){return e}))}));if(t)return P=t,"break"},G=T?3:1;G>0;G--){if("break"===z(G))break}t.placement!==P&&(t.modifiersData[r]._skip=!0,t.placement=P,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Ee(e,t,o){return void 0===o&&(o={x:0,y:0}),{top:e.top-t.height-o.y,right:e.right-t.width+o.x,bottom:e.bottom-t.height+o.y,left:e.left-t.width-o.x}}function Se(e){return[n,s,i,a].some((function(t){return e[t]>=0}))}const Te={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,o=e.name,r=t.rects.reference,n=t.rects.popper,i=t.modifiersData.preventOverflow,s=_e(t,{elementContext:"reference"}),a=_e(t,{altBoundary:!0}),p=Ee(s,r),l=Ee(a,n,i),g=Se(p),u=Se(l);t.modifiersData[o]={referenceClippingOffsets:p,popperEscapeOffsets:l,isReferenceHidden:g,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":g,"data-popper-escaped":u})}};const Oe={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,o=e.options,r=e.name,i=o.offset,p=void 0===i?[0,0]:i,l=y.reduce((function(e,o){return e[o]=function(e,t,o){var r=C(e),i=[a,n].indexOf(r)>=0?-1:1,p="function"==typeof o?o(Object.assign({},t,{placement:e})):o,l=p[0],g=p[1];return l=l||0,g=(g||0)*i,[a,s].indexOf(r)>=0?{x:g,y:l}:{x:l,y:g}}(o,t.rects,p),e}),{}),g=l[t.placement],u=g.x,c=g.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=u,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=l}};const we={name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state,o=e.name;t.modifiersData[o]=me({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}};const Ae={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,o=e.options,r=e.name,p=o.mainAxis,l=void 0===p||p,u=o.altAxis,c=void 0!==u&&u,d=o.boundary,f=o.rootBoundary,h=o.altBoundary,b=o.padding,y=o.tether,m=void 0===y||y,_=o.tetherOffset,v=void 0===_?0:_,E=_e(t,{boundary:d,rootBoundary:f,padding:b,altBoundary:h}),S=C(t.placement),T=ee(t.placement),O=!T,w=K(S),A="x"===w?"y":"x",D=t.modifiersData.popperOffsets,j=t.rects.reference,M=t.rects.popper,F="function"==typeof v?v(Object.assign({},t.rects,{placement:t.placement})):v,R="number"==typeof F?{mainAxis:F,altAxis:F}:Object.assign({mainAxis:0,altAxis:0},F),x=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,P={x:0,y:0};if(D){if(l){var L,I="y"===w?n:a,U="y"===w?i:s,k="y"===w?"height":"width",H=D[w],V=H+E[I],q=H-E[U],z=m?-M[k]/2:0,G=T===g?j[k]:M[k],$=T===g?-M[k]:-j[k],X=t.elements.arrow,Z=m&&X?W(X):{width:0,height:0},Q=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=Q[I],oe=Q[U],re=J(0,j[k],Z[k]),ne=O?j[k]/2-z-re-te-R.mainAxis:G-re-te-R.mainAxis,ie=O?-j[k]/2+z+re+oe+R.mainAxis:$+re+oe+R.mainAxis,se=t.elements.arrow&&Y(t.elements.arrow),ae=se?"y"===w?se.clientTop||0:se.clientLeft||0:0,pe=null!=(L=null==x?void 0:x[w])?L:0,le=H+ie-pe,ge=J(m?N(V,H+ne-pe-ae):V,H,m?B(q,le):q);D[w]=ge,P[w]=ge-H}if(c){var ue,ce="x"===w?n:a,de="x"===w?i:s,fe=D[A],he="y"===A?"height":"width",be=fe+E[ce],ye=fe-E[de],me=-1!==[n,a].indexOf(S),ve=null!=(ue=null==x?void 0:x[A])?ue:0,Ee=me?be:fe-j[he]-M[he]-ve+R.altAxis,Se=me?fe+j[he]+M[he]-ve-R.altAxis:ye,Te=m&&me?function(e,t,o){var r=J(e,t,o);return r>o?o:r}(Ee,fe,Se):J(m?Ee:be,fe,m?Se:ye);D[A]=Te,P[A]=Te-fe}t.modifiersData[r]=P}},requiresIfExists:["offset"]};function De(e,t,o){void 0===o&&(o=!1);var r,n,i=R(t),s=R(t)&&function(e){var t=e.getBoundingClientRect(),o=L(t.width)/e.offsetWidth||1,r=L(t.height)/e.offsetHeight||1;return 1!==o||1!==r}(t),a=z(t),p=k(e,s,o),l={scrollLeft:0,scrollTop:0},g={x:0,y:0};return(i||!i&&!o)&&(("body"!==j(t)||ce(a))&&(l=(r=t)!==M(r)&&R(r)?{scrollLeft:(n=r).scrollLeft,scrollTop:n.scrollTop}:ge(r)),R(t)?((g=k(t,!0)).x+=t.clientLeft,g.y+=t.clientTop):a&&(g.x=ue(a))),{x:p.left+l.scrollLeft-g.x,y:p.top+l.scrollTop-g.y,width:p.width,height:p.height}}function je(e){var t=new Map,o=new Set,r=[];function n(e){o.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!o.has(e)){var r=t.get(e);r&&n(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){o.has(e.name)||n(e)})),r}var Me={placement:"bottom",modifiers:[],strategy:"absolute"};function Fe(){for(var e=arguments.length,t=new Array(e),o=0;oBe.has(e)&&Be.get(e).get(t)||null,remove(e,t){if(!Be.has(e))return;const o=Be.get(e);o.delete(t),0===o.size&&Be.delete(e)}},Le="transitionend",Ie=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,((e,t)=>`#${CSS.escape(t)}`))),e),Ue=e=>{e.dispatchEvent(new Event(Le))},ke=e=>!(!e||"object"!=typeof e)&&(void 0!==e.jquery&&(e=e[0]),void 0!==e.nodeType),We=e=>ke(e)?e.jquery?e[0]:e:"string"==typeof e&&e.length>0?document.querySelector(Ie(e)):null,He=e=>{if(!ke(e)||0===e.getClientRects().length)return!1;const t="visible"===getComputedStyle(e).getPropertyValue("visibility"),o=e.closest("details:not([open])");if(!o)return t;if(o!==e){const t=e.closest("summary");if(t&&t.parentNode!==o)return!1;if(null===t)return!1}return t},Ve=e=>!e||e.nodeType!==Node.ELEMENT_NODE||(!!e.classList.contains("disabled")||(void 0!==e.disabled?e.disabled:e.hasAttribute("disabled")&&"false"!==e.getAttribute("disabled"))),qe=e=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof e.getRootNode){const t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?qe(e.parentNode):null},ze=()=>{},Ge=e=>{e.offsetHeight},$e=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,Ye=[],Ke=()=>"rtl"===document.documentElement.dir,Je=e=>{var t;t=()=>{const t=$e();if(t){const o=e.NAME,r=t.fn[o];t.fn[o]=e.jQueryInterface,t.fn[o].Constructor=e,t.fn[o].noConflict=()=>(t.fn[o]=r,e.jQueryInterface)}},"loading"===document.readyState?(Ye.length||document.addEventListener("DOMContentLoaded",(()=>{for(const e of Ye)e()})),Ye.push(t)):t()},Xe=(e,t=[],o=e)=>"function"==typeof e?e(...t):o,Ze=(e,t,o=!0)=>{if(!o)return void Xe(e);const r=(e=>{if(!e)return 0;let{transitionDuration:t,transitionDelay:o}=window.getComputedStyle(e);const r=Number.parseFloat(t),n=Number.parseFloat(o);return r||n?(t=t.split(",")[0],o=o.split(",")[0],1e3*(Number.parseFloat(t)+Number.parseFloat(o))):0})(t)+5;let n=!1;const i=({target:o})=>{o===t&&(n=!0,t.removeEventListener(Le,i),Xe(e))};t.addEventListener(Le,i),setTimeout((()=>{n||Ue(t)}),r)},Qe=(e,t,o,r)=>{const n=e.length;let i=e.indexOf(t);return-1===i?!o&&r?e[n-1]:e[0]:(i+=o?1:-1,r&&(i=(i+n)%n),e[Math.max(0,Math.min(i,n-1))])},et=/[^.]*(?=\..*)\.|.*/,tt=/\..*/,ot=/::\d+$/,rt={};let nt=1;const it={mouseenter:"mouseover",mouseleave:"mouseout"},st=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function at(e,t){return t&&`${t}::${nt++}`||e.uidEvent||nt++}function pt(e){const t=at(e);return e.uidEvent=t,rt[t]=rt[t]||{},rt[t]}function lt(e,t,o=null){return Object.values(e).find((e=>e.callable===t&&e.delegationSelector===o))}function gt(e,t,o){const r="string"==typeof t,n=r?o:t||o;let i=ft(e);return st.has(i)||(i=e),[r,n,i]}function ut(e,t,o,r,n){if("string"!=typeof t||!e)return;let[i,s,a]=gt(t,o,r);if(t in it){const e=e=>function(t){if(!t.relatedTarget||t.relatedTarget!==t.delegateTarget&&!t.delegateTarget.contains(t.relatedTarget))return e.call(this,t)};s=e(s)}const p=pt(e),l=p[a]||(p[a]={}),g=lt(l,s,i?o:null);if(g)return void(g.oneOff=g.oneOff&&n);const u=at(s,t.replace(et,"")),c=i?function(e,t,o){return function r(n){const i=e.querySelectorAll(t);for(let{target:s}=n;s&&s!==this;s=s.parentNode)for(const a of i)if(a===s)return bt(n,{delegateTarget:s}),r.oneOff&&ht.off(e,n.type,t,o),o.apply(s,[n])}}(e,o,s):function(e,t){return function o(r){return bt(r,{delegateTarget:e}),o.oneOff&&ht.off(e,r.type,t),t.apply(e,[r])}}(e,s);c.delegationSelector=i?o:null,c.callable=s,c.oneOff=n,c.uidEvent=u,l[u]=c,e.addEventListener(a,c,i)}function ct(e,t,o,r,n){const i=lt(t[o],r,n);i&&(e.removeEventListener(o,i,Boolean(n)),delete t[o][i.uidEvent])}function dt(e,t,o,r){const n=t[o]||{};for(const[i,s]of Object.entries(n))i.includes(r)&&ct(e,t,o,s.callable,s.delegationSelector)}function ft(e){return e=e.replace(tt,""),it[e]||e}const ht={on(e,t,o,r){ut(e,t,o,r,!1)},one(e,t,o,r){ut(e,t,o,r,!0)},off(e,t,o,r){if("string"!=typeof t||!e)return;const[n,i,s]=gt(t,o,r),a=s!==t,p=pt(e),l=p[s]||{},g=t.startsWith(".");if(void 0===i){if(g)for(const o of Object.keys(p))dt(e,p,o,t.slice(1));for(const[o,r]of Object.entries(l)){const n=o.replace(ot,"");a&&!t.includes(n)||ct(e,p,s,r.callable,r.delegationSelector)}}else{if(!Object.keys(l).length)return;ct(e,p,s,i,n?o:null)}},trigger(e,t,o){if("string"!=typeof t||!e)return null;const r=$e();let n=null,i=!0,s=!0,a=!1;t!==ft(t)&&r&&(n=r.Event(t,o),r(e).trigger(n),i=!n.isPropagationStopped(),s=!n.isImmediatePropagationStopped(),a=n.isDefaultPrevented());const p=bt(new Event(t,{bubbles:i,cancelable:!0}),o);return a&&p.preventDefault(),s&&e.dispatchEvent(p),p.defaultPrevented&&n&&n.preventDefault(),p}};function bt(e,t={}){for(const[o,r]of Object.entries(t))try{e[o]=r}catch(t){Object.defineProperty(e,o,{configurable:!0,get:()=>r})}return e}function yt(e){if("true"===e)return!0;if("false"===e)return!1;if(e===Number(e).toString())return Number(e);if(""===e||"null"===e)return null;if("string"!=typeof e)return e;try{return JSON.parse(decodeURIComponent(e))}catch(t){return e}}function mt(e){return e.replace(/[A-Z]/g,(e=>`-${e.toLowerCase()}`))}const _t={setDataAttribute(e,t,o){e.setAttribute(`data-bs-${mt(t)}`,o)},removeDataAttribute(e,t){e.removeAttribute(`data-bs-${mt(t)}`)},getDataAttributes(e){if(!e)return{};const t={},o=Object.keys(e.dataset).filter((e=>e.startsWith("bs")&&!e.startsWith("bsConfig")));for(const r of o){let o=r.replace(/^bs/,"");o=o.charAt(0).toLowerCase()+o.slice(1,o.length),t[o]=yt(e.dataset[r])}return t},getDataAttribute:(e,t)=>yt(e.getAttribute(`data-bs-${mt(t)}`))};class vt{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(e){return e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e}_mergeConfigObj(e,t){const o=ke(t)?_t.getDataAttribute(t,"config"):{};return{...this.constructor.Default,..."object"==typeof o?o:{},...ke(t)?_t.getDataAttributes(t):{},..."object"==typeof e?e:{}}}_typeCheckConfig(e,t=this.constructor.DefaultType){for(const[r,n]of Object.entries(t)){const t=e[r],i=ke(t)?"element":null==(o=t)?`${o}`:Object.prototype.toString.call(o).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(n).test(i))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${r}" provided type "${i}" but expected type "${n}".`)}var o}}class Et extends vt{constructor(e,t){super(),(e=We(e))&&(this._element=e,this._config=this._getConfig(t),Ne.set(this._element,this.constructor.DATA_KEY,this))}dispose(){Ne.remove(this._element,this.constructor.DATA_KEY),ht.off(this._element,this.constructor.EVENT_KEY);for(const e of Object.getOwnPropertyNames(this))this[e]=null}_queueCallback(e,t,o=!0){Ze(e,t,o)}_getConfig(e){return e=this._mergeConfigObj(e,this._element),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}static getInstance(e){return Ne.get(We(e),this.DATA_KEY)}static getOrCreateInstance(e,t={}){return this.getInstance(e)||new this(e,"object"==typeof t?t:null)}static get VERSION(){return"5.3.2"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(e){return`${e}${this.EVENT_KEY}`}}const St=e=>{let t=e.getAttribute("data-bs-target");if(!t||"#"===t){let o=e.getAttribute("href");if(!o||!o.includes("#")&&!o.startsWith("."))return null;o.includes("#")&&!o.startsWith("#")&&(o=`#${o.split("#")[1]}`),t=o&&"#"!==o?Ie(o.trim()):null}return t},Tt={find:(e,t=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(t,e)),findOne:(e,t=document.documentElement)=>Element.prototype.querySelector.call(t,e),children:(e,t)=>[].concat(...e.children).filter((e=>e.matches(t))),parents(e,t){const o=[];let r=e.parentNode.closest(t);for(;r;)o.push(r),r=r.parentNode.closest(t);return o},prev(e,t){let o=e.previousElementSibling;for(;o;){if(o.matches(t))return[o];o=o.previousElementSibling}return[]},next(e,t){let o=e.nextElementSibling;for(;o;){if(o.matches(t))return[o];o=o.nextElementSibling}return[]},focusableChildren(e){const t=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((e=>`${e}:not([tabindex^="-"])`)).join(",");return this.find(t,e).filter((e=>!Ve(e)&&He(e)))},getSelectorFromElement(e){const t=St(e);return t&&Tt.findOne(t)?t:null},getElementFromSelector(e){const t=St(e);return t?Tt.findOne(t):null},getMultipleElementsFromSelector(e){const t=St(e);return t?Tt.find(t):[]}},Ot=(e,t="hide")=>{const o=`click.dismiss${e.EVENT_KEY}`,r=e.NAME;ht.on(document,o,`[data-bs-dismiss="${r}"]`,(function(o){if(["A","AREA"].includes(this.tagName)&&o.preventDefault(),Ve(this))return;const n=Tt.getElementFromSelector(this)||this.closest(`.${r}`);e.getOrCreateInstance(n)[t]()}))},wt=".bs.alert",At=`close${wt}`,Dt=`closed${wt}`;class jt extends Et{static get NAME(){return"alert"}close(){if(ht.trigger(this._element,At).defaultPrevented)return;this._element.classList.remove("show");const e=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,e)}_destroyElement(){this._element.remove(),ht.trigger(this._element,Dt),this.dispose()}static jQueryInterface(e){return this.each((function(){const t=jt.getOrCreateInstance(this);if("string"==typeof e){if(void 0===t[e]||e.startsWith("_")||"constructor"===e)throw new TypeError(`No method named "${e}"`);t[e](this)}}))}}Ot(jt,"close"),Je(jt);const Mt='[data-bs-toggle="button"]';class Ft extends Et{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(e){return this.each((function(){const t=Ft.getOrCreateInstance(this);"toggle"===e&&t[e]()}))}}ht.on(document,"click.bs.button.data-api",Mt,(e=>{e.preventDefault();const t=e.target.closest(Mt);Ft.getOrCreateInstance(t).toggle()})),Je(Ft);const Rt=".bs.swipe",xt=`touchstart${Rt}`,Pt=`touchmove${Rt}`,Ct=`touchend${Rt}`,Bt=`pointerdown${Rt}`,Nt=`pointerup${Rt}`,Lt={endCallback:null,leftCallback:null,rightCallback:null},It={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class Ut extends vt{constructor(e,t){super(),this._element=e,e&&Ut.isSupported()&&(this._config=this._getConfig(t),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return Lt}static get DefaultType(){return It}static get NAME(){return"swipe"}dispose(){ht.off(this._element,Rt)}_start(e){this._supportPointerEvents?this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX):this._deltaX=e.touches[0].clientX}_end(e){this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX-this._deltaX),this._handleSwipe(),Xe(this._config.endCallback)}_move(e){this._deltaX=e.touches&&e.touches.length>1?0:e.touches[0].clientX-this._deltaX}_handleSwipe(){const e=Math.abs(this._deltaX);if(e<=40)return;const t=e/this._deltaX;this._deltaX=0,t&&Xe(t>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(ht.on(this._element,Bt,(e=>this._start(e))),ht.on(this._element,Nt,(e=>this._end(e))),this._element.classList.add("pointer-event")):(ht.on(this._element,xt,(e=>this._start(e))),ht.on(this._element,Pt,(e=>this._move(e))),ht.on(this._element,Ct,(e=>this._end(e))))}_eventIsPointerPenTouch(e){return this._supportPointerEvents&&("pen"===e.pointerType||"touch"===e.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const kt=".bs.carousel",Wt=".data-api",Ht="next",Vt="prev",qt="left",zt="right",Gt=`slide${kt}`,$t=`slid${kt}`,Yt=`keydown${kt}`,Kt=`mouseenter${kt}`,Jt=`mouseleave${kt}`,Xt=`dragstart${kt}`,Zt=`load${kt}${Wt}`,Qt=`click${kt}${Wt}`,eo="carousel",to="active",oo=".active",ro=".carousel-item",no=oo+ro,io={ArrowLeft:zt,ArrowRight:qt},so={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},ao={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class po extends Et{constructor(e,t){super(e,t),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=Tt.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===eo&&this.cycle()}static get Default(){return so}static get DefaultType(){return ao}static get NAME(){return"carousel"}next(){this._slide(Ht)}nextWhenVisible(){!document.hidden&&He(this._element)&&this.next()}prev(){this._slide(Vt)}pause(){this._isSliding&&Ue(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?ht.one(this._element,$t,(()=>this.cycle())):this.cycle())}to(e){const t=this._getItems();if(e>t.length-1||e<0)return;if(this._isSliding)return void ht.one(this._element,$t,(()=>this.to(e)));const o=this._getItemIndex(this._getActive());if(o===e)return;const r=e>o?Ht:Vt;this._slide(r,t[e])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(e){return e.defaultInterval=e.interval,e}_addEventListeners(){this._config.keyboard&&ht.on(this._element,Yt,(e=>this._keydown(e))),"hover"===this._config.pause&&(ht.on(this._element,Kt,(()=>this.pause())),ht.on(this._element,Jt,(()=>this._maybeEnableCycle()))),this._config.touch&&Ut.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const e of Tt.find(".carousel-item img",this._element))ht.on(e,Xt,(e=>e.preventDefault()));const e={leftCallback:()=>this._slide(this._directionToOrder(qt)),rightCallback:()=>this._slide(this._directionToOrder(zt)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new Ut(this._element,e)}_keydown(e){if(/input|textarea/i.test(e.target.tagName))return;const t=io[e.key];t&&(e.preventDefault(),this._slide(this._directionToOrder(t)))}_getItemIndex(e){return this._getItems().indexOf(e)}_setActiveIndicatorElement(e){if(!this._indicatorsElement)return;const t=Tt.findOne(oo,this._indicatorsElement);t.classList.remove(to),t.removeAttribute("aria-current");const o=Tt.findOne(`[data-bs-slide-to="${e}"]`,this._indicatorsElement);o&&(o.classList.add(to),o.setAttribute("aria-current","true"))}_updateInterval(){const e=this._activeElement||this._getActive();if(!e)return;const t=Number.parseInt(e.getAttribute("data-bs-interval"),10);this._config.interval=t||this._config.defaultInterval}_slide(e,t=null){if(this._isSliding)return;const o=this._getActive(),r=e===Ht,n=t||Qe(this._getItems(),o,r,this._config.wrap);if(n===o)return;const i=this._getItemIndex(n),s=t=>ht.trigger(this._element,t,{relatedTarget:n,direction:this._orderToDirection(e),from:this._getItemIndex(o),to:i});if(s(Gt).defaultPrevented)return;if(!o||!n)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(i),this._activeElement=n;const p=r?"carousel-item-start":"carousel-item-end",l=r?"carousel-item-next":"carousel-item-prev";n.classList.add(l),Ge(n),o.classList.add(p),n.classList.add(p);this._queueCallback((()=>{n.classList.remove(p,l),n.classList.add(to),o.classList.remove(to,l,p),this._isSliding=!1,s($t)}),o,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return Tt.findOne(no,this._element)}_getItems(){return Tt.find(ro,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(e){return Ke()?e===qt?Vt:Ht:e===qt?Ht:Vt}_orderToDirection(e){return Ke()?e===Vt?qt:zt:e===Vt?zt:qt}static jQueryInterface(e){return this.each((function(){const t=po.getOrCreateInstance(this,e);if("number"!=typeof e){if("string"==typeof e){if(void 0===t[e]||e.startsWith("_")||"constructor"===e)throw new TypeError(`No method named "${e}"`);t[e]()}}else t.to(e)}))}}ht.on(document,Qt,"[data-bs-slide], [data-bs-slide-to]",(function(e){const t=Tt.getElementFromSelector(this);if(!t||!t.classList.contains(eo))return;e.preventDefault();const o=po.getOrCreateInstance(t),r=this.getAttribute("data-bs-slide-to");return r?(o.to(r),void o._maybeEnableCycle()):"next"===_t.getDataAttribute(this,"slide")?(o.next(),void o._maybeEnableCycle()):(o.prev(),void o._maybeEnableCycle())})),ht.on(window,Zt,(()=>{const e=Tt.find('[data-bs-ride="carousel"]');for(const t of e)po.getOrCreateInstance(t)})),Je(po);const lo=".bs.collapse",go=`show${lo}`,uo=`shown${lo}`,co=`hide${lo}`,fo=`hidden${lo}`,ho=`click${lo}.data-api`,bo="show",yo="collapse",mo="collapsing",_o=`:scope .${yo} .${yo}`,vo='[data-bs-toggle="collapse"]',Eo={parent:null,toggle:!0},So={parent:"(null|element)",toggle:"boolean"};class To extends Et{constructor(e,t){super(e,t),this._isTransitioning=!1,this._triggerArray=[];const o=Tt.find(vo);for(const e of o){const t=Tt.getSelectorFromElement(e),o=Tt.find(t).filter((e=>e===this._element));null!==t&&o.length&&this._triggerArray.push(e)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Eo}static get DefaultType(){return So}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let e=[];if(this._config.parent&&(e=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((e=>e!==this._element)).map((e=>To.getOrCreateInstance(e,{toggle:!1})))),e.length&&e[0]._isTransitioning)return;if(ht.trigger(this._element,go).defaultPrevented)return;for(const t of e)t.hide();const t=this._getDimension();this._element.classList.remove(yo),this._element.classList.add(mo),this._element.style[t]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const o=`scroll${t[0].toUpperCase()+t.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(mo),this._element.classList.add(yo,bo),this._element.style[t]="",ht.trigger(this._element,uo)}),this._element,!0),this._element.style[t]=`${this._element[o]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(ht.trigger(this._element,co).defaultPrevented)return;const e=this._getDimension();this._element.style[e]=`${this._element.getBoundingClientRect()[e]}px`,Ge(this._element),this._element.classList.add(mo),this._element.classList.remove(yo,bo);for(const e of this._triggerArray){const t=Tt.getElementFromSelector(e);t&&!this._isShown(t)&&this._addAriaAndCollapsedClass([e],!1)}this._isTransitioning=!0;this._element.style[e]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(mo),this._element.classList.add(yo),ht.trigger(this._element,fo)}),this._element,!0)}_isShown(e=this._element){return e.classList.contains(bo)}_configAfterMerge(e){return e.toggle=Boolean(e.toggle),e.parent=We(e.parent),e}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const e=this._getFirstLevelChildren(vo);for(const t of e){const e=Tt.getElementFromSelector(t);e&&this._addAriaAndCollapsedClass([t],this._isShown(e))}}_getFirstLevelChildren(e){const t=Tt.find(_o,this._config.parent);return Tt.find(e,this._config.parent).filter((e=>!t.includes(e)))}_addAriaAndCollapsedClass(e,t){if(e.length)for(const o of e)o.classList.toggle("collapsed",!t),o.setAttribute("aria-expanded",t)}static jQueryInterface(e){const t={};return"string"==typeof e&&/show|hide/.test(e)&&(t.toggle=!1),this.each((function(){const o=To.getOrCreateInstance(this,t);if("string"==typeof e){if(void 0===o[e])throw new TypeError(`No method named "${e}"`);o[e]()}}))}}ht.on(document,ho,vo,(function(e){("A"===e.target.tagName||e.delegateTarget&&"A"===e.delegateTarget.tagName)&&e.preventDefault();for(const e of Tt.getMultipleElementsFromSelector(this))To.getOrCreateInstance(e,{toggle:!1}).toggle()})),Je(To);const Oo="dropdown",wo=".bs.dropdown",Ao=".data-api",Do="ArrowUp",jo="ArrowDown",Mo=`hide${wo}`,Fo=`hidden${wo}`,Ro=`show${wo}`,xo=`shown${wo}`,Po=`click${wo}${Ao}`,Co=`keydown${wo}${Ao}`,Bo=`keyup${wo}${Ao}`,No="show",Lo='[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)',Io=`${Lo}.${No}`,Uo=".dropdown-menu",ko=Ke()?"top-end":"top-start",Wo=Ke()?"top-start":"top-end",Ho=Ke()?"bottom-end":"bottom-start",Vo=Ke()?"bottom-start":"bottom-end",qo=Ke()?"left-start":"right-start",zo=Ke()?"right-start":"left-start",Go={autoClose:!0,boundary:"clippingParents",display:"dynamic",offset:[0,2],popperConfig:null,reference:"toggle"},$o={autoClose:"(boolean|string)",boundary:"(string|element)",display:"string",offset:"(array|string|function)",popperConfig:"(null|object|function)",reference:"(string|element|object)"};class Yo extends Et{constructor(e,t){super(e,t),this._popper=null,this._parent=this._element.parentNode,this._menu=Tt.next(this._element,Uo)[0]||Tt.prev(this._element,Uo)[0]||Tt.findOne(Uo,this._parent),this._inNavbar=this._detectNavbar()}static get Default(){return Go}static get DefaultType(){return $o}static get NAME(){return Oo}toggle(){return this._isShown()?this.hide():this.show()}show(){if(Ve(this._element)||this._isShown())return;const e={relatedTarget:this._element};if(!ht.trigger(this._element,Ro,e).defaultPrevented){if(this._createPopper(),"ontouchstart"in document.documentElement&&!this._parent.closest(".navbar-nav"))for(const e of[].concat(...document.body.children))ht.on(e,"mouseover",ze);this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(No),this._element.classList.add(No),ht.trigger(this._element,xo,e)}}hide(){if(Ve(this._element)||!this._isShown())return;const e={relatedTarget:this._element};this._completeHide(e)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(e){if(!ht.trigger(this._element,Mo,e).defaultPrevented){if("ontouchstart"in document.documentElement)for(const e of[].concat(...document.body.children))ht.off(e,"mouseover",ze);this._popper&&this._popper.destroy(),this._menu.classList.remove(No),this._element.classList.remove(No),this._element.setAttribute("aria-expanded","false"),_t.removeDataAttribute(this._menu,"popper"),ht.trigger(this._element,Fo,e)}}_getConfig(e){if("object"==typeof(e=super._getConfig(e)).reference&&!ke(e.reference)&&"function"!=typeof e.reference.getBoundingClientRect)throw new TypeError(`${Oo.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return e}_createPopper(){if(void 0===r)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=this._parent:ke(this._config.reference)?e=We(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const t=this._getPopperConfig();this._popper=Pe(e,this._menu,t)}_isShown(){return this._menu.classList.contains(No)}_getPlacement(){const e=this._parent;if(e.classList.contains("dropend"))return qo;if(e.classList.contains("dropstart"))return zo;if(e.classList.contains("dropup-center"))return"top";if(e.classList.contains("dropdown-center"))return"bottom";const t="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return e.classList.contains("dropup")?t?Wo:ko:t?Vo:Ho}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:e}=this._config;return"string"==typeof e?e.split(",").map((e=>Number.parseInt(e,10))):"function"==typeof e?t=>e(t,this._element):e}_getPopperConfig(){const e={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(_t.setDataAttribute(this._menu,"popper","static"),e.modifiers=[{name:"applyStyles",enabled:!1}]),{...e,...Xe(this._config.popperConfig,[e])}}_selectMenuItem({key:e,target:t}){const o=Tt.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((e=>He(e)));o.length&&Qe(o,t,e===jo,!o.includes(t)).focus()}static jQueryInterface(e){return this.each((function(){const t=Yo.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e])throw new TypeError(`No method named "${e}"`);t[e]()}}))}static clearMenus(e){if(2===e.button||"keyup"===e.type&&"Tab"!==e.key)return;const t=Tt.find(Io);for(const o of t){const t=Yo.getInstance(o);if(!t||!1===t._config.autoClose)continue;const r=e.composedPath(),n=r.includes(t._menu);if(r.includes(t._element)||"inside"===t._config.autoClose&&!n||"outside"===t._config.autoClose&&n)continue;if(t._menu.contains(e.target)&&("keyup"===e.type&&"Tab"===e.key||/input|select|option|textarea|form/i.test(e.target.tagName)))continue;const i={relatedTarget:t._element};"click"===e.type&&(i.clickEvent=e),t._completeHide(i)}}static dataApiKeydownHandler(e){const t=/input|textarea/i.test(e.target.tagName),o="Escape"===e.key,r=[Do,jo].includes(e.key);if(!r&&!o)return;if(t&&!o)return;e.preventDefault();const n=this.matches(Lo)?this:Tt.prev(this,Lo)[0]||Tt.next(this,Lo)[0]||Tt.findOne(Lo,e.delegateTarget.parentNode),i=Yo.getOrCreateInstance(n);if(r)return e.stopPropagation(),i.show(),void i._selectMenuItem(e);i._isShown()&&(e.stopPropagation(),i.hide(),n.focus())}}ht.on(document,Co,Lo,Yo.dataApiKeydownHandler),ht.on(document,Co,Uo,Yo.dataApiKeydownHandler),ht.on(document,Po,Yo.clearMenus),ht.on(document,Bo,Yo.clearMenus),ht.on(document,Po,Lo,(function(e){e.preventDefault(),Yo.getOrCreateInstance(this).toggle()})),Je(Yo);const Ko="backdrop",Jo="show",Xo=`mousedown.bs.${Ko}`,Zo={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Qo={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class er extends vt{constructor(e){super(),this._config=this._getConfig(e),this._isAppended=!1,this._element=null}static get Default(){return Zo}static get DefaultType(){return Qo}static get NAME(){return Ko}show(e){if(!this._config.isVisible)return void Xe(e);this._append();const t=this._getElement();this._config.isAnimated&&Ge(t),t.classList.add(Jo),this._emulateAnimation((()=>{Xe(e)}))}hide(e){this._config.isVisible?(this._getElement().classList.remove(Jo),this._emulateAnimation((()=>{this.dispose(),Xe(e)}))):Xe(e)}dispose(){this._isAppended&&(ht.off(this._element,Xo),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const e=document.createElement("div");e.className=this._config.className,this._config.isAnimated&&e.classList.add("fade"),this._element=e}return this._element}_configAfterMerge(e){return e.rootElement=We(e.rootElement),e}_append(){if(this._isAppended)return;const e=this._getElement();this._config.rootElement.append(e),ht.on(e,Xo,(()=>{Xe(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(e){Ze(e,this._getElement(),this._config.isAnimated)}}const tr=".bs.focustrap",or=`focusin${tr}`,rr=`keydown.tab${tr}`,nr="backward",ir={autofocus:!0,trapElement:null},sr={autofocus:"boolean",trapElement:"element"};class ar extends vt{constructor(e){super(),this._config=this._getConfig(e),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return ir}static get DefaultType(){return sr}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),ht.off(document,tr),ht.on(document,or,(e=>this._handleFocusin(e))),ht.on(document,rr,(e=>this._handleKeydown(e))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,ht.off(document,tr))}_handleFocusin(e){const{trapElement:t}=this._config;if(e.target===document||e.target===t||t.contains(e.target))return;const o=Tt.focusableChildren(t);0===o.length?t.focus():this._lastTabNavDirection===nr?o[o.length-1].focus():o[0].focus()}_handleKeydown(e){"Tab"===e.key&&(this._lastTabNavDirection=e.shiftKey?nr:"forward")}}const pr=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",lr=".sticky-top",gr="padding-right",ur="margin-right";class cr{constructor(){this._element=document.body}getWidth(){const e=document.documentElement.clientWidth;return Math.abs(window.innerWidth-e)}hide(){const e=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,gr,(t=>t+e)),this._setElementAttributes(pr,gr,(t=>t+e)),this._setElementAttributes(lr,ur,(t=>t-e))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,gr),this._resetElementAttributes(pr,gr),this._resetElementAttributes(lr,ur)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(e,t,o){const r=this.getWidth();this._applyManipulationCallback(e,(e=>{if(e!==this._element&&window.innerWidth>e.clientWidth+r)return;this._saveInitialAttribute(e,t);const n=window.getComputedStyle(e).getPropertyValue(t);e.style.setProperty(t,`${o(Number.parseFloat(n))}px`)}))}_saveInitialAttribute(e,t){const o=e.style.getPropertyValue(t);o&&_t.setDataAttribute(e,t,o)}_resetElementAttributes(e,t){this._applyManipulationCallback(e,(e=>{const o=_t.getDataAttribute(e,t);null!==o?(_t.removeDataAttribute(e,t),e.style.setProperty(t,o)):e.style.removeProperty(t)}))}_applyManipulationCallback(e,t){if(ke(e))t(e);else for(const o of Tt.find(e,this._element))t(o)}}const dr=".bs.modal",fr=`hide${dr}`,hr=`hidePrevented${dr}`,br=`hidden${dr}`,yr=`show${dr}`,mr=`shown${dr}`,_r=`resize${dr}`,vr=`click.dismiss${dr}`,Er=`mousedown.dismiss${dr}`,Sr=`keydown.dismiss${dr}`,Tr=`click${dr}.data-api`,Or="modal-open",wr="show",Ar="modal-static",Dr={backdrop:!0,focus:!0,keyboard:!0},jr={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Mr extends Et{constructor(e,t){super(e,t),this._dialog=Tt.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cr,this._addEventListeners()}static get Default(){return Dr}static get DefaultType(){return jr}static get NAME(){return"modal"}toggle(e){return this._isShown?this.hide():this.show(e)}show(e){if(this._isShown||this._isTransitioning)return;ht.trigger(this._element,yr,{relatedTarget:e}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(Or),this._adjustDialog(),this._backdrop.show((()=>this._showElement(e))))}hide(){if(!this._isShown||this._isTransitioning)return;ht.trigger(this._element,fr).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(wr),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated()))}dispose(){ht.off(window,dr),ht.off(this._dialog,dr),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new er({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new ar({trapElement:this._element})}_showElement(e){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const t=Tt.findOne(".modal-body",this._dialog);t&&(t.scrollTop=0),Ge(this._element),this._element.classList.add(wr);this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,ht.trigger(this._element,mr,{relatedTarget:e})}),this._dialog,this._isAnimated())}_addEventListeners(){ht.on(this._element,Sr,(e=>{"Escape"===e.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),ht.on(window,_r,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),ht.on(this._element,Er,(e=>{ht.one(this._element,vr,(t=>{this._element===e.target&&this._element===t.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(Or),this._resetAdjustments(),this._scrollBar.reset(),ht.trigger(this._element,br)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(ht.trigger(this._element,hr).defaultPrevented)return;const e=this._element.scrollHeight>document.documentElement.clientHeight,t=this._element.style.overflowY;"hidden"===t||this._element.classList.contains(Ar)||(e||(this._element.style.overflowY="hidden"),this._element.classList.add(Ar),this._queueCallback((()=>{this._element.classList.remove(Ar),this._queueCallback((()=>{this._element.style.overflowY=t}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const e=this._element.scrollHeight>document.documentElement.clientHeight,t=this._scrollBar.getWidth(),o=t>0;if(o&&!e){const e=Ke()?"paddingLeft":"paddingRight";this._element.style[e]=`${t}px`}if(!o&&e){const e=Ke()?"paddingRight":"paddingLeft";this._element.style[e]=`${t}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(e,t){return this.each((function(){const o=Mr.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===o[e])throw new TypeError(`No method named "${e}"`);o[e](t)}}))}}ht.on(document,Tr,'[data-bs-toggle="modal"]',(function(e){const t=Tt.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&e.preventDefault(),ht.one(t,yr,(e=>{e.defaultPrevented||ht.one(t,br,(()=>{He(this)&&this.focus()}))}));const o=Tt.findOne(".modal.show");o&&Mr.getInstance(o).hide();Mr.getOrCreateInstance(t).toggle(this)})),Ot(Mr),Je(Mr);const Fr=".bs.offcanvas",Rr=".data-api",xr=`load${Fr}${Rr}`,Pr="show",Cr="showing",Br="hiding",Nr=".offcanvas.show",Lr=`show${Fr}`,Ir=`shown${Fr}`,Ur=`hide${Fr}`,kr=`hidePrevented${Fr}`,Wr=`hidden${Fr}`,Hr=`resize${Fr}`,Vr=`click${Fr}${Rr}`,qr=`keydown.dismiss${Fr}`,zr={backdrop:!0,keyboard:!0,scroll:!1},Gr={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class $r extends Et{constructor(e,t){super(e,t),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zr}static get DefaultType(){return Gr}static get NAME(){return"offcanvas"}toggle(e){return this._isShown?this.hide():this.show(e)}show(e){if(this._isShown)return;if(ht.trigger(this._element,Lr,{relatedTarget:e}).defaultPrevented)return;this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cr).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Cr);this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Pr),this._element.classList.remove(Cr),ht.trigger(this._element,Ir,{relatedTarget:e})}),this._element,!0)}hide(){if(!this._isShown)return;if(ht.trigger(this._element,Ur).defaultPrevented)return;this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Br),this._backdrop.hide();this._queueCallback((()=>{this._element.classList.remove(Pr,Br),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cr).reset(),ht.trigger(this._element,Wr)}),this._element,!0)}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const e=Boolean(this._config.backdrop);return new er({className:"offcanvas-backdrop",isVisible:e,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:e?()=>{"static"!==this._config.backdrop?this.hide():ht.trigger(this._element,kr)}:null})}_initializeFocusTrap(){return new ar({trapElement:this._element})}_addEventListeners(){ht.on(this._element,qr,(e=>{"Escape"===e.key&&(this._config.keyboard?this.hide():ht.trigger(this._element,kr))}))}static jQueryInterface(e){return this.each((function(){const t=$r.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e]||e.startsWith("_")||"constructor"===e)throw new TypeError(`No method named "${e}"`);t[e](this)}}))}}ht.on(document,Vr,'[data-bs-toggle="offcanvas"]',(function(e){const t=Tt.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&e.preventDefault(),Ve(this))return;ht.one(t,Wr,(()=>{He(this)&&this.focus()}));const o=Tt.findOne(Nr);o&&o!==t&&$r.getInstance(o).hide();$r.getOrCreateInstance(t).toggle(this)})),ht.on(window,xr,(()=>{for(const e of Tt.find(Nr))$r.getOrCreateInstance(e).show()})),ht.on(window,Hr,(()=>{for(const e of Tt.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(e).position&&$r.getOrCreateInstance(e).hide()})),Ot($r),Je($r);const Yr={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kr=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Jr=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xr=(e,t)=>{const o=e.nodeName.toLowerCase();return t.includes(o)?!Kr.has(o)||Boolean(Jr.test(e.nodeValue)):t.filter((e=>e instanceof RegExp)).some((e=>e.test(o)))};const Zr={allowList:Yr,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Qr={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},en={entry:"(string|element|function|null)",selector:"(string|element)"};class tn extends vt{constructor(e){super(),this._config=this._getConfig(e)}static get Default(){return Zr}static get DefaultType(){return Qr}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((e=>this._resolvePossibleFunction(e))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(e){return this._checkContent(e),this._config.content={...this._config.content,...e},this}toHtml(){const e=document.createElement("div");e.innerHTML=this._maybeSanitize(this._config.template);for(const[t,o]of Object.entries(this._config.content))this._setContent(e,o,t);const t=e.children[0],o=this._resolvePossibleFunction(this._config.extraClass);return o&&t.classList.add(...o.split(" ")),t}_typeCheckConfig(e){super._typeCheckConfig(e),this._checkContent(e.content)}_checkContent(e){for(const[t,o]of Object.entries(e))super._typeCheckConfig({selector:t,entry:o},en)}_setContent(e,t,o){const r=Tt.findOne(o,e);r&&((t=this._resolvePossibleFunction(t))?ke(t)?this._putElementInTemplate(We(t),r):this._config.html?r.innerHTML=this._maybeSanitize(t):r.textContent=t:r.remove())}_maybeSanitize(e){return this._config.sanitize?function(e,t,o){if(!e.length)return e;if(o&&"function"==typeof o)return o(e);const r=(new window.DOMParser).parseFromString(e,"text/html"),n=[].concat(...r.body.querySelectorAll("*"));for(const e of n){const o=e.nodeName.toLowerCase();if(!Object.keys(t).includes(o)){e.remove();continue}const r=[].concat(...e.attributes),n=[].concat(t["*"]||[],t[o]||[]);for(const t of r)Xr(t,n)||e.removeAttribute(t.nodeName)}return r.body.innerHTML}(e,this._config.allowList,this._config.sanitizeFn):e}_resolvePossibleFunction(e){return Xe(e,[this])}_putElementInTemplate(e,t){if(this._config.html)return t.innerHTML="",void t.append(e);t.textContent=e.textContent}}const on=new Set(["sanitize","allowList","sanitizeFn"]),rn="fade",nn="show",sn=".modal",an="hide.bs.modal",pn="hover",ln="focus",gn={AUTO:"auto",TOP:"top",RIGHT:Ke()?"left":"right",BOTTOM:"bottom",LEFT:Ke()?"right":"left"},un={allowList:Yr,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},cn={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class dn extends Et{constructor(e,t){if(void 0===r)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(e,t),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return un}static get DefaultType(){return cn}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),ht.off(this._element.closest(sn),an,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const e=ht.trigger(this._element,this.constructor.eventName("show")),t=(qe(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(e.defaultPrevented||!t)return;this._disposePopper();const o=this._getTipElement();this._element.setAttribute("aria-describedby",o.getAttribute("id"));const{container:r}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(r.append(o),ht.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(o),o.classList.add(nn),"ontouchstart"in document.documentElement)for(const e of[].concat(...document.body.children))ht.on(e,"mouseover",ze);this._queueCallback((()=>{ht.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(!this._isShown())return;if(ht.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented)return;if(this._getTipElement().classList.remove(nn),"ontouchstart"in document.documentElement)for(const e of[].concat(...document.body.children))ht.off(e,"mouseover",ze);this._activeTrigger.click=!1,this._activeTrigger[ln]=!1,this._activeTrigger[pn]=!1,this._isHovered=null;this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),ht.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(e){const t=this._getTemplateFactory(e).toHtml();if(!t)return null;t.classList.remove(rn,nn),t.classList.add(`bs-${this.constructor.NAME}-auto`);const o=(e=>{do{e+=Math.floor(1e6*Math.random())}while(document.getElementById(e));return e})(this.constructor.NAME).toString();return t.setAttribute("id",o),this._isAnimated()&&t.classList.add(rn),t}setContent(e){this._newContent=e,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(e){return this._templateFactory?this._templateFactory.changeContent(e):this._templateFactory=new tn({...this._config,content:e,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(e){return this.constructor.getOrCreateInstance(e.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(rn)}_isShown(){return this.tip&&this.tip.classList.contains(nn)}_createPopper(e){const t=Xe(this._config.placement,[this,e,this._element]),o=gn[t.toUpperCase()];return Pe(this._element,e,this._getPopperConfig(o))}_getOffset(){const{offset:e}=this._config;return"string"==typeof e?e.split(",").map((e=>Number.parseInt(e,10))):"function"==typeof e?t=>e(t,this._element):e}_resolvePossibleFunction(e){return Xe(e,[this._element])}_getPopperConfig(e){const t={placement:e,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:e=>{this._getTipElement().setAttribute("data-popper-placement",e.state.placement)}}]};return{...t,...Xe(this._config.popperConfig,[t])}}_setListeners(){const e=this._config.trigger.split(" ");for(const t of e)if("click"===t)ht.on(this._element,this.constructor.eventName("click"),this._config.selector,(e=>{this._initializeOnDelegatedTarget(e).toggle()}));else if("manual"!==t){const e=t===pn?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),o=t===pn?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");ht.on(this._element,e,this._config.selector,(e=>{const t=this._initializeOnDelegatedTarget(e);t._activeTrigger["focusin"===e.type?ln:pn]=!0,t._enter()})),ht.on(this._element,o,this._config.selector,(e=>{const t=this._initializeOnDelegatedTarget(e);t._activeTrigger["focusout"===e.type?ln:pn]=t._element.contains(e.relatedTarget),t._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},ht.on(this._element.closest(sn),an,this._hideModalHandler)}_fixTitle(){const e=this._element.getAttribute("title");e&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",e),this._element.setAttribute("data-bs-original-title",e),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(e,t){clearTimeout(this._timeout),this._timeout=setTimeout(e,t)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(e){const t=_t.getDataAttributes(this._element);for(const e of Object.keys(t))on.has(e)&&delete t[e];return e={...t,..."object"==typeof e&&e?e:{}},e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e.container=!1===e.container?document.body:We(e.container),"number"==typeof e.delay&&(e.delay={show:e.delay,hide:e.delay}),"number"==typeof e.title&&(e.title=e.title.toString()),"number"==typeof e.content&&(e.content=e.content.toString()),e}_getDelegateConfig(){const e={};for(const[t,o]of Object.entries(this._config))this.constructor.Default[t]!==o&&(e[t]=o);return e.selector=!1,e.trigger="manual",e}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(e){return this.each((function(){const t=dn.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e])throw new TypeError(`No method named "${e}"`);t[e]()}}))}}Je(dn);const fn={...dn.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},hn={...dn.DefaultType,content:"(null|string|element|function)"};class bn extends dn{static get Default(){return fn}static get DefaultType(){return hn}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(e){return this.each((function(){const t=bn.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e])throw new TypeError(`No method named "${e}"`);t[e]()}}))}}Je(bn);const yn=".bs.scrollspy",mn=`activate${yn}`,_n=`click${yn}`,vn=`load${yn}.data-api`,En="active",Sn="[href]",Tn=".nav-link",On=`${Tn}, .nav-item > ${Tn}, .list-group-item`,wn={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},An={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Dn extends Et{constructor(e,t){super(e,t),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return wn}static get DefaultType(){return An}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const e of this._observableSections.values())this._observer.observe(e)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(e){return e.target=We(e.target)||document.body,e.rootMargin=e.offset?`${e.offset}px 0px -30%`:e.rootMargin,"string"==typeof e.threshold&&(e.threshold=e.threshold.split(",").map((e=>Number.parseFloat(e)))),e}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(ht.off(this._config.target,_n),ht.on(this._config.target,_n,Sn,(e=>{const t=this._observableSections.get(e.target.hash);if(t){e.preventDefault();const o=this._rootElement||window,r=t.offsetTop-this._element.offsetTop;if(o.scrollTo)return void o.scrollTo({top:r,behavior:"smooth"});o.scrollTop=r}})))}_getNewObserver(){const e={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((e=>this._observerCallback(e)),e)}_observerCallback(e){const t=e=>this._targetLinks.get(`#${e.target.id}`),o=e=>{this._previousScrollData.visibleEntryTop=e.target.offsetTop,this._process(t(e))},r=(this._rootElement||document.documentElement).scrollTop,n=r>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=r;for(const i of e){if(!i.isIntersecting){this._activeTarget=null,this._clearActiveClass(t(i));continue}const e=i.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(n&&e){if(o(i),!r)return}else n||e||o(i)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const e=Tt.find(Sn,this._config.target);for(const t of e){if(!t.hash||Ve(t))continue;const e=Tt.findOne(decodeURI(t.hash),this._element);He(e)&&(this._targetLinks.set(decodeURI(t.hash),t),this._observableSections.set(t.hash,e))}}_process(e){this._activeTarget!==e&&(this._clearActiveClass(this._config.target),this._activeTarget=e,e.classList.add(En),this._activateParents(e),ht.trigger(this._element,mn,{relatedTarget:e}))}_activateParents(e){if(e.classList.contains("dropdown-item"))Tt.findOne(".dropdown-toggle",e.closest(".dropdown")).classList.add(En);else for(const t of Tt.parents(e,".nav, .list-group"))for(const e of Tt.prev(t,On))e.classList.add(En)}_clearActiveClass(e){e.classList.remove(En);const t=Tt.find(`${Sn}.${En}`,e);for(const e of t)e.classList.remove(En)}static jQueryInterface(e){return this.each((function(){const t=Dn.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e]||e.startsWith("_")||"constructor"===e)throw new TypeError(`No method named "${e}"`);t[e]()}}))}}ht.on(window,vn,(()=>{for(const e of Tt.find('[data-bs-spy="scroll"]'))Dn.getOrCreateInstance(e)})),Je(Dn);const jn=".bs.tab",Mn=`hide${jn}`,Fn=`hidden${jn}`,Rn=`show${jn}`,xn=`shown${jn}`,Pn=`click${jn}`,Cn=`keydown${jn}`,Bn=`load${jn}`,Nn="ArrowLeft",Ln="ArrowRight",In="ArrowUp",Un="ArrowDown",kn="Home",Wn="End",Hn="active",Vn="fade",qn="show",zn=".dropdown-toggle",Gn=`:not(${zn})`,$n='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Yn=`${`.nav-link${Gn}, .list-group-item${Gn}, [role="tab"]${Gn}`}, ${$n}`,Kn=`.${Hn}[data-bs-toggle="tab"], .${Hn}[data-bs-toggle="pill"], .${Hn}[data-bs-toggle="list"]`;class Jn extends Et{constructor(e){super(e),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),ht.on(this._element,Cn,(e=>this._keydown(e))))}static get NAME(){return"tab"}show(){const e=this._element;if(this._elemIsActive(e))return;const t=this._getActiveElem(),o=t?ht.trigger(t,Mn,{relatedTarget:e}):null;ht.trigger(e,Rn,{relatedTarget:t}).defaultPrevented||o&&o.defaultPrevented||(this._deactivate(t,e),this._activate(e,t))}_activate(e,t){if(!e)return;e.classList.add(Hn),this._activate(Tt.getElementFromSelector(e));this._queueCallback((()=>{"tab"===e.getAttribute("role")?(e.removeAttribute("tabindex"),e.setAttribute("aria-selected",!0),this._toggleDropDown(e,!0),ht.trigger(e,xn,{relatedTarget:t})):e.classList.add(qn)}),e,e.classList.contains(Vn))}_deactivate(e,t){if(!e)return;e.classList.remove(Hn),e.blur(),this._deactivate(Tt.getElementFromSelector(e));this._queueCallback((()=>{"tab"===e.getAttribute("role")?(e.setAttribute("aria-selected",!1),e.setAttribute("tabindex","-1"),this._toggleDropDown(e,!1),ht.trigger(e,Fn,{relatedTarget:t})):e.classList.remove(qn)}),e,e.classList.contains(Vn))}_keydown(e){if(![Nn,Ln,In,Un,kn,Wn].includes(e.key))return;e.stopPropagation(),e.preventDefault();const t=this._getChildren().filter((e=>!Ve(e)));let o;if([kn,Wn].includes(e.key))o=t[e.key===kn?0:t.length-1];else{const r=[Ln,Un].includes(e.key);o=Qe(t,e.target,r,!0)}o&&(o.focus({preventScroll:!0}),Jn.getOrCreateInstance(o).show())}_getChildren(){return Tt.find(Yn,this._parent)}_getActiveElem(){return this._getChildren().find((e=>this._elemIsActive(e)))||null}_setInitialAttributes(e,t){this._setAttributeIfNotExists(e,"role","tablist");for(const e of t)this._setInitialAttributesOnChild(e)}_setInitialAttributesOnChild(e){e=this._getInnerElement(e);const t=this._elemIsActive(e),o=this._getOuterElement(e);e.setAttribute("aria-selected",t),o!==e&&this._setAttributeIfNotExists(o,"role","presentation"),t||e.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(e,"role","tab"),this._setInitialAttributesOnTargetPanel(e)}_setInitialAttributesOnTargetPanel(e){const t=Tt.getElementFromSelector(e);t&&(this._setAttributeIfNotExists(t,"role","tabpanel"),e.id&&this._setAttributeIfNotExists(t,"aria-labelledby",`${e.id}`))}_toggleDropDown(e,t){const o=this._getOuterElement(e);if(!o.classList.contains("dropdown"))return;const r=(e,r)=>{const n=Tt.findOne(e,o);n&&n.classList.toggle(r,t)};r(zn,Hn),r(".dropdown-menu",qn),o.setAttribute("aria-expanded",t)}_setAttributeIfNotExists(e,t,o){e.hasAttribute(t)||e.setAttribute(t,o)}_elemIsActive(e){return e.classList.contains(Hn)}_getInnerElement(e){return e.matches(Yn)?e:Tt.findOne(Yn,e)}_getOuterElement(e){return e.closest(".nav-item, .list-group-item")||e}static jQueryInterface(e){return this.each((function(){const t=Jn.getOrCreateInstance(this);if("string"==typeof e){if(void 0===t[e]||e.startsWith("_")||"constructor"===e)throw new TypeError(`No method named "${e}"`);t[e]()}}))}}ht.on(document,Pn,$n,(function(e){["A","AREA"].includes(this.tagName)&&e.preventDefault(),Ve(this)||Jn.getOrCreateInstance(this).show()})),ht.on(window,Bn,(()=>{for(const e of Tt.find(Kn))Jn.getOrCreateInstance(e)})),Je(Jn);const Xn=".bs.toast",Zn=`mouseover${Xn}`,Qn=`mouseout${Xn}`,ei=`focusin${Xn}`,ti=`focusout${Xn}`,oi=`hide${Xn}`,ri=`hidden${Xn}`,ni=`show${Xn}`,ii=`shown${Xn}`,si="hide",ai="show",pi="showing",li={animation:"boolean",autohide:"boolean",delay:"number"},gi={animation:!0,autohide:!0,delay:5e3};class ui extends Et{constructor(e,t){super(e,t),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return gi}static get DefaultType(){return li}static get NAME(){return"toast"}show(){if(ht.trigger(this._element,ni).defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");this._element.classList.remove(si),Ge(this._element),this._element.classList.add(ai,pi),this._queueCallback((()=>{this._element.classList.remove(pi),ht.trigger(this._element,ii),this._maybeScheduleHide()}),this._element,this._config.animation)}hide(){if(!this.isShown())return;if(ht.trigger(this._element,oi).defaultPrevented)return;this._element.classList.add(pi),this._queueCallback((()=>{this._element.classList.add(si),this._element.classList.remove(pi,ai),ht.trigger(this._element,ri)}),this._element,this._config.animation)}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(ai),super.dispose()}isShown(){return this._element.classList.contains(ai)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(e,t){switch(e.type){case"mouseover":case"mouseout":this._hasMouseInteraction=t;break;case"focusin":case"focusout":this._hasKeyboardInteraction=t}if(t)return void this._clearTimeout();const o=e.relatedTarget;this._element===o||this._element.contains(o)||this._maybeScheduleHide()}_setListeners(){ht.on(this._element,Zn,(e=>this._onInteraction(e,!0))),ht.on(this._element,Qn,(e=>this._onInteraction(e,!1))),ht.on(this._element,ei,(e=>this._onInteraction(e,!0))),ht.on(this._element,ti,(e=>this._onInteraction(e,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(e){return this.each((function(){const t=ui.getOrCreateInstance(this,e);if("string"==typeof e){if(void 0===t[e])throw new TypeError(`No method named "${e}"`);t[e](this)}}))}}Ot(ui),Je(ui)},3019:function(__unused_webpack_module,exports,__webpack_require__){var $jscomp=$jscomp||{};$jscomp.scope={},$jscomp.findInternal=function(e,t,o){e instanceof String&&(e=String(e));for(var r=e.length,n=0;n=r}}),"es6","es3"),$jscomp.polyfill("Array.prototype.find",(function(e){return e||function(e,t){return $jscomp.findInternal(this,e,t).v}}),"es6","es3"),$jscomp.polyfill("String.prototype.startsWith",(function(e){return e||function(e,t){var o=$jscomp.checkStringArgs(this,e,"startsWith");e+="";var r=o.length,n=e.length;t=Math.max(0,Math.min(0|t,o.length));for(var i=0;i=n}}),"es6","es3"),$jscomp.polyfill("String.prototype.repeat",(function(e){return e||function(e){var t=$jscomp.checkStringArgs(this,null,"repeat");if(0>e||1342177279>>=1)&&(t+=t);return o}}),"es6","es3");var COMPILED=!0,goog=goog||{};goog.global=this||self,goog.exportPath_=function(e,t,o){e=e.split("."),o=o||goog.global,e[0]in o||void 0===o.execScript||o.execScript("var "+e[0]);for(var r;e.length&&(r=e.shift());)e.length||void 0===t?o=o[r]&&o[r]!==Object.prototype[r]?o[r]:o[r]={}:o[r]=t},goog.define=function(e,t){if(!COMPILED){var o=goog.global.CLOSURE_UNCOMPILED_DEFINES,r=goog.global.CLOSURE_DEFINES;o&&void 0===o.nodeType&&Object.prototype.hasOwnProperty.call(o,e)?t=o[e]:r&&void 0===r.nodeType&&Object.prototype.hasOwnProperty.call(r,e)&&(t=r[e])}return t},goog.FEATURESET_YEAR=2012,goog.DEBUG=!0,goog.LOCALE="en",goog.TRUSTED_SITE=!0,goog.STRICT_MODE_COMPATIBLE=!1,goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG,goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1,goog.provide=function(e){if(goog.isInModuleLoader_())throw Error("goog.provide cannot be used within a module.");if(!COMPILED&&goog.isProvided_(e))throw Error('Namespace "'+e+'" already declared.');goog.constructNamespace_(e)},goog.constructNamespace_=function(e,t){if(!COMPILED){delete goog.implicitNamespaces_[e];for(var o=e;(o=o.substring(0,o.lastIndexOf(".")))&&!goog.getObjectByName(o);)goog.implicitNamespaces_[o]=!0}goog.exportPath_(e,t)},goog.getScriptNonce=function(e){return e&&e!=goog.global?goog.getScriptNonce_(e.document):(null===goog.cspNonce_&&(goog.cspNonce_=goog.getScriptNonce_(goog.global.document)),goog.cspNonce_)},goog.NONCE_PATTERN_=/^[\w+/_-]+[=]{0,2}$/,goog.cspNonce_=null,goog.getScriptNonce_=function(e){return(e=e.querySelector&&e.querySelector("script[nonce]"))&&(e=e.nonce||e.getAttribute("nonce"))&&goog.NONCE_PATTERN_.test(e)?e:""},goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/,goog.module=function(e){if("string"!=typeof e||!e||-1==e.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInGoogModuleLoader_())throw Error("Module "+e+" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");if(goog.moduleLoaderState_.moduleName=e,!COMPILED){if(goog.isProvided_(e))throw Error('Namespace "'+e+'" already declared.');delete goog.implicitNamespaces_[e]}},goog.module.get=function(e){return goog.module.getInternal_(e)},goog.module.getInternal_=function(e){if(!COMPILED){if(e in goog.loadedModules_)return goog.loadedModules_[e].exports;if(!goog.implicitNamespaces_[e])return null!=(e=goog.getObjectByName(e))?e:null}return null},goog.ModuleType={ES6:"es6",GOOG:"goog"},goog.moduleLoaderState_=null,goog.isInModuleLoader_=function(){return goog.isInGoogModuleLoader_()||goog.isInEs6ModuleLoader_()},goog.isInGoogModuleLoader_=function(){return!!goog.moduleLoaderState_&&goog.moduleLoaderState_.type==goog.ModuleType.GOOG},goog.isInEs6ModuleLoader_=function(){if(goog.moduleLoaderState_&&goog.moduleLoaderState_.type==goog.ModuleType.ES6)return!0;var e=goog.global.$jscomp;return!!e&&("function"==typeof e.getCurrentModulePath&&!!e.getCurrentModulePath())},goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInGoogModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0},goog.declareModuleId=function(e){if(!COMPILED){if(!goog.isInEs6ModuleLoader_())throw Error("goog.declareModuleId may only be called from within an ES6 module");if(goog.moduleLoaderState_&&goog.moduleLoaderState_.moduleName)throw Error("goog.declareModuleId may only be called once per module.");if(e in goog.loadedModules_)throw Error('Module with namespace "'+e+'" already exists.')}if(goog.moduleLoaderState_)goog.moduleLoaderState_.moduleName=e;else{var t=goog.global.$jscomp;if(!t||"function"!=typeof t.getCurrentModulePath)throw Error('Module with namespace "'+e+'" has been loaded incorrectly.');t=t.require(t.getCurrentModulePath()),goog.loadedModules_[e]={exports:t,type:goog.ModuleType.ES6,moduleId:e}}},goog.setTestOnly=function(e){if(goog.DISALLOW_TEST_ONLY_CODE)throw e=e||"",Error("Importing test-only code into non-debug environment"+(e?": "+e:"."))},goog.forwardDeclare=function(e){},COMPILED||(goog.isProvided_=function(e){return e in goog.loadedModules_||!goog.implicitNamespaces_[e]&&null!=goog.getObjectByName(e)},goog.implicitNamespaces_={"goog.module":!0}),goog.getObjectByName=function(e,t){e=e.split("."),t=t||goog.global;for(var o=0;o>>0),goog.uidCounter_=0,goog.getHashCode=goog.getUid,goog.removeHashCode=goog.removeUid,goog.cloneObject=function(e){var t=goog.typeOf(e);if("object"==t||"array"==t){if("function"==typeof e.clone)return e.clone();for(var o in t="array"==t?[]:{},e)t[o]=goog.cloneObject(e[o]);return t}return e},goog.bindNative_=function(e,t,o){return e.call.apply(e.bind,arguments)},goog.bindJs_=function(e,t,o){if(!e)throw Error();if(2{"use strict";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()')})),a("es7",(function(){return b("2 ** 2 == 4")})),a("es8",(function(){return b("async () => 1, true")})),a("es9",(function(){return b("({...rest} = {}), true")})),a("es_next",(function(){return!1})),{target:c,map:d}},goog.Transpiler.prototype.needsTranspile=function(e,t){if("always"==goog.TRANSPILE)return!0;if("never"==goog.TRANSPILE)return!1;if(!this.requiresTranspilation_){var o=this.createRequiresTranspilation_();this.requiresTranspilation_=o.map,this.transpilationTarget_=this.transpilationTarget_||o.target}if(e in this.requiresTranspilation_)return!!this.requiresTranspilation_[e]||!(!goog.inHtmlDocument_()||"es6"!=t||"noModule"in goog.global.document.createElement("script"));throw Error("Unknown language mode: "+e)},goog.Transpiler.prototype.transpile=function(e,t){return goog.transpile_(e,t,this.transpilationTarget_)},goog.transpiler_=new goog.Transpiler,goog.protectScriptTag_=function(e){return e.replace(/<\/(SCRIPT)/gi,"\\x3c/$1")},goog.DebugLoader_=function(){this.dependencies_={},this.idToPath_={},this.written_={},this.loadingDeps_=[],this.depsToLoad_=[],this.paused_=!1,this.factory_=new goog.DependencyFactory(goog.transpiler_),this.deferredCallbacks_={},this.deferredQueue_=[]},goog.DebugLoader_.prototype.bootstrap=function(e,t){function o(){r&&(goog.global.setTimeout(r,0),r=null)}var r=t;if(e.length){t=[];for(var n=0;n<\/script>",t.write(goog.TRUSTED_TYPES_POLICY_?goog.TRUSTED_TYPES_POLICY_.createHTML(r):r)}else{var n=t.createElement("script");n.defer=goog.Dependency.defer_,n.async=!1,n.type="text/javascript",(r=goog.getScriptNonce())&&n.setAttribute("nonce",r),goog.DebugLoader_.IS_OLD_IE_?(e.pause(),n.onreadystatechange=function(){"loaded"!=n.readyState&&"complete"!=n.readyState||(e.loaded(),e.resume())}):n.onload=function(){n.onload=null,e.loaded()},n.src=goog.TRUSTED_TYPES_POLICY_?goog.TRUSTED_TYPES_POLICY_.createScriptURL(this.path):this.path,t.head.appendChild(n)}}else goog.logToConsole_("Cannot use default debug loader outside of HTML documents."),"deps.js"==this.relativePath?(goog.logToConsole_("Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, or setting CLOSURE_NO_DEPS to true."),e.loaded()):e.pause()},goog.Es6ModuleDependency=function(e,t,o,r,n){goog.Dependency.call(this,e,t,o,r,n)},goog.inherits(goog.Es6ModuleDependency,goog.Dependency),goog.Es6ModuleDependency.prototype.load=function(e){if(goog.global.CLOSURE_IMPORT_SCRIPT)goog.global.CLOSURE_IMPORT_SCRIPT(this.path)?e.loaded():e.pause();else if(goog.inHtmlDocument_()){var t=goog.global.document,o=this;if(goog.isDocumentLoading_()){var r=function(e,o){e=o?'