diff --git a/README.md b/README.md index 6c2fdd857..621122d12 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ This can be achieved by editing the 'platformio.ini' file and add/change one or * erase flash: `platformio run -e generic -t erase` ### using the pre-compiled .bin files -The pre-compiled files can be found on the [github page](https://github.com/tbnobody/OpenDTU) in the tab "Actions" and the sub menu "OpenDTU Build". Just choose the latest build from the master branch (blue font). You need to be logged in with your github account to download the files. +The pre-compiled files can be found on the [github page](https://github.com/tbnobody/OpenDTU) in the tab "Actions" and the sub menu "OpenDTU Build". Just choose the latest build from the master branch (search for "master" in the blue font text but click on the white header text!). You need to be logged in with your github account to download the files. Use a ESP32 flash tool of your choice (see next chapter) and flash the `.bin` files to the right addresses: | Address | File | @@ -184,7 +184,7 @@ Use a ESP32 flash tool of your choice (see next chapter) and flash the `.bin` fi For further updates you can just use the web interface and upload the `opendtu-*.bin` file. -### Flash with esptool.py (Linux) +#### Flash with esptool.py (Linux) ``` esptool.py --port /dev/ttyUSB0 --chip esp32 --before default_reset --after hard_reset \ write_flash --flash_mode dout --flash_freq 40m --flash_size detect \ @@ -194,7 +194,7 @@ esptool.py --port /dev/ttyUSB0 --chip esp32 --before default_reset --after hard_ 0x10000 opendtu-generic.bin ``` -### Flash with Espressif Flash Download Tool (Windows) +#### Flash with Espressif Flash Download Tool (Windows) [Download link](https://www.espressif.com/en/support/download/other-tools) @@ -205,7 +205,7 @@ esptool.py --port /dev/ttyUSB0 --chip esp32 --before default_reset --after hard_ - To program, press "Start" on screen, then the "Boot" button. - When flashing is complete (FINISH appears) then press the Reset button on the ESP32 board (or powercycle ) to start the OpenDTU application. -### Flash with ESP_Flasher (Windows) +#### Flash with ESP_Flasher (Windows) Users report that [ESP_Flasher](https://github.com/Jason2866/ESP_Flasher/releases/) is suitable for flashing OpenDTU on Windows. ## First configuration @@ -236,6 +236,9 @@ A documentation of the Web API can be found here: [Web-API Documentation](docs/W ## Available cases * * +* +* + ## Building * Building the WebApp diff --git a/docs/MQTT_Topics.md b/docs/MQTT_Topics.md index 4f73b6166..46a2b6738 100644 --- a/docs/MQTT_Topics.md +++ b/docs/MQTT_Topics.md @@ -66,8 +66,8 @@ cmd topics are used to set values. Status topics are updated from values set in | [serial]/status/limit_relative | R | Current applied production limit of the inverter | % of total possible output | | [serial]/status/limit_absolute | R | Current applied production limit of the inverter | Watt (W) | | [serial]/cmd/limit_persistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % | -| [serial]/cmd/limit_persistent_absolute | W | Set the inverter limit as a absolute value. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic after around 4 minutes. | Watt (W) | +| [serial]/cmd/limit_persistent_absolute | W | Set the inverter limit as a absolute value. The value will survive the night without power. The updated value will set immediatly within the inverter but show up in the web GUI and limit_relative topic after around 4 minutes. If you are using a already known inverter (known Hardware ID), the updated value will show up within a few seconds. | Watt (W) | | [serial]/cmd/limit_nonpersistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % | -| [serial]/cmd/limit_nonpersistent_absolute | W | Set the inverter limit as a absolute value. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic after around 4 minutes. | Watt (W) | +| [serial]/cmd/limit_nonpersistent_absolute | W | Set the inverter limit as a absolute value. The value will reset to the last persistent value at night without power. The updated value will set immediatly within the inverter but show up in the web GUI and limit_relative topic after around 4 minutes. If you are using a already known inverter (known Hardware ID), the updated value will show up within a few seconds. | Watt (W) | | [serial]/cmd/power | W | Turn the inverter on (1) or off (0) | 0 or 1 | | [serial]/cmd/restart | W | Restarts the inverters (also resets YieldDay) | 1 | diff --git a/lib/CircularBuffer/CircularBuffer.h b/lib/CircularBuffer/CircularBuffer.h deleted file mode 100644 index 32db3871a..000000000 --- a/lib/CircularBuffer/CircularBuffer.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - CircularBuffer - An Arduino circular buffering library for arbitrary types. - - Created by Ivo Pullens, Emmission, 2014 -- www.emmission.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef CircularBuffer_h -#define CircularBuffer_h - -#include - -#ifdef ESP8266 -#define DISABLE_IRQ noInterrupts() -#define RESTORE_IRQ interrupts() -#elif ESP32 -#define DISABLE_IRQ ; -#define RESTORE_IRQ ; -#else -#define DISABLE_IRQ \ - uint8_t sreg = SREG; \ - cli(); - -#define RESTORE_IRQ \ - SREG = sreg; -#endif - -template -class CircularBuffer { - - typedef BUFFERTYPE BufferType; - BufferType Buffer[BUFFERSIZE]; - - public: - CircularBuffer() : m_buff(Buffer) { - m_size = BUFFERSIZE; - clear(); - } - - /** Clear all entries in the circular buffer. */ - void clear(void) - { - m_front = 0; - m_fill = 0; - } - - /** Test if the circular buffer is empty */ - inline bool empty(void) const - { - return !m_fill; - } - - /** Return the number of records stored in the buffer */ - inline uint8_t available(void) const - { - return m_fill; - } - - /** Test if the circular buffer is full */ - inline bool full(void) const - { - return m_fill == m_size; - } - - inline uint8_t getFill(void) const { - return m_fill; - } - - /** Aquire record on front of the buffer, for writing. - * After filling the record, it has to be pushed to actually - * add it to the buffer. - * @return Pointer to record, or NULL when buffer is full. - */ - BUFFERTYPE* getFront(void) const - { - DISABLE_IRQ; - BUFFERTYPE* f = NULL; - if (!full()) - f = get(m_front); - RESTORE_IRQ; - return f; - } - - /** Push record to front of the buffer - * @param record Record to push. If record was aquired previously (using getFront) its - * data will not be copied as it is already present in the buffer. - * @return True, when record was pushed successfully. - */ - bool pushFront(BUFFERTYPE* record) - { - bool ok = false; - DISABLE_IRQ; - if (!full()) - { - BUFFERTYPE* f = get(m_front); - if (f != record) - *f = *record; - m_front = (m_front+1) % m_size; - m_fill++; - ok = true; - } - RESTORE_IRQ; - return ok; - } - - /** Aquire record on back of the buffer, for reading. - * After reading the record, it has to be pop'ed to actually - * remove it from the buffer. - * @return Pointer to record, or NULL when buffer is empty. - */ - BUFFERTYPE* getBack(void) const - { - BUFFERTYPE* b = NULL; - DISABLE_IRQ; - if (!empty()) - b = get(back()); - RESTORE_IRQ; - return b; - } - - /** Remove record from back of the buffer. - * @return True, when record was pop'ed successfully. - */ - bool popBack(void) - { - bool ok = false; - DISABLE_IRQ; - if (!empty()) - { - m_fill--; - ok = true; - } - RESTORE_IRQ; - return ok; - } - - protected: - inline BUFFERTYPE * get(const uint8_t idx) const - { - return &(m_buff[idx]); - } - inline uint8_t back(void) const - { - return (m_front - m_fill + m_size) % m_size; - } - - uint8_t m_size; // Total number of records that can be stored in the buffer. - BUFFERTYPE* const m_buff; - volatile uint8_t m_front; // Index of front element (not pushed yet). - volatile uint8_t m_fill; // Amount of records currently pushed. -}; - -#endif // CircularBuffer_h \ No newline at end of file diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index 355a4db2b..2b04ddc0d 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -9,14 +9,14 @@ HoymilesClass Hoymiles; -void HoymilesClass::init() +void HoymilesClass::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ) { _xSemaphore = xSemaphoreCreateMutex(); HOY_SEMAPHORE_GIVE(); // release before first use _pollInterval = 0; _radio.reset(new HoymilesRadio()); - _radio->init(); + _radio->init(initialisedSpiBus, pinCE, pinIRQ); } void HoymilesClass::loop() diff --git a/lib/Hoymiles/src/Hoymiles.h b/lib/Hoymiles/src/Hoymiles.h index 4b6d37d6e..033eabe03 100644 --- a/lib/Hoymiles/src/Hoymiles.h +++ b/lib/Hoymiles/src/Hoymiles.h @@ -12,7 +12,7 @@ class HoymilesClass { public: - void init(); + void init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ); void loop(); std::shared_ptr addInverter(const char* name, uint64_t serial); diff --git a/lib/Hoymiles/src/HoymilesRadio.cpp b/lib/Hoymiles/src/HoymilesRadio.cpp index db70d8b5a..9272b278e 100644 --- a/lib/Hoymiles/src/HoymilesRadio.cpp +++ b/lib/Hoymiles/src/HoymilesRadio.cpp @@ -5,15 +5,14 @@ #include #include -void HoymilesRadio::init() +void HoymilesRadio::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ) { _dtuSerial.u64 = 0; - _hspi.reset(new SPIClass(HSPI)); - _radio.reset(new RF24(HOYMILES_PIN_CE, HOYMILES_PIN_CS)); + _spiPtr.reset(initialisedSpiBus); + _radio.reset(new RF24(pinCE, initialisedSpiBus->pinSS())); - _hspi->begin(HOYMILES_PIN_SCLK, HOYMILES_PIN_MISO, HOYMILES_PIN_MOSI, HOYMILES_PIN_CS); - _radio->begin(_hspi.get()); + _radio->begin(_spiPtr.get()); _radio->setDataRate(RF24_250KBPS); _radio->enableDynamicPayloads(); @@ -27,7 +26,7 @@ void HoymilesRadio::init() Serial.println(F("Connection error!!")); } - attachInterrupt(digitalPinToInterrupt(HOYMILES_PIN_IRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING); + attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING); openReadingPipe(); _radio->startListening(); @@ -43,17 +42,15 @@ void HoymilesRadio::loop() if (_packetReceived) { Serial.println(F("Interrupt received")); while (_radio->available()) { - if (!_rxBuffer.full()) { - fragment_t* f; - f = _rxBuffer.getFront(); - memset(f->fragment, 0xcc, MAX_RF_PAYLOAD_SIZE); - f->len = _radio->getDynamicPayloadSize(); - f->channel = _radio->getChannel(); - if (f->len > MAX_RF_PAYLOAD_SIZE) - f->len = MAX_RF_PAYLOAD_SIZE; - - _radio->read(f->fragment, f->len); - _rxBuffer.pushFront(f); + if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) { + fragment_t f; + memset(f.fragment, 0xcc, MAX_RF_PAYLOAD_SIZE); + f.len = _radio->getDynamicPayloadSize(); + f.channel = _radio->getChannel(); + if (f.len > MAX_RF_PAYLOAD_SIZE) + f.len = MAX_RF_PAYLOAD_SIZE; + _radio->read(f.fragment, f.len); + _rxBuffer.push(f); } else { Serial.println(F("Buffer full")); _radio->flush_rx(); @@ -64,16 +61,16 @@ void HoymilesRadio::loop() } else { // Perform package parsing only if no packages are received if (!_rxBuffer.empty()) { - fragment_t* f = _rxBuffer.getBack(); - if (checkFragmentCrc(f)) { - std::shared_ptr inv = Hoymiles.getInverterByFragment(f); + fragment_t f = _rxBuffer.back(); + if (checkFragmentCrc(&f)) { + std::shared_ptr inv = Hoymiles.getInverterByFragment(&f); if (nullptr != inv) { // Save packet in inverter rx buffer char buf[30]; - snprintf(buf, sizeof(buf), "RX Channel: %d --> ", f->channel); - dumpBuf(buf, f->fragment, f->len); - inv->addRxFragment(f->fragment, f->len); + snprintf(buf, sizeof(buf), "RX Channel: %d --> ", f.channel); + dumpBuf(buf, f.fragment, f.len); + inv->addRxFragment(f.fragment, f.len); } else { Serial.println(F("Inverter Not found!")); } @@ -83,7 +80,7 @@ void HoymilesRadio::loop() } // Remove paket from buffer even it was corrupted - _rxBuffer.popBack(); + _rxBuffer.pop(); } } diff --git a/lib/Hoymiles/src/HoymilesRadio.h b/lib/Hoymiles/src/HoymilesRadio.h index 1a29af93f..189321dfa 100644 --- a/lib/Hoymiles/src/HoymilesRadio.h +++ b/lib/Hoymiles/src/HoymilesRadio.h @@ -1,6 +1,5 @@ #pragma once -#include "CircularBuffer.h" #include "TimeoutHelper.h" #include "commands/CommandAbstract.h" #include "types.h" @@ -12,33 +11,9 @@ // number of fragments hold in buffer #define FRAGMENT_BUFFER_SIZE 30 -#ifndef HOYMILES_PIN_MISO -#define HOYMILES_PIN_MISO 19 -#endif - -#ifndef HOYMILES_PIN_MOSI -#define HOYMILES_PIN_MOSI 23 -#endif - -#ifndef HOYMILES_PIN_SCLK -#define HOYMILES_PIN_SCLK 18 -#endif - -#ifndef HOYMILES_PIN_IRQ -#define HOYMILES_PIN_IRQ 16 -#endif - -#ifndef HOYMILES_PIN_CE -#define HOYMILES_PIN_CE 4 -#endif - -#ifndef HOYMILES_PIN_CS -#define HOYMILES_PIN_CS 5 -#endif - class HoymilesRadio { public: - void init(); + void init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ); void loop(); void setPALevel(rf24_pa_dbm_e paLevel); @@ -71,7 +46,7 @@ class HoymilesRadio { void sendRetransmitPacket(uint8_t fragment_id); void sendLastPacketAgain(); - std::unique_ptr _hspi; + std::unique_ptr _spiPtr; std::unique_ptr _radio; uint8_t _rxChLst[5] = { 3, 23, 40, 61, 75 }; uint8_t _rxChIdx = 0; @@ -81,7 +56,7 @@ class HoymilesRadio { volatile bool _packetReceived = false; - CircularBuffer _rxBuffer; + std::queue _rxBuffer; TimeoutHelper _rxTimeout; serial_u _dtuSerial; diff --git a/lib/Hoymiles/src/parser/DevInfoParser.cpp b/lib/Hoymiles/src/parser/DevInfoParser.cpp index a9d031359..2b1bd330e 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.cpp +++ b/lib/Hoymiles/src/parser/DevInfoParser.cpp @@ -18,6 +18,7 @@ const devInfo_t devInfo[] = { { { 0x10, 0x11, 0x30, ALL }, 800, "HM-800" }, { { 0x10, 0x11, 0x40, ALL }, 800, "HM-800" }, { { 0x10, 0x12, 0x10, ALL }, 1200, "HM-1200" }, + { { 0x10, 0x02, 0x30, ALL }, 1500, "MI-1500 Gen3" }, { { 0x10, 0x12, 0x30, ALL }, 1500, "HM-1500" }, { { 0x10, 0x10, 0x10, 0x15 }, static_cast(300 * 0.7), "HM-300" }, // HM-300 factory limitted to 70% }; diff --git a/platformio.ini b/platformio.ini index ca07c8b44..495cda6f0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -36,12 +36,19 @@ monitor_speed = 115200 upload_protocol = esptool ; Specify port here. Comment out (add ; in front of line) to use auto detection. -monitor_port = COM5 -upload_port = COM5 +monitor_port = COM4 +upload_port = COM4 [env:generic] board = esp32dev +build_flags = ${env.build_flags} + -DHOYMILES_PIN_MISO=19 + -DHOYMILES_PIN_MOSI=23 + -DHOYMILES_PIN_SCLK=18 + -DHOYMILES_PIN_IRQ=16 + -DHOYMILES_PIN_CE=4 + -DHOYMILES_PIN_CS=5 [env:olimex_esp32_poe] @@ -97,6 +104,7 @@ build_flags = ${env.build_flags} -DHOYMILES_PIN_CS=15 -DOPENDTU_ETHERNET + [env:LilyGO_T_ETH_POE] ; http://www.lilygo.cn/claprod_view.aspx?TypeId=21&Id=1344&FId=t28:21:28 board = esp32dev @@ -113,4 +121,29 @@ build_flags = ${env.build_flags} -DETH_TYPE=ETH_PHY_LAN8720 -DETH_ADDR=0 -DETH_MDC_PIN=23 - -DETH_MDIO_PIN=18 \ No newline at end of file + -DETH_MDIO_PIN=18 + + +[env:esp_s3_12k_kit] +; https://www.waveshare.com/wiki/NodeMCU-ESP-S3-12K-Kit +board = esp32-s3-devkitc-1 +build_flags = ${env.build_flags} + -DHOYMILES_PIN_MISO=16 + -DHOYMILES_PIN_MOSI=17 + -DHOYMILES_PIN_SCLK=18 + -DHOYMILES_PIN_IRQ=3 + -DHOYMILES_PIN_CE=4 + -DHOYMILES_PIN_CS=5 + + +[env:lolin32_lite] +; https://www.makershop.de/plattformen/esp8266/wemos-lolin32/ +; https://www.az-delivery.de/products/esp32-lolin-lolin32 +board = lolin32_lite +build_flags = ${env.build_flags} + -DHOYMILES_PIN_MISO=19 + -DHOYMILES_PIN_MOSI=23 + -DHOYMILES_PIN_SCLK=18 + -DHOYMILES_PIN_IRQ=16 + -DHOYMILES_PIN_CE=17 + -DHOYMILES_PIN_CS=5 \ No newline at end of file diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index d103281e3..5f77b70e9 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -120,7 +120,7 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv createDeviceInfo(deviceObj, inv); if (Configuration.get().Mqtt_Hass_Expire) { - root[F("exp_aft")] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 2; + root[F("exp_aft")] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 3; } if (devCls != 0) { root[F("dev_cla")] = devCls; diff --git a/src/WebApi_ntp.cpp b/src/WebApi_ntp.cpp index a2d1e9361..4c3715473 100644 --- a/src/WebApi_ntp.cpp +++ b/src/WebApi_ntp.cpp @@ -277,6 +277,7 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request) local.tm_mday = root[F("day")].as(); // day of the month - [ 1 to 31 ] local.tm_mon = root[F("month")].as() - 1; // months since January - [ 0 to 11 ] local.tm_year = root[F("year")].as() - 1900; // years since 1900 + local.tm_isdst = -1; time_t t = mktime(&local); struct timeval now = { .tv_sec = t, .tv_usec = 0 }; diff --git a/src/main.cpp b/src/main.cpp index dcbddae01..5e51c6e95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -96,7 +96,9 @@ void setup() // Initialize inverter communication Serial.print(F("Initialize Hoymiles interface... ")); - Hoymiles.init(); + SPIClass* spiClass = new SPIClass(HSPI); + spiClass->begin(HOYMILES_PIN_SCLK, HOYMILES_PIN_MISO, HOYMILES_PIN_MOSI, HOYMILES_PIN_CS); + Hoymiles.init(spiClass, HOYMILES_PIN_CE, HOYMILES_PIN_IRQ); Serial.println(F(" Setting radio PA level... ")); Hoymiles.getRadio()->setPALevel((rf24_pa_dbm_e)config.Dtu_PaLevel); diff --git a/webapp/package.json b/webapp/package.json index dd160a24b..83df423c2 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -28,7 +28,7 @@ "@vue/eslint-config-typescript": "^11.0.2", "@vue/tsconfig": "^0.1.3", "eslint": "^8.28.0", - "eslint-plugin-vue": "^9.7.0", + "eslint-plugin-vue": "^9.8.0", "npm-run-all": "^4.1.5", "sass": "^1.56.1", "typescript": "^4.9.3", diff --git a/webapp/src/views/InverterAdminView.vue b/webapp/src/views/InverterAdminView.vue index 47f0585b3..a19e7bbae 100644 --- a/webapp/src/views/InverterAdminView.vue +++ b/webapp/src/views/InverterAdminView.vue @@ -99,13 +99,13 @@ - W* + Wp* -
*) Input the kWp of the channel to +
*) Input the Wp of the channel to calculate irradiation.
diff --git a/webapp/src/views/NtpAdminView.vue b/webapp/src/views/NtpAdminView.vue index ce18c79c9..dbb104353 100644 --- a/webapp/src/views/NtpAdminView.vue +++ b/webapp/src/views/NtpAdminView.vue @@ -63,7 +63,8 @@
diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 055bc34c9..590c9c032 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -878,10 +878,10 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-vue@^9.7.0: - version "9.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.7.0.tgz#d391b9864f128ea2d1ee4dabeafb5f7c0cea981f" - integrity sha512-DrOO3WZCZEwcLsnd3ohFwqCoipGRSTKTBTnLwdhqAbYZtzWl0o7D+D8ZhlmiZvABKTEl8AFsqH1GHGdybyoQmw== +eslint-plugin-vue@^9.8.0: + version "9.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.8.0.tgz#91de2aabbee8cdbef078ccd4f650a9ecfa445f4f" + integrity sha512-E/AXwcTzunyzM83C2QqDHxepMzvI2y6x+mmeYHbVDQlKFqmKYvRrhaVixEeeG27uI44p9oKDFiyCRw4XxgtfHA== dependencies: eslint-utils "^3.0.0" natural-compare "^1.4.0" diff --git a/webapp_dist/index.html.gz b/webapp_dist/index.html.gz index f7547917e..0830730b7 100644 Binary files a/webapp_dist/index.html.gz and b/webapp_dist/index.html.gz differ diff --git a/webapp_dist/js/app.js.gz b/webapp_dist/js/app.js.gz index 793e6d0be..5199a3c09 100644 Binary files a/webapp_dist/js/app.js.gz and b/webapp_dist/js/app.js.gz differ diff --git a/webapp_dist/zones.json.gz b/webapp_dist/zones.json.gz index 45374b962..f1ea50bf1 100644 Binary files a/webapp_dist/zones.json.gz and b/webapp_dist/zones.json.gz differ