├── .gitattributes ├── LICENSE ├── README.md ├── bin └── firmware.bin ├── firmware └── TachoLED │ ├── TachoLED.ino │ ├── data.h │ ├── hub.h │ ├── led.h │ ├── palettes.h │ └── tacho.h ├── libraries ├── EEManager │ ├── .gitattributes │ ├── LICENSE │ ├── README.md │ ├── README_EN.md │ ├── examples │ │ ├── demo │ │ │ └── demo.ino │ │ ├── demoSimple │ │ │ └── demoSimple.ino │ │ └── manyBlocks │ │ │ └── manyBlocks.ino │ ├── keywords.txt │ ├── library.properties │ └── src │ │ └── EEManager.h ├── GyverHub │ ├── .gitattributes │ ├── LICENSE │ ├── README.md │ ├── docs │ │ ├── 1.main.md │ │ ├── 2.start.md │ │ ├── 3.app.md │ │ ├── 4.basics.md │ │ ├── 5.advanced.md │ │ ├── 6.canvas.md │ │ ├── 7.integration.md │ │ ├── 8.manual.md │ │ └── promo.jpg │ ├── examples │ │ ├── basic │ │ │ └── basic.ino │ │ ├── canvas │ │ │ └── canvas.ino │ │ ├── dynamic_components │ │ │ └── dynamic_components.ino │ │ ├── full_demo │ │ │ └── full_demo.ino │ │ ├── joy_demo │ │ │ └── joy_demo.ino │ │ ├── struct_demo │ │ │ └── struct_demo.ino │ │ └── update │ │ │ └── update.ino │ ├── keywords.txt │ ├── library.properties │ └── src │ │ ├── GyverHub.h │ │ ├── async │ │ ├── http.h │ │ ├── mime.cpp │ │ ├── mime.h │ │ ├── mqtt.h │ │ └── ws.h │ │ ├── builder.h │ │ ├── canvas.h │ │ ├── config.hpp │ │ ├── esp_inc │ │ ├── index.h │ │ ├── script.h │ │ └── style.h │ │ ├── macro.hpp │ │ ├── sync │ │ ├── http.h │ │ ├── mqtt.h │ │ └── ws.h │ │ └── utils │ │ ├── action.h │ │ ├── b64.cpp │ │ ├── b64.h │ │ ├── build.h │ │ ├── button.h │ │ ├── cmd_p.cpp │ │ ├── cmd_p.h │ │ ├── color.h │ │ ├── datatypes.cpp │ │ ├── datatypes.h │ │ ├── flags.h │ │ ├── hub.h │ │ ├── log.h │ │ ├── misc.cpp │ │ ├── misc.h │ │ ├── modules.h │ │ ├── pos.h │ │ ├── pos_geo.cpp │ │ ├── pos_geo.h │ │ ├── stats.h │ │ ├── stats_p.cpp │ │ ├── stats_p.h │ │ └── timer.h ├── arduinoWebSockets-2.3.6 │ ├── .clang-format │ ├── .github │ │ └── workflows │ │ │ └── main.yml │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── examples │ │ ├── Nginx │ │ │ └── esp8266.ssl.reverse.proxy.conf │ │ ├── avr │ │ │ └── WebSocketClientAVR │ │ │ │ └── WebSocketClientAVR.ino │ │ ├── esp32 │ │ │ ├── WebSocketClient │ │ │ │ └── WebSocketClient.ino │ │ │ ├── WebSocketClientSSL │ │ │ │ └── WebSocketClientSSL.ino │ │ │ ├── WebSocketClientSocketIOack │ │ │ │ └── WebSocketClientSocketIOack.ino │ │ │ └── WebSocketServer │ │ │ │ └── WebSocketServer.ino │ │ ├── esp8266 │ │ │ ├── WebSocketClient │ │ │ │ └── WebSocketClient.ino │ │ │ ├── WebSocketClientOTA │ │ │ │ ├── README.md │ │ │ │ ├── WebSocketClientOTA.ino │ │ │ │ └── python_ota_server │ │ │ │ │ ├── main.py │ │ │ │ │ └── requirements.txt │ │ │ ├── WebSocketClientSSL │ │ │ │ └── WebSocketClientSSL.ino │ │ │ ├── WebSocketClientSSLWithCA │ │ │ │ └── WebSocketClientSSLWithCA.ino │ │ │ ├── WebSocketClientSocketIO │ │ │ │ └── WebSocketClientSocketIO.ino │ │ │ ├── WebSocketClientSocketIOack │ │ │ │ └── WebSocketClientSocketIOack.ino │ │ │ ├── WebSocketClientStomp │ │ │ │ └── WebSocketClientStomp.ino │ │ │ ├── WebSocketClientStompOverSockJs │ │ │ │ └── WebSocketClientStompOverSockJs.ino │ │ │ ├── WebSocketServer │ │ │ │ └── WebSocketServer.ino │ │ │ ├── WebSocketServerAllFunctionsDemo │ │ │ │ └── WebSocketServerAllFunctionsDemo.ino │ │ │ ├── WebSocketServerFragmentation │ │ │ │ └── WebSocketServerFragmentation.ino │ │ │ ├── WebSocketServerHooked │ │ │ │ ├── WebSocketServerHooked.ino │ │ │ │ ├── emu │ │ │ │ └── ws-testclient.py │ │ │ ├── WebSocketServerHttpHeaderValidation │ │ │ │ └── WebSocketServerHttpHeaderValidation.ino │ │ │ └── WebSocketServer_LEDcontrol │ │ │ │ └── WebSocketServer_LEDcontrol.ino │ │ └── particle │ │ │ └── ParticleWebSocketClient │ │ │ └── application.cpp │ ├── library.json │ ├── library.properties │ ├── src │ │ ├── SocketIOclient.cpp │ │ ├── SocketIOclient.h │ │ ├── WebSockets.cpp │ │ ├── WebSockets.h │ │ ├── WebSockets4WebServer.h │ │ ├── WebSocketsClient.cpp │ │ ├── WebSocketsClient.h │ │ ├── WebSocketsServer.cpp │ │ ├── WebSocketsServer.h │ │ ├── WebSocketsVersion.h │ │ ├── libb64 │ │ │ ├── AUTHORS │ │ │ ├── LICENSE │ │ │ ├── cdecode.c │ │ │ ├── cdecode_inc.h │ │ │ ├── cencode.c │ │ │ └── cencode_inc.h │ │ └── libsha1 │ │ │ ├── libsha1.c │ │ │ └── libsha1.h │ ├── tests │ │ ├── webSocket.html │ │ └── webSocketServer │ │ │ ├── index.js │ │ │ └── package.json │ └── travis │ │ ├── common.sh │ │ └── version.py └── pubsubclient-2.8 │ ├── .gitignore │ ├── .travis.yml │ ├── CHANGES.txt │ ├── LICENSE.txt │ ├── README.md │ ├── examples │ ├── mqtt_auth │ │ └── mqtt_auth.ino │ ├── mqtt_basic │ │ └── mqtt_basic.ino │ ├── mqtt_esp8266 │ │ └── mqtt_esp8266.ino │ ├── mqtt_large_message │ │ └── mqtt_large_message.ino │ ├── mqtt_publish_in_callback │ │ └── mqtt_publish_in_callback.ino │ ├── mqtt_reconnect_nonblocking │ │ └── mqtt_reconnect_nonblocking.ino │ └── mqtt_stream │ │ └── mqtt_stream.ino │ ├── keywords.txt │ ├── library.json │ ├── library.properties │ ├── src │ ├── PubSubClient.cpp │ └── PubSubClient.h │ └── tests │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── src │ ├── connect_spec.cpp │ ├── keepalive_spec.cpp │ ├── lib │ │ ├── Arduino.h │ │ ├── BDDTest.cpp │ │ ├── BDDTest.h │ │ ├── Buffer.cpp │ │ ├── Buffer.h │ │ ├── Client.h │ │ ├── IPAddress.cpp │ │ ├── IPAddress.h │ │ ├── Print.h │ │ ├── ShimClient.cpp │ │ ├── ShimClient.h │ │ ├── Stream.cpp │ │ ├── Stream.h │ │ └── trace.h │ ├── publish_spec.cpp │ ├── receive_spec.cpp │ └── subscribe_spec.cpp │ ├── testcases │ ├── __init__.py │ ├── mqtt_basic.py │ ├── mqtt_publish_in_callback.py │ └── settings.py │ └── testsuite.py ├── project.json └── schemes └── scheme.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TachoLED 2 | 3 | -------------------------------------------------------------------------------- /bin/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGyver/TachoLED/af7504a83dde779187af78d57a48e02772c97df3/bin/firmware.bin -------------------------------------------------------------------------------- /firmware/TachoLED/TachoLED.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "data.h" 4 | #include "hub.h" 5 | #include "led.h" 6 | #include "tacho.h" 7 | 8 | void setup() { 9 | WiFi.mode(WIFI_AP); 10 | WiFi.softAP("TachoLED"); 11 | 12 | EEPROM.begin(memory.blockSize()); 13 | memory.begin(0, 'b'); 14 | led_init(); 15 | led_change(); 16 | hub_init(); 17 | tacho_init(); 18 | } 19 | 20 | void loop() { 21 | hub_tick(); 22 | led_tick(); 23 | tacho_tick(); 24 | memory.tick(); 25 | } 26 | -------------------------------------------------------------------------------- /firmware/TachoLED/data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define TACHO_PIN D1 6 | #define LED_PIN D2 7 | #define LED_CHIP WS2812 8 | #define LED_ORDER GRB 9 | #define VBAT_MAX 630 10 | #define VBAT_MIN 500 11 | #define LED_PRD 30 12 | 13 | struct Data { 14 | uint16_t led_amount = 26; 15 | uint16_t diam = 68; 16 | uint16_t pal_len = 60; 17 | uint8_t led_bri = 255; 18 | uint8_t ledm = 60; 19 | uint8_t mode = 0; 20 | uint8_t max_spd = 25; 21 | uint8_t pal = 0; 22 | }; 23 | 24 | Data data; 25 | EEManager memory(data); -------------------------------------------------------------------------------- /firmware/TachoLED/hub.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define GH_NO_MQTT 5 | #include 6 | 7 | #include "data.h" 8 | #include "palettes.h" 9 | #include "tacho.h" 10 | 11 | GyverHub hub("MyDevices", "TachoLED", ""); 12 | 13 | static int _analog_f = VBAT_MAX; 14 | 15 | static int getBat() { 16 | int vbat = map(_analog_f, VBAT_MIN, VBAT_MAX, 0, 100); 17 | return constrain(vbat, 0, 100); 18 | } 19 | 20 | void build() { 21 | bool flag = 0; 22 | hub.Title(F("Status")); 23 | hub.BeginWidgets(); 24 | hub.WidgetSize(50); 25 | hub.Gauge_(F("spd"), tacho_kmh(), F("kmh"), F("Speed"), 0, data.max_spd); 26 | hub.Gauge(getBat(), F("%"), F("Battery")); 27 | 28 | hub.Title(F("Mode")); 29 | hub.WidgetSize(100); 30 | flag |= hub.Tabs(&data.mode, F("Pallette,Color"), F("Mode")); 31 | 32 | if (data.mode == 0) { 33 | hub.WidgetSize(50); 34 | flag |= hub.Input(&data.pal_len, GH_UINT16, F("Length [leds]")); 35 | flag |= hub.Select(&data.pal, FPSTR(paletteNames)); 36 | } 37 | 38 | hub.Title(F("Settings")); 39 | hub.WidgetSize(50); 40 | flag |= hub.Input(&data.led_amount, GH_UINT16, F("LED amount")); 41 | flag |= hub.Input(&data.diam, GH_UINT16, F("Diameter [mm]")); 42 | flag |= hub.Input(&data.ledm, GH_UINT8, F("leds/m")); 43 | flag |= hub.Input(&data.max_spd, GH_UINT8, F("Max speed [kmh]")); 44 | hub.WidgetSize(100); 45 | flag |= hub.Slider(&data.led_bri, GH_UINT8, F("Brightness"), 0, 255); 46 | 47 | if (flag) memory.update(); 48 | } 49 | 50 | void hub_init() { 51 | hub.onBuild(build); 52 | hub.begin(); 53 | } 54 | 55 | void hub_tick() { 56 | hub.tick(); 57 | 58 | // filter analog read 59 | static GHtimer vbat(500); 60 | if (vbat) _analog_f += (analogRead(0) - _analog_f) / 4; 61 | 62 | static GHtimer upd(1000); 63 | if (upd) { 64 | hub.sendUpdate(F("spd"), String(tacho_kmh())); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /firmware/TachoLED/led.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "data.h" 6 | #include "hub.h" 7 | #include "palettes.h" 8 | #include "tacho.h" 9 | 10 | CLEDController *cled = nullptr; 11 | CRGB *leds; 12 | 13 | void led_init() { 14 | leds = (CRGB *)malloc(sizeof(CRGB)); 15 | cled = &FastLED.addLeds(leds, 0); 16 | } 17 | 18 | void led_change() { 19 | leds = (CRGB *)realloc(leds, sizeof(CRGB) * data.led_amount); 20 | cled->setLeds(leds, data.led_amount); 21 | } 22 | 23 | void led_tick() { 24 | static GHtimer tmr(LED_PRD); 25 | if (tmr) { 26 | switch (data.mode) { 27 | case 0: { 28 | static uint16_t pos = 0; 29 | pos += tacho_speed() * LED_PRD / 1000; // (mm / s) * (ms / 1000) == mm 30 | uint16_t idx = pos * data.ledm / 1000; // mm * (leds / m / 1000) == leds 31 | 32 | for (uint16_t i = 0; i < data.led_amount; i++) { 33 | leds[data.led_amount - i - 1] = ColorFromPalette(paletteArr[data.pal], 255 - (idx + i) * 255 / data.pal_len, 255, LINEARBLEND); 34 | } 35 | cled->showLeds(data.led_bri); 36 | } break; 37 | 38 | case 1: { 39 | uint16_t spd = min(tacho_speed(), (uint16_t)(data.max_spd * 278)); 40 | cled->showColor(CHSV(map(spd, 0, data.max_spd * 278, 120, 0), 255, 255), data.led_bri); 41 | } break; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /firmware/TachoLED/tacho.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "data.h" 5 | #include "hub.h" 6 | 7 | static volatile uint32_t _prev; 8 | static volatile uint32_t _pulse; 9 | static volatile uint32_t _tprd; 10 | static uint16_t _speed, _speed_f; 11 | 12 | IRAM_ATTR void tachoISR() { 13 | uint32_t us = micros(); 14 | if (!_tprd) _tprd = us - _prev; 15 | _prev = us; 16 | _pulse++; 17 | } 18 | 19 | void tacho_init() { 20 | attachInterrupt(TACHO_PIN, tachoISR, FALLING); 21 | pinMode(TACHO_PIN, INPUT_PULLUP); 22 | } 23 | 24 | uint16_t tacho_speed() { 25 | return _speed_f; 26 | } 27 | uint16_t tacho_kmh() { 28 | return _speed_f / 278; 29 | } 30 | uint32_t tacho_pulse() { 31 | return _pulse; 32 | } 33 | 34 | void tacho_tick() { 35 | if (_tprd) { 36 | _speed = (data.diam * 3141592ul) / _tprd; // (2*Pi*D / (prd / 1000000)) 37 | _tprd = 0; 38 | } 39 | 40 | static GHtimer tmr(50); 41 | if (tmr) { 42 | _speed_f += (_speed - _speed_f) >> 2; 43 | if (_speed && micros() - _prev > 1000000) _speed = _speed_f = 0; 44 | } 45 | } -------------------------------------------------------------------------------- /libraries/EEManager/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /libraries/EEManager/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libraries/EEManager/examples/demo/demo.ino: -------------------------------------------------------------------------------- 1 | // структура для хранения данных 2 | struct Data { 3 | char val = 'H'; 4 | char str[15] = "ello kitty!"; 5 | }; 6 | Data data; // переменная, с которой мы работаем в программе 7 | 8 | #include // подключаем либу 9 | EEManager memory(data); // передаём нашу переменную (фактически её адрес) 10 | 11 | // можно задать таймаут обновления, по умолч. 5 секунд (5000мс) 12 | //EEManager memory(data, 1000); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | // для esp8266 не забудь вызвать EEPROM.begin(размер)! 17 | // EEPROM.begin(memory.blockSize()); 18 | /* 19 | Запускаем менеджер, передаём: 20 | - Стартовый адрес в памяти для записи даты 21 | - Ключ хранения (0.. 255) или символ 22 | */ 23 | byte stat = memory.begin(0, 'b'); 24 | 25 | /* 26 | Коды возврата: 27 | 0 - ключ совпал, данные прочитаны из епром 28 | 1 - ключ не совпал (первый запуск), данные записаны в епром 29 | 2 - ошибка, в епроме не хватает места 30 | */ 31 | Serial.println(stat); 32 | 33 | // выведем в порт всё содержимое блока памяти, включая ключ 34 | for (uint16_t i = memory.startAddr(); i < memory.endAddr() + 1; i++) 35 | Serial.write(EEPROM.read(i)); 36 | Serial.println(); 37 | 38 | data.val = 'X'; // изменим данные в переменной 39 | memory.update(); // отложим обновление 40 | 41 | // примечание: если нужно создать ещё один блок следующим в памяти - 42 | // запускаем его на адресе memory.endAddr() + 1, это первый 43 | // свободный байт после первого блока 44 | } 45 | 46 | void loop() { 47 | // в лупе вызываем tick(), в нём по таймеру произойдёт обновление 48 | // функция вернёт true, когда это случится 49 | if (memory.tick()) Serial.println("Updated!"); 50 | 51 | // выведем в порт всё содержимое блока памяти, включая ключ 52 | for (uint16_t i = memory.startAddr(); i < memory.endAddr() + 1; i++) 53 | Serial.write(EEPROM.read(i)); 54 | Serial.println(); 55 | 56 | // таймер сброса на 10 секунд: через 10 секунд 57 | // произойдёт сброс ключа данных, и при следующем запуске 58 | // в епром будут записаны данные по умолчанию (то что в ярлыке структуры) 59 | static uint32_t tmr; 60 | if (millis() - tmr >= 10000) { 61 | memory.reset(); 62 | Serial.println("reset"); 63 | for (;;); 64 | } 65 | 66 | delay(1000); // чилим 67 | } 68 | -------------------------------------------------------------------------------- /libraries/EEManager/examples/demoSimple/demoSimple.ino: -------------------------------------------------------------------------------- 1 | // структура для хранения данных 2 | struct Data { 3 | byte valB; 4 | int valI; 5 | }; 6 | Data data; // переменная, с которой мы работаем в программе 7 | 8 | #include // подключаем либу 9 | EEManager memory(data); // передаём нашу переменную (фактически её адрес) 10 | 11 | // можно задать таймаут обновления, по умолч. 5 секунд (5000мс) 12 | //EEManager memory(data, 1000); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | // для esp8266 не забудь вызвать EEPROM.begin(размер)! 17 | // EEPROM.begin(memory.blockSize()); 18 | 19 | /* 20 | Запускаем менеджер, передаём: 21 | - Стартовый адрес в памяти для записи даты 22 | - Ключ хранения (0.. 255) или символ 23 | */ 24 | memory.begin(0, 'b'); 25 | // здесь данные уже прочитаны из памяти 26 | Serial.println(data.valB); 27 | Serial.println(data.valI); 28 | 29 | // меняем данные 30 | data.valB = random(100); 31 | data.valI = random(10000); 32 | memory.update(); // отложить обновление 33 | 34 | // вызывать update несколько раз - безопасно 35 | // данные запишутся только после выхода таймаута 36 | memory.update(); 37 | memory.update(); 38 | memory.update(); 39 | } 40 | 41 | void loop() { 42 | // данные автоматически запишутся здесь по таймауту 43 | memory.tick(); 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /libraries/EEManager/examples/manyBlocks/manyBlocks.ino: -------------------------------------------------------------------------------- 1 | // блок 1 - структура 2 | struct DataBlock { 3 | int valI; 4 | byte valB; 5 | }; 6 | DataBlock data; 7 | 8 | // блок 2 - массив 9 | int arr[10]; 10 | 11 | #include 12 | EEManager mem1(data); 13 | EEManager mem2(arr); 14 | 15 | void setup() { 16 | Serial.begin(9600); 17 | // для esp8266 не забудь вызвать EEPROM.begin(размер)! 18 | // EEPROM.begin(mem1.blockSize() + mem2.blockSize()); 19 | 20 | // первый блок храним с адреса 0 21 | mem1.begin(0, 'a'); 22 | 23 | // второй - следом за ним 24 | mem2.begin(mem1.nextAddr(), 'a'); 25 | } 26 | 27 | void loop() { 28 | 29 | } 30 | -------------------------------------------------------------------------------- /libraries/EEManager/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For EEManager 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | EEManager KEYWORD1 9 | 10 | ####################################### 11 | # Methods and Functions (KEYWORD2) 12 | ####################################### 13 | 14 | setTimeout KEYWORD2 15 | begin KEYWORD2 16 | updateNow KEYWORD2 17 | update KEYWORD2 18 | tick KEYWORD2 19 | reset KEYWORD2 20 | dataSize KEYWORD2 21 | blockSize KEYWORD2 22 | startAddr KEYWORD2 23 | endAddr KEYWORD2 24 | nextAddr KEYWORD2 25 | keyAddr KEYWORD2 26 | 27 | EEBlock KEYWORD2 28 | 29 | 30 | ####################################### 31 | # Constants (LITERAL1) 32 | ####################################### -------------------------------------------------------------------------------- /libraries/EEManager/library.properties: -------------------------------------------------------------------------------- 1 | name=EEManager 2 | version=2.0 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Simple library for reducing EEPROM wear 6 | paragraph=Simple library for reducing EEPROM wear 7 | category=Data Storage 8 | url=https://github.com/GyverLibs/EEManager 9 | architectures=* 10 | -------------------------------------------------------------------------------- /libraries/EEManager/src/EEManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | Менеджер EEPROM - библиотека для уменьшения износа памяти 3 | Документация: 4 | GitHub: https://github.com/GyverLibs/EEManager 5 | Возможности: 6 | - Отложенная запись (обновление) по таймеру 7 | - Работает на базе стандартной EEPROM.h 8 | - Встроенный механизм ключа первой записи 9 | 10 | AlexGyver, alex@alexgyver.ru 11 | https://alexgyver.ru/ 12 | MIT License 13 | 14 | Версии: 15 | v1.0 - релиз 16 | v1.1 - изменены коды возврата begin 17 | v1.2 - добавлена nextAddr() 18 | v1.2.1 - поддержка esp32 19 | v1.2.2 - пофиксил варнинг 20 | v1.3 - исправлен критический баг с адресацией, добавлен макрос EEBlock 21 | v1.4 - ещё больше поддержки esp8266/32 22 | v2.0 - ключ запуска перенесён в начало блока для удобства. Обновление библиотеки сбросит данные в EEPROM! 23 | */ 24 | 25 | #ifndef _EEManager_h 26 | #define _EEManager_h 27 | #include 28 | #include 29 | 30 | #define EEBlock(x) (sizeof(x) + 1) 31 | 32 | class EEManager { 33 | public: 34 | // передать данные любого типа, опционально таймаут обновления в мс 35 | template EEManager(T &data, uint16_t tout = 5000) { 36 | _data = (uint8_t*)&data; 37 | _size = sizeof(T); 38 | _tout = tout; 39 | } 40 | 41 | // сменить таймаут 42 | void setTimeout(uint16_t tout = 5000) { 43 | _tout = tout; 44 | } 45 | 46 | // начать работу, прочитать данные в переменную. Принимает адрес начала хранения даты и ключ 47 | uint8_t begin(uint16_t addr, uint8_t key) { 48 | _addr = addr + 1; // данные начнутся со следующего адреса 49 | if (nextAddr() > (uint16_t)EEPROM.length()) return 2; // не хватит места 50 | _ready = 1; // EEPROM запущен и размера хватит 51 | if (EEPROM.read(keyAddr()) != key) { // ключ не совпал 52 | EEPROM.write(keyAddr(), key); // пишем ключ 53 | updateNow(); // пишем стандартные значения 54 | return 1; 55 | } 56 | for (uint16_t i = 0; i < _size; i++) _data[i] = EEPROM.read(_addr + i); 57 | return 0; 58 | } 59 | 60 | // обновить данные в еепром сейчас 61 | void updateNow() { 62 | if (_ready) { 63 | #if defined(ESP8266) || defined(ESP32) 64 | for (uint16_t i = 0; i < _size; i++) EEPROM.write(_addr + i, _data[i]); 65 | EEPROM.commit(); 66 | #else 67 | for (uint16_t i = 0; i < _size; i++) EEPROM.update(_addr + i, _data[i]); 68 | #endif 69 | } 70 | } 71 | 72 | // отложить обновление и сбросить таймер 73 | void update() { 74 | _tmr = millis(); 75 | _update = 1; 76 | } 77 | 78 | // тикер обновления 79 | bool tick() { 80 | if (_update && millis() - _tmr >= _tout) { 81 | updateNow(); 82 | _update = 0; 83 | return 1; 84 | } return 0; 85 | } 86 | 87 | // сбросить ключ запуска. При перезагрузке (или вызове begin) запишутся стандартные данные 88 | void reset() { 89 | EEPROM.write(keyAddr(), EEPROM.read(keyAddr()) + 1); // меняем ключ на +1, при перезапуске будет дефолт 90 | #if defined(ESP8266) || defined(ESP32) 91 | EEPROM.commit(); 92 | #endif 93 | } 94 | 95 | // получить размер данных 96 | uint16_t dataSize() { 97 | return _size; 98 | } 99 | 100 | // получить размер всего блока (данные + ключ) 101 | uint16_t blockSize() { 102 | return _size + 1; 103 | } 104 | 105 | // получить адрес ключа 106 | uint16_t keyAddr() { 107 | return _addr - 1; 108 | } 109 | 110 | // получить адрес первого байта данных в блоке 111 | uint16_t startAddr() { 112 | return _addr; 113 | } 114 | 115 | // получить адрес последнего байта в блоке 116 | uint16_t endAddr() { 117 | return _addr + _size - 1; 118 | } 119 | 120 | // получить первый свободный адрес для следующего блока 121 | uint16_t nextAddr() { 122 | return _addr + _size; 123 | } 124 | 125 | private: 126 | uint8_t* _data; 127 | uint16_t _size, _addr; 128 | bool _ready = 0, _update = 0; 129 | uint32_t _tmr = 0; 130 | uint16_t _tout; 131 | }; 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /libraries/GyverHub/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /libraries/GyverHub/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libraries/GyverHub/docs/7.integration.md: -------------------------------------------------------------------------------- 1 | ## Как это работает 2 | Интеграция в системы умных домов (Яндекс Алиса, Home Assistant...) осуществляется через MQTT. Для этого система умного дома должна быть подключена к тому же MQTT брокеру, что и устройство, либо являться готовым сервисом. Например: 3 | - [WQTT](https://www.wqtt.ru/) - MQTT брокер + панель управления + навык для Алисы 4 | - [Домовёнок Кузя](https://alexstar.ru/) - панель управления + навык для Алисы 5 | 6 | В общем случае это работает следующим образом: 7 | - Библиотека GyverHub сама подписывается на топики для установки значений 8 | - Из устройства можно отправлять данные на известные топики, на которые должен подписаться умный дом 9 | 10 | ### Список топиков 11 | Список топиков с учётом префикса сети `PREFIX` и id устройства `ID` есть во вкладке Info в приложении GyverHub. Имена компонентов `NAME` отображаются во всплывающем окне при наведении курсора на компонент. 12 | 13 | ## Топики для подписки 14 | ### Получение значений 15 | Чтобы получать данные с устройства, умный дом должен подписаться на топик 16 | 17 | `PREFIX`/hub/`ID`/get/`NAME` 18 | 19 | #### Отправка значений вручную 20 | Чтобы отправить данные с устройства в умный дом, достаточно в программе вызвать команду `.sendGet(NAME, VALUE)`, где `NAME` - это имя компонента, `VALUE` - значение. В этом сценарии можно вообще не создавать в билдере компоненты для приложения. Отправлять данные можно из любого места в программе, например по какому то условию (сработал датчик, устройство включено кнопкой, закрыта дверь) или просто по таймеру, чтобы умный дом всегда знал актуальное значение (датчик температуры, заряд батареи). 21 | 22 | #### Отправка значений авто 23 | Вызвать `.sendGet(NAME)` - библиотека вызовет билдер, сама прочитает значение указанного компонента и отправит на get-топик. Имена компонентов можно передать списком через запятую без пробелов `.sendGet("cmp1,cmp2,slider")` - их значения будут отправлены на get-топик отдельными сообщениями. 24 | 25 | > Данную функцию нельзя вызывать внутри билдера. 26 | 27 | #### Автоматическая отправка 28 | Можно включить `.sendGetAuto(true)` - тогда при изменении компонентов с приложения библиотека автоматически отправит новое значение на get-топик. 29 | 30 | #### Dummy 31 | Если GyverHub используется исключительно для интеграции с умным домом, а интерфейс в приложении не нужен - есть специальный компонент `Dummy` - "пустышка". Он не создаёт в панели управления никаких компонентов, но позволяет привязать переменную для автоматизации отправки и принятия запросов из системы умного дома: 32 | 33 | ```cpp 34 | int16_t var; 35 | 36 | void build() { 37 | hub.Dummy_("comp", &var, GH_INT16); 38 | } 39 | ``` 40 | 41 | ### Статус 42 | Чтобы получать статус устройства, умный дом должен подписаться на топик 43 | 44 | `PREFIX`/hub/`ID`/status 45 | 46 | Устройство будет автоматически отправлять сообщение `online` при включении и `offline` при отключении (через Last Will). 47 | 48 | Также в программе можно вызвать 49 | - `.turnOn()` для отправки состояния online 50 | - `.turnOff()` для отправки состояния offline 51 | 52 | ## Топики для отправки 53 | ### Установка значения 54 | Отправить новое значение для компонента можно на топик 55 | 56 | `PREFIX`/`ID`/set/`NAME` 57 | 58 | > Примечание: не работает для кнопок 59 | 60 | ### Запрос чтения 61 | Для запроса значения нужно отправить пустое сообщение на топик: 62 | 63 | `PREFIX`/`ID`/read/`NAME` 64 | 65 | Получив это сообщение, библиотека ответит текущим значением на get-топик, значение компонента будет прочитано в билдере. -------------------------------------------------------------------------------- /libraries/GyverHub/docs/8.manual.md: -------------------------------------------------------------------------------- 1 | ## Ручной режим 2 | Библиотека позволяет работать с микроконтроллером в ручном режиме, то есть без встроенных способов связи (WebSocket/MQTT), либо со своей реализацией этих способов. Для работы в ручном режиме нужно реализовать в программа прием и передачу по любому из способов связи, которые поддерживает приложение GyverHub (WebSocket, MQTT, Serial, Bluetooth) при помощи любых сторонних библиотек и аппаратных модулей. 3 | 4 | ### Своя реализация MQTT/WS для ESPxx 5 | Если необходимо сделать свою реализацию этих протоколов в скетче, то рекомендуется отключить встроенные: 6 | ```cpp 7 | // перед подключением GyverHub 8 | #define GH_NO_WS // убрать WebSocket 9 | #define GH_NO_MQTT // убрать MQTT 10 | 11 | #include 12 | ``` 13 | 14 | ### Парсинг запроса 15 | Полученный из приложения запрос (см. [API](https://github.com/GyverLibs/GyverHub/wiki#api)) нужно передать в функцию `parse`: 16 | - `parse(char* url, GHconn_t conn)` - парсить команду вида `PREFIX/ID/HUB_ID/CMD/NAME=VALUE` 17 | - `parse(char* url, char* value, GHconn_t conn)` - парсить команду вида `PREFIX/ID/HUB_ID/CMD/NAME`, `VALUE` отдельной строкой 18 | 19 | > Если запрос приходит в виде `String`, то передать как `(char*)str.c_str()` 20 | 21 | > `GHconn_t` - тип соединения (`GH_SERIAL`, `GH_BT`, `GH_WS`, `GH_MQTT`). Он же будет передан в обработчик ответа на запрос для ответа по тому же протоколу. 22 | 23 | Пример для Serial: 24 | ```cpp 25 | void loop() { 26 | if (Serial.available()) { 27 | String str = Serial.readStringUntil('\0'); 28 | hub.parse((char*)str.c_str(), GH_SERIAL); 29 | } 30 | } 31 | ``` 32 | 33 | ### Ответ на запрос 34 | Библиотека разберёт запрос и сформирует ответ в виде `String` строки. Получить ответ для отправки в приложение можно в подключенной функции вида `f(String& s, GHconn_t conn, bool broadcast)`, например так: 35 | 36 | ```cpp 37 | void manual(String& s, GHconn_t conn, bool br) { 38 | switch(conn) { 39 | case GH_SERIAL: 40 | //Serial.print(s); 41 | break; 42 | 43 | case GH_WS: 44 | //if (br) broadcastWS(s); 45 | //else sendWS(s); 46 | break; 47 | } 48 | } 49 | 50 | void setup() { 51 | hub.onManual(manual); 52 | } 53 | ``` 54 | 55 | > Обработчик `onManual()` по сути вызывается внутри функции `parse()` 56 | 57 | #### Флаг broadcast 58 | Этот флаг указывает на то, что ответ должен быть отправлен всем клиентам. При `false` нужно отправить ответ только клиенту, от которого пришел запрос. При `true` - в том числе всем остальным клиентам, если это возможно (например при MQTT и WebSocket соединении). 59 | 60 | ### Размер буфера 61 | При помощи `.setBufferSize(uint16_t size)` можно установить размер буфера отправки пакета с компонентами панели управления в ручном режиме. 62 | - При размере `0` пакет будет собран полностью и строка займет столько, сколько весит пакет компонентов 63 | - При другом указанном размере буфера обработчик `.onManual()` будет вызываться с частями пакета для отправки, а строка не будет превышать указанную длину! -------------------------------------------------------------------------------- /libraries/GyverHub/docs/promo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGyver/TachoLED/af7504a83dde779187af78d57a48e02772c97df3/libraries/GyverHub/docs/promo.jpg -------------------------------------------------------------------------------- /libraries/GyverHub/examples/canvas/canvas.ino: -------------------------------------------------------------------------------- 1 | // CANVAS DEMO 2 | 3 | // WiFi 4 | #define AP_SSID "" 5 | #define AP_PASS "" 6 | 7 | #include 8 | #include 9 | GyverHub hub("MyDevices", "ESP8266", ""); 10 | 11 | GHpos pos1; // обработка кликов по холсту 12 | 13 | void build() { 14 | hub.BeginWidgets(); 15 | 16 | // пустой холст, 400x300px 17 | // зададим имя, чтобы обновлять его ниже в loop() 18 | hub.Canvas_(F("cv")); 19 | 20 | hub.WidgetSize(50); 21 | 22 | // холст с рисунком. Обязательный порядок вызова: создать, начать, рисовать, закончить 23 | GHcanvas cv1; // создать холст 24 | // начать рисование, холст 200x200, обработка кликов 25 | // зададим имя, чтобы обновлять его ниже в loop() 26 | hub.BeginCanvas_(F("cv1"), 200, 200, &cv1, &pos1); 27 | cv1.stroke(0xff0000); 28 | cv1.strokeWeight(5); 29 | cv1.line(0, 0, -1, -1); 30 | cv1.line(0, -1, -1, 0); 31 | hub.EndCanvas(); // закончить холст 32 | 33 | // и ещё один 34 | GHcanvas cv2; 35 | // зададим имя, чтобы обновлять его ниже в loop() 36 | hub.BeginCanvas_(F("cv2"), 300, 300, &cv2); 37 | cv2.fill(0x00ff00); 38 | cv2.noStroke(); 39 | cv2.circle(150, 150, 50); 40 | hub.EndCanvas(); 41 | } 42 | 43 | void setup() { 44 | Serial.begin(115200); 45 | 46 | #ifdef GH_ESP_BUILD 47 | WiFi.mode(WIFI_STA); 48 | WiFi.begin(AP_SSID, AP_PASS); 49 | while (WiFi.status() != WL_CONNECTED) { 50 | delay(500); 51 | Serial.print("."); 52 | } 53 | Serial.println(); 54 | Serial.println(WiFi.localIP()); 55 | 56 | hub.setupMQTT("test.mosquitto.org", 1883); 57 | #endif 58 | 59 | hub.onBuild(build); 60 | hub.begin(); 61 | } 62 | 63 | void loop() { 64 | hub.tick(); 65 | 66 | // обработка кликов 67 | if (pos1.changed()) { 68 | Serial.println("Canvas 1 click:"); 69 | Serial.println(pos1.x); 70 | Serial.println(pos1.y); 71 | 72 | // выведем кружок в место клика 73 | GHcanvas cv; 74 | hub.sendCanvasBegin(F("cv1"), cv); 75 | cv.circle(pos1.x, pos1.y, 10); 76 | hub.sendCanvasEnd(cv); 77 | } 78 | 79 | // обновление холста по таймеру 80 | static GHtimer tmr(300); 81 | if (tmr.ready()) { 82 | // способ 1 83 | GHcanvas cv; // создать холст 84 | cv.noStroke(); 85 | cv.fill(GHcolor(random(255), random(255), random(255)), random(100, 255)); 86 | cv.circle(random(0, 400), random(0, 300), random(5, 30)); 87 | hub.sendCanvas(F("cv"), cv); // отправить холст 88 | 89 | // способ 2 (использует меньше оперативной памяти!) 90 | GHcanvas cv2; // создать холст 91 | hub.sendCanvasBegin(F("cv2"), cv2); // начать отправку 92 | cv2.stroke(0xffffff, 100); 93 | cv2.strokeWeight(5); 94 | cv2.line(random(0, 300), random(0, 300), random(0, 300), random(0, 300)); 95 | hub.sendCanvasEnd(cv2); // закончить отправку 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /libraries/GyverHub/examples/dynamic_components/dynamic_components.ino: -------------------------------------------------------------------------------- 1 | // динамически создаваемые компоненты 2 | 3 | #include 4 | 5 | #define AP_SSID "" 6 | #define AP_PASS "" 7 | 8 | #include 9 | GyverHub hub("MyDevices", "ESP8266", ""); 10 | 11 | #define MAX_TEXT 20 12 | #define DYN_MAX 5 13 | bool sws[DYN_MAX]; 14 | int16_t slds[DYN_MAX]; 15 | char inputs[DYN_MAX][20]; 16 | uint8_t spin_am = 2; 17 | uint8_t tab = 0; 18 | 19 | void build() { 20 | hub.BeginWidgets(); 21 | 22 | hub.WidgetSize(80); 23 | hub.Tabs(&tab, F("Sliders,Switches,Inputs,Buttons")); 24 | 25 | // спиннер с настройкой количества. По клику обновляем страницу 26 | hub.WidgetSize(20); 27 | if (hub.Spinner(&spin_am, GH_UINT8, F("Amount"), 0, DYN_MAX, 1)) { 28 | hub.refresh(); 29 | } 30 | 31 | switch (tab) { 32 | case 0: 33 | hub.WidgetSize(100); 34 | for (int i = 0; i < spin_am; i++) { 35 | bool a = hub.Slider(&slds[i], GH_INT16, String("Slider #") + i); 36 | if (a) Serial.println(String("Set slider: #") + i + ", value: " + slds[i]); 37 | } 38 | break; 39 | case 1: 40 | hub.WidgetSize(25); 41 | for (int i = 0; i < spin_am; i++) { 42 | bool a = hub.Switch(&sws[i], String("Switch #") + i); 43 | if (a) Serial.println(String("Set switch: #") + i + ", value: " + sws[i]); 44 | } 45 | break; 46 | case 2: 47 | hub.WidgetSize(50); 48 | for (int i = 0; i < spin_am; i++) { 49 | bool a = hub.Input(&inputs[i], GH_CSTR, String("Input #") + i); 50 | if (a) Serial.println(String("Set input: #") + i + ", value: " + inputs[i]); 51 | } 52 | break; 53 | case 3: 54 | hub.WidgetSize(25); 55 | for (int i = 0; i < spin_am; i++) { 56 | // имена компонентов тоже можно генерировать, если это нужно 57 | bool a = (hub.Button_(String("btn/") + i, 0, String("Button #") + i) == 1); 58 | if (a) Serial.println(String("Pressed button: btn/") + i); 59 | } 60 | break; 61 | } 62 | } 63 | 64 | void setup() { 65 | Serial.begin(115200); 66 | 67 | #ifdef GH_ESP_BUILD 68 | WiFi.mode(WIFI_STA); 69 | WiFi.begin(AP_SSID, AP_PASS); 70 | while (WiFi.status() != WL_CONNECTED) { 71 | delay(500); 72 | Serial.print("."); 73 | } 74 | Serial.println(); 75 | Serial.println(WiFi.localIP()); 76 | 77 | hub.setupMQTT("test.mosquitto.org", 1883); 78 | #endif 79 | 80 | hub.onBuild(build); 81 | hub.begin(); 82 | } 83 | 84 | void loop() { 85 | hub.tick(); 86 | } -------------------------------------------------------------------------------- /libraries/GyverHub/examples/joy_demo/joy_demo.ino: -------------------------------------------------------------------------------- 1 | // JOY DEMO 2 | 3 | // WiFi 4 | #define AP_SSID "" 5 | #define AP_PASS "" 6 | 7 | #include 8 | #include 9 | GyverHub hub("MyDevices", "ESP8266", ""); 10 | 11 | GHpos pos2; 12 | 13 | void build() { 14 | hub.BeginWidgets(); 15 | hub.WidgetSize(50); 16 | 17 | // первый обработаем в билдере 18 | GHpos pos1; 19 | if (hub.Joystick(&pos1)) { 20 | Serial.println(pos1.x); 21 | Serial.println(pos1.y); 22 | } 23 | 24 | // второй в loop 25 | hub.Joystick(&pos2, 0, 1, F("my joy"), GH_RED); 26 | } 27 | 28 | void setup() { 29 | Serial.begin(115200); 30 | 31 | #ifdef GH_ESP_BUILD 32 | WiFi.mode(WIFI_STA); 33 | WiFi.begin(AP_SSID, AP_PASS); 34 | while (WiFi.status() != WL_CONNECTED) { 35 | delay(500); 36 | Serial.print("."); 37 | } 38 | Serial.println(); 39 | Serial.println(WiFi.localIP()); 40 | 41 | hub.setupMQTT("test.mosquitto.org", 1883); 42 | #endif 43 | 44 | hub.onBuild(build); 45 | hub.begin(); 46 | } 47 | 48 | void loop() { 49 | hub.tick(); 50 | 51 | if (pos2.changed()) { 52 | Serial.println("joy 2:"); 53 | Serial.println(pos2.x); 54 | Serial.println(pos2.y); 55 | } 56 | } -------------------------------------------------------------------------------- /libraries/GyverHub/examples/struct_demo/struct_demo.ino: -------------------------------------------------------------------------------- 1 | // DATA STRUCT 2 | 3 | // WiFi 4 | #define AP_SSID "" 5 | #define AP_PASS "" 6 | 7 | #include 8 | #include 9 | #include 10 | GyverHub hub("MyDevices", "ESP8266", ""); 11 | 12 | struct Data { 13 | bool sw; 14 | char inp[10]; 15 | uint16_t sld; 16 | float spin; 17 | Stamp date; 18 | GHcolor col; 19 | GHflags flags; 20 | }; 21 | 22 | Data data; 23 | 24 | void build() { 25 | // Задача - получить сигнал о том, что было изменение и 26 | // нужно сохранить данные в память (EEPROM, файл итд) 27 | 28 | // ================= СПОСОБ 1 ================= 29 | GHbuild b = hub.getBuild(); 30 | 31 | hub.Switch(&data.sw, 0); 32 | hub.Input(&data.inp, GH_CSTR, 0, 10); 33 | hub.Slider(&data.sld, GH_INT16); 34 | hub.Spinner(&data.spin, GH_FLOAT); 35 | hub.Date(&data.date); 36 | hub.Color(&data.col); 37 | hub.Flags(&data.flags); 38 | 39 | // было действие установки (ЛЮБОЕ НА СТРАНИЦЕ) 40 | if (b.action.type == GH_ACTION_SET) { 41 | // сохраняем структуру data 42 | } 43 | 44 | // ================= СПОСОБ 2 ================= 45 | bool flag = 0; 46 | flag |= hub.Switch(&data.sw, 0); 47 | flag |= hub.Input(&data.inp, GH_CSTR, 0, 10); 48 | flag |= hub.Slider(&data.sld, GH_INT16); 49 | flag |= hub.Spinner(&data.spin, GH_FLOAT); 50 | flag |= hub.Date(&data.date); 51 | flag |= hub.Color(&data.col); 52 | flag |= hub.Flags(&data.flags); 53 | 54 | // если хоть один из компонентов кликнут, flag будет 1 55 | // в отличие от первого способа, можно гибко разбивать компоненты 56 | // на группы, вводя несколько флагов для разных структур 57 | if (flag) { 58 | // сохраняем структуру data 59 | } 60 | } 61 | 62 | void setup() { 63 | Serial.begin(115200); 64 | 65 | #ifdef GH_ESP_BUILD 66 | WiFi.mode(WIFI_STA); 67 | WiFi.begin(AP_SSID, AP_PASS); 68 | while (WiFi.status() != WL_CONNECTED) { 69 | delay(500); 70 | Serial.print("."); 71 | } 72 | Serial.println(); 73 | Serial.println(WiFi.localIP()); 74 | 75 | hub.setupMQTT("test.mosquitto.org", 1883); 76 | #endif 77 | 78 | hub.onBuild(build); 79 | hub.begin(); 80 | } 81 | 82 | void loop() { 83 | hub.tick(); 84 | } -------------------------------------------------------------------------------- /libraries/GyverHub/examples/update/update.ino: -------------------------------------------------------------------------------- 1 | // UPDATE DEMO 2 | 3 | // WiFi 4 | #define AP_SSID "" 5 | #define AP_PASS "" 6 | 7 | #include 8 | #include 9 | GyverHub hub("MyDevices", "ESP8266", ""); 10 | 11 | void build() { 12 | hub.BeginWidgets(); 13 | hub.WidgetSize(50); 14 | 15 | // обновляемым компонентам нужно присвоить уникальные имена 16 | // чтобы было на кого отправлять обновления 17 | hub.Label_(F("lbl")); 18 | 19 | hub.WidgetSize(25); 20 | hub.LED_(F("led")); 21 | 22 | // по клику по кнопке 23 | if (hub.ButtonIcon(0, F(""))) { 24 | static bool led; 25 | led = !led; 26 | hub.sendUpdate("ga", String(random(100))); // обновляем шкалу 27 | hub.sendUpdate("led", String(led)); // обновляем светодиод 28 | } 29 | 30 | hub.WidgetSize(50); 31 | hub.Canvas_(F("cv")); 32 | hub.Gauge_(F("ga")); 33 | } 34 | 35 | void setup() { 36 | Serial.begin(115200); 37 | 38 | #ifdef GH_ESP_BUILD 39 | WiFi.mode(WIFI_STA); 40 | WiFi.begin(AP_SSID, AP_PASS); 41 | while (WiFi.status() != WL_CONNECTED) { 42 | delay(500); 43 | Serial.print("."); 44 | } 45 | Serial.println(); 46 | Serial.println(WiFi.localIP()); 47 | 48 | hub.setupMQTT("test.mosquitto.org", 1883); 49 | #endif 50 | 51 | hub.onBuild(build); 52 | hub.begin(); 53 | } 54 | 55 | void loop() { 56 | hub.tick(); 57 | 58 | // таймер на 500 мс 59 | // добавим случайных кругов на холст 60 | static GHtimer tmr1(500); 61 | if (tmr1.ready()) { 62 | GHcanvas cv; 63 | cv.fill(GHcolor(random(255), random(255), random(255)), random(100, 255)); 64 | cv.circle(random(0, 40) * 10, random(0, 30) * 10, random(5, 30)); 65 | hub.sendCanvas(F("cv"), cv); 66 | } 67 | 68 | // таймер на 1с 69 | // выведем миллис на label 70 | static GHtimer tmr2(1000); 71 | if (tmr2.ready()) { 72 | hub.sendUpdate("lbl", String(millis())); 73 | } 74 | } -------------------------------------------------------------------------------- /libraries/GyverHub/library.properties: -------------------------------------------------------------------------------- 1 | name=GyverHub 2 | version=1.0 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=ESP8266/ESP32/Arduino control panel with in-sketch GUI builder 6 | paragraph=ESP8266/ESP32/Arduino control panel with in-sketch GUI builder 7 | category=Communication 8 | url=https://github.com/GyverLibs/GyverHub 9 | architectures=* 10 | depends=PubSubClient,WebSockets -------------------------------------------------------------------------------- /libraries/GyverHub/src/async/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | #include "../macro.hpp" 4 | 5 | #ifdef GH_ESP_BUILD 6 | #ifdef GH_NO_WS 7 | class HubHTTP { 8 | public: 9 | }; 10 | #else 11 | 12 | #include 13 | #include 14 | 15 | #ifndef GH_NO_FS 16 | #if (GH_FS == LittleFS) 17 | #include 18 | #elif (GH_FS == SPIFFS) 19 | #include 20 | #endif 21 | #endif 22 | 23 | #ifdef GH_INCLUDE_PORTAL 24 | #include "../esp_inc/index.h" 25 | #include "../esp_inc/script.h" 26 | #include "../esp_inc/style.h" 27 | #endif 28 | 29 | class HubHTTP { 30 | // ============ PUBLIC ============= 31 | public: 32 | AsyncWebServer server; 33 | 34 | HubHTTP() : server(GH_HTTP_PORT) {} 35 | 36 | // ============ PROTECTED ============= 37 | protected: 38 | void beginHTTP() { 39 | server.on("/hub_discover_all", HTTP_GET, [this](AsyncWebServerRequest* req) { 40 | AsyncWebServerResponse* resp = req->beginResponse(200, F("text/plain"), F("OK")); 41 | req->send(resp); 42 | }); 43 | 44 | #ifndef GH_NO_PORTAL 45 | server.on("/favicon.svg", HTTP_GET, [this](AsyncWebServerRequest* request) { 46 | AsyncWebServerResponse* response = request->beginResponse(200); 47 | request->send(response); 48 | }); 49 | #ifdef GH_INCLUDE_PORTAL 50 | server.on("/", HTTP_GET, [this](AsyncWebServerRequest* request) { 51 | AsyncWebServerResponse* response = request->beginResponse_P(200, "text/html", hub_index_h, hub_index_h_len); 52 | gzip_h(response); 53 | cache_h(response); 54 | request->send(response); 55 | }); 56 | server.on("/script.js", HTTP_GET, [this](AsyncWebServerRequest* request) { 57 | AsyncWebServerResponse* response = request->beginResponse_P(200, "text/javascript", hub_script_h, hub_script_h_len); 58 | gzip_h(response); 59 | cache_h(response); 60 | request->send(response); 61 | }); 62 | server.on("/style.css", HTTP_GET, [this](AsyncWebServerRequest* request) { 63 | AsyncWebServerResponse* response = request->beginResponse_P(200, "text/css", hub_style_h, hub_style_h_len); 64 | gzip_h(response); 65 | cache_h(response); 66 | request->send(response); 67 | }); 68 | #else 69 | #ifndef GH_NO_FS 70 | server.on("/", HTTP_GET, [this](AsyncWebServerRequest* request) { 71 | AsyncWebServerResponse* response = request->beginResponse(GH_FS, "/hub/index.html.gz", "text/html"); 72 | gzip_h(response); 73 | cache_h(response); 74 | request->send(response); 75 | }); 76 | server.on("/script.js", HTTP_GET, [this](AsyncWebServerRequest* request) { 77 | AsyncWebServerResponse* response = request->beginResponse(GH_FS, "/hub/script.js.gz", "text/javascript"); 78 | gzip_h(response); 79 | cache_h(response); 80 | request->send(response); 81 | }); 82 | server.on("/style.css", HTTP_GET, [this](AsyncWebServerRequest* request) { 83 | AsyncWebServerResponse* response = request->beginResponse(GH_FS, "/hub/style.css.gz", "text/css"); 84 | gzip_h(response); 85 | cache_h(response); 86 | request->send(response); 87 | }); 88 | #endif 89 | #endif 90 | #endif 91 | CORS(); 92 | server.begin(); 93 | } 94 | 95 | void endHTTP() { 96 | server.end(); 97 | } 98 | 99 | void tickHTTP() { 100 | } 101 | 102 | // ============ PRIVATE ============= 103 | private: 104 | void CORS() { 105 | DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), F("*")); 106 | DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Private-Network"), F("true")); 107 | DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), F("*")); 108 | } 109 | void gzip_h(AsyncWebServerResponse* response) { 110 | response->addHeader("Content-Encoding", "gzip"); 111 | } 112 | void cache_h(AsyncWebServerResponse* response) { 113 | response->addHeader(F("Cache-Control"), GH_CACHE_PRD); 114 | } 115 | }; 116 | #endif 117 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/async/mime.cpp: -------------------------------------------------------------------------------- 1 | #include "mime.h" 2 | 3 | #define GH_MIME_AMOUNT 17 4 | 5 | GH_PGM(_GH_MIME_EX0, ".avi"); 6 | GH_PGM(_GH_MIME_EX1, ".bin"); 7 | GH_PGM(_GH_MIME_EX2, ".bmp"); 8 | GH_PGM(_GH_MIME_EX3, ".css"); 9 | GH_PGM(_GH_MIME_EX4, ".csv"); 10 | GH_PGM(_GH_MIME_EX5, ".gz"); 11 | GH_PGM(_GH_MIME_EX6, ".gif"); 12 | GH_PGM(_GH_MIME_EX7, ".html"); 13 | GH_PGM(_GH_MIME_EX8, ".jpeg"); 14 | GH_PGM(_GH_MIME_EX9, ".jpg"); 15 | GH_PGM(_GH_MIME_EX10, ".js"); 16 | GH_PGM(_GH_MIME_EX11, ".json"); 17 | GH_PGM(_GH_MIME_EX12, ".png"); 18 | GH_PGM(_GH_MIME_EX13, ".svg"); 19 | GH_PGM(_GH_MIME_EX14, ".txt"); 20 | GH_PGM(_GH_MIME_EX15, ".wav"); 21 | GH_PGM(_GH_MIME_EX16, ".xml"); 22 | GH_PGM_LIST(_GH_mimie_ex_list, _GH_MIME_EX0, _GH_MIME_EX1, _GH_MIME_EX2, _GH_MIME_EX3, _GH_MIME_EX4, _GH_MIME_EX5, _GH_MIME_EX6, _GH_MIME_EX7, _GH_MIME_EX8, _GH_MIME_EX9, _GH_MIME_EX10, _GH_MIME_EX11, _GH_MIME_EX12, _GH_MIME_EX13, _GH_MIME_EX14, _GH_MIME_EX15, _GH_MIME_EX16); 23 | 24 | GH_PGM(_GH_MIME0, "video/x-msvideo"); 25 | GH_PGM(_GH_MIME1, "application/octet-stream"); 26 | GH_PGM(_GH_MIME2, "image/bmp"); 27 | GH_PGM(_GH_MIME3, "text/css"); 28 | GH_PGM(_GH_MIME4, "text/csv"); 29 | GH_PGM(_GH_MIME5, "application/gzip"); 30 | GH_PGM(_GH_MIME6, "image/gif"); 31 | GH_PGM(_GH_MIME7, "text/html"); 32 | GH_PGM(_GH_MIME8, "image/jpeg"); 33 | GH_PGM(_GH_MIME9, "image/jpeg"); 34 | GH_PGM(_GH_MIME10, "text/javascript"); 35 | GH_PGM(_GH_MIME11, "application/json"); 36 | GH_PGM(_GH_MIME12, "image/png"); 37 | GH_PGM(_GH_MIME13, "image/svg+xml"); 38 | GH_PGM(_GH_MIME14, "text/plain"); 39 | GH_PGM(_GH_MIME15, "audio/wav"); 40 | GH_PGM(_GH_MIME16, "application/xml"); 41 | GH_PGM_LIST(_GH_mimie_list, _GH_MIME0, _GH_MIME1, _GH_MIME2, _GH_MIME3, _GH_MIME4, _GH_MIME5, _GH_MIME6, _GH_MIME7, _GH_MIME8, _GH_MIME9, _GH_MIME10, _GH_MIME11, _GH_MIME12, _GH_MIME13, _GH_MIME14, _GH_MIME15, _GH_MIME16); 42 | 43 | String GHgetMime(const String& path) { 44 | for (uint16_t i = 0; i < GH_MIME_AMOUNT; i++) { 45 | if (path.endsWith(FPSTR(_GH_mimie_ex_list[i]))) return FPSTR(_GH_mimie_list[i]); 46 | } 47 | return F("text/plain"); 48 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/async/mime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../macro.hpp" 5 | 6 | String GHgetMime(const String& path); -------------------------------------------------------------------------------- /libraries/GyverHub/src/async/mqtt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | #include "../macro.hpp" 4 | 5 | #ifdef GH_ESP_BUILD 6 | #ifdef GH_NO_WS 7 | class HubMQTT { 8 | public: 9 | void setupMQTT(const char* host, uint16_t port, const char* login = nullptr, const char* pass = nullptr, uint8_t nqos = 0, bool nret = 0) {} 10 | }; 11 | #else 12 | 13 | #include 14 | #include 15 | 16 | #include "../utils/stats.h" 17 | 18 | class HubMQTT { 19 | // ============ PUBLIC ============= 20 | public: 21 | // настроить MQTT (хост брокера, порт, логин, пароль, QoS, retained) 22 | void setupMQTT(const char* host, uint16_t port, const char* login = nullptr, const char* pass = nullptr, uint8_t nqos = 0, bool nret = 0) { 23 | if (!strlen(host)) return; 24 | mqtt.setServer(host, port); 25 | _setupMQTT(login, pass, nqos, nret); 26 | } 27 | void setupMQTT(IPAddress ip, uint16_t port, const char* login = nullptr, const char* pass = nullptr, uint8_t nqos = 0, bool nret = 0) { 28 | mqtt.setServer(ip, port); 29 | _setupMQTT(login, pass, nqos, nret); 30 | } 31 | 32 | // MQTT подключен 33 | bool online() { 34 | return mqtt.connected(); 35 | } 36 | 37 | // ============ PROTECTED ============= 38 | protected: 39 | virtual void parse(char* url, char* value, GHconn_t conn, bool manual) = 0; 40 | virtual const char* getPrefix() = 0; 41 | virtual const char* getID() = 0; 42 | virtual void sendEvent(GHevent_t state, GHconn_t conn) = 0; 43 | 44 | void beginMQTT() { 45 | mqtt.onConnect([this](GH_UNUSED bool pres) { 46 | String sub_topic(getPrefix()); 47 | mqtt.subscribe(sub_topic.c_str(), qos); 48 | 49 | sub_topic += '/'; 50 | sub_topic += getID(); 51 | sub_topic += "/#"; 52 | mqtt.subscribe(sub_topic.c_str(), qos); 53 | 54 | String status(getPrefix()); 55 | status += F("/hub/"); 56 | status += getID(); 57 | status += F("/status"); 58 | String offline(F("offline")); 59 | mqtt.setWill(status.c_str(), qos, ret, offline.c_str()); 60 | 61 | String online(F("online")); 62 | sendMQTT(status, online); 63 | sendEvent(GH_CONNECTED, GH_MQTT); 64 | mqtt_tmr = millis(); 65 | }); 66 | 67 | mqtt.onDisconnect([this](GH_UNUSED AsyncMqttClientDisconnectReason reason) { 68 | String m_id("DEV-"); 69 | m_id += String(random(0xffffff), HEX); 70 | mqtt.setClientId(m_id.c_str()); 71 | sendEvent(GH_DISCONNECTED, GH_MQTT); 72 | mqtt_tmr = millis(); 73 | }); 74 | 75 | mqtt.onMessage([this](char* topic, char* data, GH_UNUSED AsyncMqttClientMessageProperties prop, size_t len, GH_UNUSED size_t index, GH_UNUSED size_t total) { 76 | char data_c[len + 1]; 77 | if (len) strncpy(data_c, (char*)data, len); 78 | data_c[len] = 0; 79 | parse(topic, data_c, GH_MQTT, false); 80 | }); 81 | } 82 | 83 | void endMQTT() { 84 | mqtt.disconnect(); 85 | } 86 | 87 | void tickMQTT() { 88 | if (mq_configured && !mqtt.connected() && (!mqtt_tmr || millis() - mqtt_tmr > GH_MQTT_RECONNECT)) { 89 | mqtt_tmr = millis(); 90 | sendEvent(GH_CONNECTING, GH_MQTT); 91 | mqtt.connect(); 92 | } 93 | } 94 | 95 | void sendMQTT(const String& topic, const String& msg) { 96 | if (mqtt.connected()) mqtt.publish(topic.c_str(), qos, ret, msg.c_str(), msg.length()); 97 | } 98 | 99 | void sendMQTT(const String& msg) { 100 | String topic(getPrefix()); 101 | topic += F("/hub"); 102 | sendMQTT(topic, msg); 103 | } 104 | 105 | void answerMQTT(const String& msg, const char* hubID) { 106 | String topic(getPrefix()); 107 | topic += F("/hub/"); 108 | topic += hubID; 109 | topic += '/'; 110 | topic += getID(); 111 | sendMQTT(topic, msg); 112 | } 113 | 114 | // ============ PRIVATE ============= 115 | private: 116 | void _setupMQTT(const char* login, const char* pass, uint8_t nqos, bool nret) { 117 | if (mqtt.connected()) mqtt.disconnect(); 118 | mqtt.setCredentials(login, pass); 119 | qos = nqos; 120 | ret = nret; 121 | mq_configured = true; 122 | } 123 | 124 | AsyncMqttClient mqtt; 125 | bool mq_configured = false; 126 | uint32_t mqtt_tmr = 0; 127 | uint8_t qos = 0; 128 | bool ret = 0; 129 | }; 130 | #endif 131 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/async/ws.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | #include "../macro.hpp" 4 | 5 | #ifdef GH_ESP_BUILD 6 | #ifdef GH_NO_WS 7 | class HubWS { 8 | public: 9 | }; 10 | #else 11 | 12 | #include 13 | #include 14 | 15 | #include "../utils/stats.h" 16 | 17 | class HubWS { 18 | // ============ PROTECTED ============= 19 | protected: 20 | HubWS() : server(GH_WS_PORT), ws("/") { 21 | server.addHandler(&ws); 22 | } 23 | 24 | virtual void parse(char* url, GHconn_t conn, bool manual) = 0; 25 | virtual void sendEvent(GHevent_t state, GHconn_t conn) = 0; 26 | 27 | void beginWS() { 28 | ws.onEvent([this](GH_UNUSED AsyncWebSocket* server, GH_UNUSED AsyncWebSocketClient* client, AwsEventType etype, void* arg, uint8_t* data, size_t len) { 29 | switch (etype) { 30 | case WS_EVT_CONNECT: 31 | sendEvent(GH_CONNECTED, GH_WS); 32 | break; 33 | 34 | case WS_EVT_DISCONNECT: 35 | sendEvent(GH_DISCONNECTED, GH_WS); 36 | break; 37 | 38 | case WS_EVT_ERROR: 39 | sendEvent(GH_ERROR, GH_WS); 40 | break; 41 | 42 | case WS_EVT_DATA: { 43 | AwsFrameInfo* ws_info = (AwsFrameInfo*)arg; 44 | if (ws_info->final && ws_info->index == 0 && ws_info->len == len && ws_info->opcode == WS_TEXT) { 45 | clientID = client->id(); 46 | parse((char*)data, GH_WS, false); 47 | } 48 | } break; 49 | 50 | case WS_EVT_PONG: 51 | break; 52 | } 53 | }); 54 | 55 | server.begin(); 56 | } 57 | 58 | void endWS() { 59 | server.end(); 60 | } 61 | 62 | void tickWS() { 63 | ws.cleanupClients(); 64 | } 65 | 66 | void sendWS(const String& answ) { 67 | ws.textAll(answ.c_str()); 68 | } 69 | 70 | void answerWS(String& answ) { 71 | ws.text(clientID, answ.c_str()); 72 | } 73 | 74 | // ============ PRIVATE ============= 75 | private: 76 | AsyncWebServer server; 77 | AsyncWebSocket ws; 78 | uint32_t clientID = 0; 79 | }; 80 | #endif 81 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define GH_VERSION "v0.1b" // версия библиотеки 4 | #define GH_CONN_TOUT 5 // таймаут соединения, с 5 | #define GH_HTTP_PORT 80 // http порт 6 | #define GH_WS_PORT 81 // websocket порт 7 | #define GH_HTTPD_PORT 82 // httpd порт (stream) 8 | #define GH_DOWN_CHUNK_SIZE 512 // размер чанка при скачивании с платы 9 | #define GH_UPL_CHUNK_SIZE 200 // размер чанка при загрузке на плату 10 | #define GH_FS_DEPTH 5 // глубина сканирования файловой системы (esp32) 11 | #define GH_FS LittleFS // файловая система 12 | #define GH_MQTT_RECONNECT 5000 // период переподключения MQTT 13 | #define GH_CACHE_PRD "max-age=604800" // период кеширования файлов для портала 14 | 15 | #if (defined(ESP8266) || defined(ESP32)) 16 | #define GH_ESP_BUILD 17 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/esp_inc/index.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define hub_index_h_len 375 3 | 4 | const uint8_t hub_index_h[] PROGMEM = { 5 | 0x1f, 0x8b, 0x08, 0x08, 0x1d, 0xb3, 0x94, 0x64, 0x02, 0xff, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 6 | 0x68, 0x74, 0x6d, 0x6c, 0x00, 0x7d, 0x92, 0x4d, 0x4f, 0xc3, 0x30, 0x0c, 0x86, 0xef, 0x48, 0xfc, 7 | 0x07, 0x93, 0x13, 0x48, 0x6c, 0xe5, 0x4b, 0x68, 0x87, 0x76, 0x08, 0x8d, 0x01, 0x37, 0x26, 0x31, 8 | 0x84, 0x38, 0xa1, 0x2c, 0x35, 0xd4, 0x23, 0x4d, 0xa6, 0xc4, 0xeb, 0x18, 0xbf, 0x9e, 0xa4, 0x29, 9 | 0x0c, 0x81, 0xd8, 0xc9, 0xaf, 0x9d, 0xc7, 0xaf, 0x6c, 0x2b, 0xf9, 0xde, 0xd5, 0xdd, 0x68, 0xfa, 10 | 0x34, 0x19, 0x43, 0xc5, 0xb5, 0x1e, 0xee, 0xee, 0xe4, 0x31, 0x82, 0x96, 0xe6, 0xb5, 0x10, 0x68, 11 | 0x44, 0x5b, 0x41, 0x59, 0x86, 0x08, 0x90, 0xd7, 0xc8, 0x12, 0x54, 0x25, 0x9d, 0x47, 0x2e, 0xc4, 12 | 0xc3, 0xf4, 0xba, 0x37, 0x10, 0xe9, 0x85, 0x89, 0x35, 0x0e, 0x6f, 0xd6, 0x0d, 0xba, 0xdb, 0xe5, 13 | 0x0c, 0x9a, 0xa3, 0xfe, 0xd9, 0xd1, 0x2c, 0xcf, 0x52, 0x79, 0xd3, 0x6b, 0x64, 0x8d, 0x85, 0x28, 14 | 0xd1, 0x2b, 0x47, 0x0b, 0x26, 0x6b, 0x04, 0x28, 0x6b, 0x18, 0x4d, 0xb0, 0xbb, 0x74, 0xe5, 0x92, 15 | 0x8c, 0xcd, 0xc6, 0xf7, 0x93, 0xc1, 0xc9, 0xf9, 0x79, 0x8c, 0xa7, 0x27, 0xf0, 0x88, 0x33, 0x18, 16 | 0x05, 0xc4, 0x59, 0x0d, 0x13, 0x69, 0x50, 0x8b, 0x3f, 0x76, 0x0d, 0xe1, 0x6a, 0x61, 0x1d, 0xff, 17 | 0xf0, 0x5a, 0x51, 0xc9, 0x55, 0x51, 0x62, 0x43, 0x0a, 0x7b, 0x6d, 0x72, 0x08, 0x64, 0x88, 0x49, 18 | 0xea, 0x9e, 0x57, 0x52, 0x63, 0x71, 0x7c, 0x08, 0xb5, 0x7c, 0xa7, 0x7a, 0x59, 0x7f, 0x15, 0x3a, 19 | 0xe3, 0x34, 0x1a, 0x78, 0xa7, 0x0a, 0x91, 0x74, 0x7f, 0xee, 0x2f, 0xda, 0x7d, 0x0a, 0x31, 0xcc, 20 | 0xb3, 0x54, 0x4b, 0xac, 0x26, 0xf3, 0x06, 0x95, 0xc3, 0x97, 0x80, 0xf2, 0x5a, 0x63, 0x5f, 0xf9, 21 | 0x6f, 0x14, 0x1c, 0xea, 0xae, 0xec, 0x2b, 0x44, 0x6e, 0x4f, 0x99, 0x75, 0xb7, 0xcc, 0x67, 0xb6, 22 | 0x5c, 0x83, 0x35, 0x0e, 0x3d, 0x7d, 0x84, 0x15, 0x52, 0x7c, 0xae, 0xf6, 0x0f, 0xba, 0x29, 0x4a, 23 | 0x6a, 0x80, 0xca, 0x42, 0x18, 0xcb, 0x61, 0x85, 0xb0, 0x99, 0x96, 0xde, 0x7f, 0xa7, 0x61, 0x8c, 24 | 0x00, 0x6c, 0xc8, 0xee, 0x35, 0x9a, 0x8b, 0xb6, 0x2d, 0xaa, 0xe7, 0x78, 0x8d, 0xff, 0x50, 0x46, 25 | 0xcf, 0x09, 0x8d, 0x6a, 0x2b, 0xba, 0x70, 0x76, 0x8e, 0x8a, 0x7d, 0xc2, 0xbf, 0xb2, 0xad, 0x2d, 26 | 0xb5, 0x24, 0x93, 0xf0, 0xa8, 0xb6, 0xa2, 0x4a, 0x53, 0x22, 0x83, 0xd8, 0x0a, 0xbe, 0x58, 0xcb, 27 | 0xe8, 0x12, 0x9b, 0xf4, 0x2f, 0x3c, 0xcf, 0xe2, 0x51, 0xd3, 0x95, 0xe3, 0x5f, 0xfe, 0x04, 0x03, 28 | 0xda, 0xe9, 0x79, 0xdb, 0x02, 0x00, 0x00, 29 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/macro.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define GH_UNUSED __attribute__((unused)) 4 | #define VSPTR const void* 5 | #define CSREF const String& 6 | #define GH_PGM(name, str) static const char name[] PROGMEM = str 7 | #define GH_PGM_LIST(name, ...) const char* const name[] PROGMEM = {__VA_ARGS__}; 8 | #define FSTR const __FlashStringHelper* 9 | #define GH_NO_LABEL F("_no") 10 | #define GH_NUMBERS F("^\\d+$") 11 | #define GH_LETTERS F("^[a-zA-Z]+$") 12 | #define GH_LETTERS_S F("^[a-z]+$") 13 | #define GH_LETTERS_C F("^[A-Z]+$") -------------------------------------------------------------------------------- /libraries/GyverHub/src/sync/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | #include "../macro.hpp" 4 | 5 | #ifdef GH_ESP_BUILD 6 | #ifdef GH_NO_WS 7 | class HubHTTP { 8 | public: 9 | }; 10 | #else 11 | 12 | #ifdef ESP8266 13 | #include 14 | #include 15 | #else 16 | #include 17 | #include 18 | #endif 19 | 20 | #ifndef GH_NO_FS 21 | #if (GH_FS == LittleFS) 22 | #include 23 | #elif (GH_FS == SPIFFS) 24 | #include 25 | #endif 26 | #endif 27 | 28 | #ifdef GH_INCLUDE_PORTAL 29 | #include "../esp_inc/index.h" 30 | #include "../esp_inc/script.h" 31 | #include "../esp_inc/style.h" 32 | #endif 33 | 34 | class HubHTTP { 35 | public: 36 | #ifdef ESP8266 37 | ESP8266WebServer server; 38 | #else 39 | WebServer server; 40 | #endif 41 | 42 | HubHTTP() : server(GH_HTTP_PORT) {} 43 | 44 | protected: 45 | void beginHTTP() { 46 | server.on("/hub_discover_all", [this]() { 47 | server.send(200, F("text/plain"), F("OK")); 48 | }); 49 | 50 | #ifndef GH_NO_PORTAL 51 | server.on("/favicon.svg", [this]() { 52 | server.send(200); 53 | }); 54 | 55 | #ifdef GH_INCLUDE_PORTAL 56 | server.on("/", [this]() { 57 | gzip_h(); 58 | cache_h(); 59 | server.send_P(200, "text/html", (PGM_P)hub_index_h, (size_t)hub_index_h_len); 60 | }); 61 | server.on("/script.js", [this]() { 62 | gzip_h(); 63 | cache_h(); 64 | server.send_P(200, "text/javascript", (PGM_P)hub_script_h, (size_t)hub_script_h_len); 65 | }); 66 | server.on("/style.css", [this]() { 67 | gzip_h(); 68 | cache_h(); 69 | server.send_P(200, "text/css", (PGM_P)hub_style_h, (size_t)hub_style_h_len); 70 | }); 71 | #else 72 | #ifndef GH_NO_FS 73 | server.on("/", [this]() { 74 | File f = GH_FS.open("/hub/index.html.gz", "r"); 75 | if (f) server.streamFile(f, "text/html"); 76 | }); 77 | server.on("/script.js", [this]() { 78 | cache_h(); 79 | File f = GH_FS.open("/hub/script.js.gz", "r"); 80 | if (f) server.streamFile(f, "text/javascript"); 81 | }); 82 | server.on("/style.css", [this]() { 83 | cache_h(); 84 | File f = GH_FS.open("/hub/style.css.gz", "r"); 85 | if (f) server.streamFile(f, "text/css"); 86 | }); 87 | #endif 88 | #endif 89 | #endif 90 | server.begin(GH_HTTP_PORT); 91 | server.enableCORS(true); 92 | } 93 | void endHTTP() { 94 | server.stop(); 95 | } 96 | void tickHTTP() { 97 | server.handleClient(); 98 | } 99 | 100 | private: 101 | void gzip_h() { 102 | server.sendHeader(F("Content-Encoding"), F("gzip")); 103 | } 104 | void cache_h() { 105 | server.sendHeader(F("Cache-Control"), GH_CACHE_PRD); 106 | } 107 | }; 108 | #endif 109 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/sync/ws.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | #include "../macro.hpp" 4 | 5 | #ifdef GH_ESP_BUILD 6 | #ifdef GH_NO_WS 7 | class HubWS { 8 | public: 9 | }; 10 | #else 11 | 12 | #include 13 | #include 14 | 15 | #include "../utils/stats.h" 16 | 17 | class HubWS { 18 | // ============ PROTECTED ============= 19 | protected: 20 | HubWS() : ws(GH_WS_PORT, "", "hub") {} 21 | 22 | virtual void parse(char* url, GHconn_t conn, bool manual) = 0; 23 | virtual void sendEvent(GHevent_t state, GHconn_t conn) = 0; 24 | 25 | void beginWS() { 26 | ws.onEvent([this](uint8_t num, WStype_t type, uint8_t* data, GH_UNUSED size_t len) { 27 | switch (type) { 28 | case WStype_CONNECTED: 29 | sendEvent(GH_CONNECTED, GH_WS); 30 | break; 31 | 32 | case WStype_DISCONNECTED: 33 | sendEvent(GH_DISCONNECTED, GH_WS); 34 | break; 35 | 36 | case WStype_ERROR: 37 | sendEvent(GH_ERROR, GH_WS); 38 | break; 39 | 40 | case WStype_TEXT: { 41 | clientID = num; 42 | /*char data_c[len + 1]; 43 | if (len) strcpy(data_c, (char*)data); 44 | data_c[len] = 0;*/ 45 | parse((char*)data, GH_WS, false); 46 | } break; 47 | 48 | case WStype_BIN: 49 | case WStype_FRAGMENT_TEXT_START: 50 | case WStype_FRAGMENT_BIN_START: 51 | case WStype_FRAGMENT: 52 | case WStype_FRAGMENT_FIN: 53 | case WStype_PING: 54 | case WStype_PONG: 55 | break; 56 | } 57 | }); 58 | 59 | ws.begin(); 60 | } 61 | 62 | void endWS() { 63 | ws.close(); 64 | } 65 | 66 | void tickWS() { 67 | ws.loop(); 68 | } 69 | 70 | void sendWS(const String& answ) { 71 | ws.broadcastTXT(answ.c_str(), answ.length()); 72 | } 73 | 74 | void answerWS(const String& answ) { 75 | ws.sendTXT(clientID, answ.c_str(), answ.length()); 76 | } 77 | 78 | // ============ PRIVATE ============= 79 | private: 80 | WebSocketsServer ws; 81 | uint8_t clientID = 0; 82 | }; 83 | #endif 84 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/action.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | struct GHaction { 6 | // имя компонента 7 | const char* name = nullptr; 8 | 9 | // значение компонента 10 | const char* value = nullptr; 11 | 12 | // получить значение как int (32 бит) 13 | int32_t valueInt() const { 14 | return atol(value); 15 | } 16 | 17 | // получить значение как float 18 | float valueFloat() const { 19 | return atof(value); 20 | } 21 | 22 | // получить значение как String 23 | String valueString() const { 24 | return value; 25 | } 26 | 27 | // получить имя как String 28 | String nameString() const { 29 | return name; 30 | } 31 | 32 | bool flag = 0; 33 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/b64.cpp: -------------------------------------------------------------------------------- 1 | #include "b64.h" 2 | 3 | static const char _b64chars[] PROGMEM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 4 | 5 | static const uint8_t _b64index[] PROGMEM = { 6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 9 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 10 | 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 11 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 12 | 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 13 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; 14 | 15 | char GH_b64v(uint8_t n) { 16 | return pgm_read_byte(_b64chars + n); 17 | } 18 | uint8_t GH_b64i(char b) { 19 | return pgm_read_byte(_b64index + b); 20 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/b64.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | char GH_b64v(uint8_t n); 5 | uint8_t GH_b64i(char b); -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/build.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../config.hpp" 5 | #include "../macro.hpp" 6 | #include "action.h" 7 | #include "datatypes.h" 8 | #include "hub.h" 9 | #include "stats.h" 10 | 11 | // тип билда 12 | enum GHbuild_t { 13 | GH_BUILD_NONE, 14 | GH_BUILD_ACTION, 15 | GH_BUILD_COUNT, 16 | GH_BUILD_READ, 17 | GH_BUILD_UI, 18 | GH_BUILD_TG, 19 | }; 20 | 21 | class GHbuild { 22 | public: 23 | GHbuild(GHbuild_t btype = GH_BUILD_NONE, bool act = 0, const char* name = nullptr, const char* value = nullptr, GHhub nhub = GHhub()) { 24 | type = btype; 25 | action.flag = act; 26 | action.name = name; 27 | action.value = value; 28 | hub = nhub; 29 | } 30 | 31 | bool nameEq(VSPTR name, bool fstr) { 32 | if (name) return fstr ? !strcmp_P(action.name, (PGM_P)name) : !strcmp(action.name, (PGM_P)name); 33 | else return autoNameEq(); 34 | } 35 | 36 | bool parse(VSPTR name, void* var, GHdata_t type, bool fstr) { 37 | if (action.flag && nameEq(name, fstr)) { 38 | action.flag = 0; 39 | GHtypeFromStr(action.value, var, type); 40 | return 1; 41 | } 42 | return 0; 43 | } 44 | 45 | bool autoNameEq() { 46 | return action.name[0] == '_' && action.name[1] == 'n' && atoi(action.name + 2) == count; 47 | } 48 | 49 | // тип билда 50 | GHbuild_t type = GH_BUILD_NONE; 51 | 52 | // данные клиента 53 | GHhub hub; 54 | 55 | // действие 56 | GHaction action; 57 | 58 | // private 59 | uint16_t count = 0; 60 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/button.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class GHbutton { 5 | public: 6 | bool state = 0; 7 | 8 | bool changed() { 9 | return _changed ? (_changed = 0, 1) : 0; 10 | } 11 | 12 | operator bool() { 13 | return state; 14 | } 15 | 16 | bool _changed = 0; 17 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/cmd_p.cpp: -------------------------------------------------------------------------------- 1 | #include "cmd_p.h" 2 | 3 | // ======================== CMD ======================== 4 | GH_PGM(_GH_CMD0, "focus"); 5 | GH_PGM(_GH_CMD1, "ping"); 6 | GH_PGM(_GH_CMD2, "unfocus"); 7 | GH_PGM(_GH_CMD3, "info"); 8 | #ifdef GH_ESP_BUILD 9 | GH_PGM(_GH_CMD4, "fsbr"); 10 | GH_PGM(_GH_CMD5, "format"); 11 | GH_PGM(_GH_CMD6, "reboot"); 12 | GH_PGM(_GH_CMD7, "fetch_chunk"); 13 | #endif 14 | 15 | #ifdef GH_ESP_BUILD 16 | #define GH_CMD_LEN 8 17 | GH_PGM_LIST(_GH_cmd_list, _GH_CMD0, _GH_CMD1, _GH_CMD2, _GH_CMD3, _GH_CMD4, _GH_CMD5, _GH_CMD6, _GH_CMD7); 18 | #else 19 | #define GH_CMD_LEN 4 20 | GH_PGM_LIST(_GH_cmd_list, _GH_CMD0, _GH_CMD1, _GH_CMD2, _GH_CMD3); 21 | #endif 22 | 23 | int GH_getCmd(char* str) { 24 | for (int i = 0; i < GH_CMD_LEN; i++) { 25 | if (!strcmp_P(str, _GH_cmd_list[i])) return i; 26 | } 27 | return -1; 28 | } 29 | 30 | // ===================== CMD NAME ==================== 31 | GH_PGM(_GH_CMDN0, "set"); 32 | GH_PGM(_GH_CMDN1, "cli"); 33 | #ifdef GH_ESP_BUILD 34 | GH_PGM(_GH_CMDN2, "delete"); 35 | GH_PGM(_GH_CMDN3, "rename"); 36 | GH_PGM(_GH_CMDN4, "fetch"); 37 | GH_PGM(_GH_CMDN5, "upload"); 38 | GH_PGM(_GH_CMDN6, "upload_chunk"); 39 | GH_PGM(_GH_CMDN7, "ota"); 40 | GH_PGM(_GH_CMDN8, "ota_chunk"); 41 | GH_PGM(_GH_CMDN9, "ota_url"); 42 | #endif 43 | 44 | #ifdef GH_ESP_BUILD 45 | #define GH_CMDN_LEN 10 46 | GH_PGM_LIST(_GH_cmdN_list, _GH_CMDN0, _GH_CMDN1, _GH_CMDN2, _GH_CMDN3, _GH_CMDN4, _GH_CMDN5, _GH_CMDN6, _GH_CMDN7, _GH_CMDN8, _GH_CMDN9); 47 | #else 48 | #define GH_CMDN_LEN 2 49 | GH_PGM_LIST(_GH_cmdN_list, _GH_CMDN0, _GH_CMDN1); 50 | #endif 51 | 52 | int GH_getCmdN(char* str) { 53 | for (int i = 0; i < GH_CMDN_LEN; i++) { 54 | if (!strcmp_P(str, _GH_cmdN_list[i])) return i; 55 | } 56 | return -1; 57 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/cmd_p.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../config.hpp" 4 | #include "../macro.hpp" 5 | 6 | int GH_getCmd(char* str); 7 | int GH_getCmdN(char* str); -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // ==================== COLORS ===================== 5 | enum GHcolors { 6 | GH_RED = 0xcb2839, 7 | GH_ORANGE = 0xd55f30, 8 | GH_YELLOW = 0xd69d27, 9 | GH_GREEN = 0x37A93C, 10 | GH_MINT = 0x25b18f, 11 | GH_AQUA = 0x2ba1cd, 12 | GH_BLUE = 0x297bcd, 13 | GH_VIOLET = 0x825ae7, 14 | GH_PINK = 0xc8589a, 15 | GH_DEFAULT = 0xffffffff, 16 | }; 17 | 18 | // ====================== COLOR ======================= 19 | struct GHcolor { 20 | uint8_t r = 0, g = 0, b = 0; 21 | 22 | GHcolor() {} 23 | GHcolor(const GHcolor& col) = default; 24 | GHcolor(uint8_t gray) { 25 | setGray(gray); 26 | } 27 | GHcolor(uint32_t hex, bool f) { 28 | if (f) setHEX(hex); 29 | } 30 | GHcolor(uint8_t v1, uint8_t v2, uint8_t v3, bool hsv = 0) { 31 | if (hsv) setHSV(v1, v2, v3); 32 | else setRGB(v1, v2, v3); 33 | } 34 | 35 | void setRGB(uint8_t nr, uint8_t ng, uint8_t nb) { 36 | r = nr; 37 | g = ng; 38 | b = nb; 39 | } 40 | void setGray(uint8_t gray) { 41 | setRGB(gray, gray, gray); 42 | } 43 | void setHEX(uint32_t hex) { 44 | r = ((uint8_t*)&hex)[2]; 45 | g = ((uint8_t*)&hex)[1]; 46 | b = ((uint8_t*)&hex)[0]; 47 | } 48 | void setHSV(uint8_t h, uint8_t s, uint8_t v) { 49 | float R, G, B; 50 | 51 | float H = h / 255.0; 52 | float S = s / 255.0; 53 | float V = v / 255.0; 54 | 55 | uint8_t i = H * 6; 56 | float f = H * 6 - i; 57 | float p = V * (1 - S); 58 | float q = V * (1 - f * S); 59 | float t = V * (1 - (1 - f) * S); 60 | 61 | switch (i) { 62 | case 0: 63 | R = V, G = t, B = p; 64 | break; 65 | case 1: 66 | R = q, G = V, B = p; 67 | break; 68 | case 2: 69 | R = p, G = V, B = t; 70 | break; 71 | case 3: 72 | R = p, G = q, B = V; 73 | break; 74 | case 4: 75 | R = t, G = p, B = V; 76 | break; 77 | case 5: 78 | R = V, G = p, B = q; 79 | break; 80 | } 81 | r = R * 255; 82 | g = G * 255; 83 | b = B * 255; 84 | } 85 | void setHue(uint8_t color) { 86 | uint8_t shift; 87 | if (color > 170) { 88 | shift = (color - 170) * 3; 89 | r = shift; 90 | g = 0; 91 | b = 255 - shift; 92 | } else if (color > 85) { 93 | shift = (color - 85) * 3; 94 | r = 0; 95 | g = 255 - shift; 96 | b = shift; 97 | } else { 98 | shift = color * 3; 99 | r = 255 - shift; 100 | g = shift; 101 | b = 0; 102 | } 103 | } 104 | 105 | uint32_t getHEX() { 106 | uint32_t hex = 0; 107 | ((uint8_t*)&hex)[2] = r; 108 | ((uint8_t*)&hex)[1] = g; 109 | ((uint8_t*)&hex)[0] = b; 110 | return hex; 111 | } 112 | operator uint32_t() { 113 | return getHEX(); 114 | } 115 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/datatypes.cpp: -------------------------------------------------------------------------------- 1 | #include "datatypes.h" 2 | 3 | void GHtypeFromStr(const char* str, void* var, GHdata_t type) { 4 | if (!var) return; 5 | switch (type) { 6 | case GH_STR: 7 | *(String*)var = str; 8 | break; 9 | case GH_CSTR: 10 | strcpy((char*)var, str); 11 | break; 12 | 13 | case GH_BOOL: 14 | *(bool*)var = (str[0] == '1'); 15 | break; 16 | 17 | case GH_INT8: 18 | *(int8_t*)var = atoi(str); 19 | break; 20 | 21 | case GH_UINT8: 22 | *(uint8_t*)var = atoi(str); 23 | break; 24 | 25 | case GH_INT16: 26 | *(int16_t*)var = atoi(str); 27 | break; 28 | case GH_UINT16: 29 | *(uint16_t*)var = atoi(str); 30 | break; 31 | 32 | case GH_INT32: 33 | *(int32_t*)var = atol(str); 34 | break; 35 | case GH_UINT32: 36 | *(uint32_t*)var = atol(str); 37 | break; 38 | 39 | case GH_FLOAT: 40 | *(float*)var = atof(str); 41 | break; 42 | case GH_DOUBLE: 43 | *(double*)var = atof(str); 44 | break; 45 | 46 | case GH_COLOR: 47 | ((GHcolor*)var)->setHEX(atol(str)); 48 | break; 49 | case GH_FLAGS: 50 | ((GHflags*)var)->flags = atoi(str); 51 | break; 52 | case GH_POS: { 53 | uint32_t xy = atol(str); 54 | ((GHpos*)var)->_changed = true; 55 | ((GHpos*)var)->x = xy >> 16; 56 | ((GHpos*)var)->y = xy & 0xffff; 57 | } break; 58 | 59 | case GH_NULL: 60 | break; 61 | } 62 | } 63 | 64 | void GHtypeToStr(String* s, void* var, GHdata_t type) { 65 | if (!var) { 66 | *s += '0'; 67 | return; 68 | } 69 | switch (type) { 70 | case GH_STR: 71 | *s += *(String*)var; 72 | break; 73 | case GH_CSTR: 74 | *s += (char*)var; 75 | break; 76 | 77 | case GH_BOOL: 78 | *s += *(bool*)var; 79 | break; 80 | 81 | case GH_INT8: 82 | *s += *(int8_t*)var; 83 | break; 84 | 85 | case GH_UINT8: 86 | *s += *(uint8_t*)var; 87 | break; 88 | 89 | case GH_INT16: 90 | *s += *(int16_t*)var; 91 | break; 92 | case GH_UINT16: 93 | *s += *(uint16_t*)var; 94 | break; 95 | 96 | case GH_INT32: 97 | *s += *(int32_t*)var; 98 | break; 99 | case GH_UINT32: 100 | *s += *(uint32_t*)var; 101 | break; 102 | 103 | case GH_FLOAT: 104 | *s += *(float*)var; 105 | break; 106 | case GH_DOUBLE: 107 | *s += *(double*)var; 108 | break; 109 | 110 | case GH_COLOR: 111 | *s += ((GHcolor*)var)->getHEX(); 112 | break; 113 | case GH_FLAGS: 114 | *s += ((GHflags*)var)->flags; 115 | break; 116 | case GH_POS: 117 | break; 118 | 119 | case GH_NULL: 120 | *s += '0'; 121 | break; 122 | } 123 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/datatypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../config.hpp" 5 | #include "../macro.hpp" 6 | #include "color.h" 7 | #include "flags.h" 8 | #include "pos.h" 9 | 10 | enum GHdata_t { 11 | GH_NULL, 12 | 13 | GH_STR, 14 | GH_CSTR, 15 | 16 | GH_BOOL, 17 | GH_INT8, 18 | GH_UINT8, 19 | GH_INT16, 20 | GH_UINT16, 21 | GH_INT32, 22 | GH_UINT32, 23 | 24 | GH_FLOAT, 25 | GH_DOUBLE, 26 | 27 | GH_COLOR, 28 | GH_FLAGS, 29 | GH_POS, 30 | }; 31 | 32 | void GHtypeToStr(String* s, void* val, GHdata_t type); 33 | void GHtypeFromStr(const char* s, void* val, GHdata_t type); -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/flags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct GHflags { 5 | uint16_t flags = 0; 6 | 7 | GHflags() {} 8 | GHflags(const GHflags& f) = default; 9 | GHflags(uint16_t nflags) { 10 | flags = nflags; 11 | } 12 | 13 | void set(uint8_t idx, uint8_t val) { 14 | if (idx < 16) bitWrite(flags, idx, val); 15 | } 16 | uint8_t get(uint8_t idx) { 17 | if (idx < 16) return bitRead(flags, idx); 18 | else return 0; 19 | } 20 | 21 | String toString() { 22 | String s; 23 | s.reserve(16); 24 | for (int i = 0; i < 16; i++) s += get(i); 25 | return s; 26 | } 27 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/hub.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "stats.h" 5 | 6 | struct GHhub { 7 | GHhub() {} 8 | GHhub(GHconn_t nconn, const char* nid, bool nmanual) { 9 | conn = nconn; 10 | if (strlen(nid) <= 8) strcpy(id, nid); 11 | manual = nmanual; 12 | } 13 | 14 | // тип соединения 15 | GHconn_t conn = GH_SYSTEM; 16 | 17 | // id клиента 18 | char id[9] = {'\0'}; 19 | 20 | // из ручного парсера 21 | bool manual = false; 22 | 23 | bool eq(GHhub& hub) { 24 | return (hub.conn == conn && !strcmp(hub.id, id)); 25 | } 26 | bool operator==(GHhub& hub) { 27 | return eq(hub); 28 | } 29 | bool operator!=(GHhub& hub) { 30 | return !eq(hub); 31 | } 32 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "misc.h" 5 | 6 | class GHlog : public Print { 7 | public: 8 | 9 | // начать и указать размер буфера 10 | void begin(int n = 64) { 11 | end(); 12 | len = head = 0; 13 | size = n; 14 | buffer = new char[size]; 15 | } 16 | 17 | ~GHlog() { 18 | end(); 19 | } 20 | 21 | // остановить 22 | void end() { 23 | if (buffer) { 24 | delete[] buffer; 25 | buffer = nullptr; 26 | } 27 | } 28 | 29 | virtual size_t write(uint8_t n) { 30 | if (buffer) _write(n); 31 | return 1; 32 | } 33 | 34 | // прочитать в строку 35 | void read(String* s) { 36 | if (!buffer) return; 37 | bool start = 0; 38 | for (uint16_t i = 0; i < len; i++) { 39 | char c = _read(i); 40 | if (start && c != '\r') GH_escapeChar(s, c); 41 | else if (c == '\n') start = 1; 42 | } 43 | } 44 | 45 | // прочитать строкой 46 | String read() { 47 | String s; 48 | s.reserve(len); 49 | read(&s); 50 | return s; 51 | } 52 | 53 | // очистить 54 | void clear() { 55 | len = head = 0; 56 | } 57 | 58 | // есть данные 59 | bool available() { 60 | return (buffer && len); 61 | } 62 | 63 | // запущен 64 | bool state() { 65 | return buffer; 66 | } 67 | 68 | // длина 69 | int length() { 70 | return len; 71 | } 72 | 73 | char* buffer = nullptr; 74 | 75 | private: 76 | void _write(uint8_t n) { 77 | if (len < size) len++; 78 | buffer[head] = n; 79 | if (++head >= size) head = 0; 80 | } 81 | char _read(int num) { 82 | return buffer[(len < size) ? num : ((head + num) % size)]; 83 | } 84 | 85 | uint16_t size = 0; 86 | uint16_t len = 0; 87 | uint16_t head = 0; 88 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/misc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../config.hpp" 5 | #include "../macro.hpp" 6 | #include "utils/b64.h" 7 | 8 | #ifdef GH_ESP_BUILD 9 | #ifndef GH_NO_FS 10 | #include 11 | #if (GH_FS == LittleFS) 12 | #include 13 | #elif (GH_FS == SPIFFS) 14 | #include 15 | #endif 16 | #endif 17 | 18 | #ifdef ESP8266 19 | #else 20 | #ifndef GH_NO_OTA 21 | #include 22 | #endif 23 | #endif 24 | #endif 25 | 26 | extern String _GH_empty_str; 27 | 28 | template 29 | struct GHparser { 30 | GHparser(char* url) { 31 | int16_t len = strlen(url); 32 | for (uint8_t i = 0; i < SIZE; i++) { 33 | char* div = (char*)memchr(url, '/', len); 34 | str[i] = url; 35 | size++; 36 | if (div && i < SIZE - 1) { 37 | uint8_t divlen = div - url; 38 | len -= divlen + 1; 39 | url += divlen + 1; 40 | *div = 0; 41 | } else break; 42 | } 43 | } 44 | ~GHparser() { 45 | for (int i = 1; i < size; i++) { 46 | *(str[i] - 1) = '/'; 47 | } 48 | } 49 | 50 | char* str[SIZE] = {}; 51 | uint8_t size = 0; 52 | }; 53 | 54 | char* GH_splitter(char* list, char div = ','); 55 | String GH_uptime(); 56 | void GH_escapeChar(String* s, char c); 57 | void GH_escapeStr(String* s, VSPTR v, bool fstr); 58 | 59 | #ifdef GH_ESP_BUILD 60 | #ifndef GH_NO_FS 61 | void GH_showFiles(String& answ, const String& path, GH_UNUSED uint8_t levels = 0, uint16_t* count = nullptr); 62 | void GH_fileToB64(File& file, String& str); 63 | void GH_B64toFile(File& file, const char* str); 64 | #endif 65 | #ifndef GH_NO_OTA 66 | void GH_B64toUpdate(const char* str); 67 | #endif 68 | #endif -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/modules.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "../config.hpp" 5 | 6 | enum GHmodule_t { 7 | GH_MOD_INFO = (1ul << 0), 8 | GH_MOD_FSBR = (1ul << 1), 9 | GH_MOD_FORMAT = (1ul << 2), 10 | GH_MOD_DOWNLOAD = (1ul << 3), 11 | GH_MOD_UPLOAD = (1ul << 4), 12 | GH_MOD_OTA = (1ul << 5), 13 | GH_MOD_OTA_URL = (1ul << 6), 14 | GH_MOD_REBOOT = (1ul << 7), 15 | GH_MOD_SET = (1ul << 8), 16 | GH_MOD_READ = (1ul << 9), 17 | GH_MOD_DELETE = (1ul << 10), 18 | GH_MOD_RENAME = (1ul << 11), 19 | 20 | GH_MOD_SERIAL = (1ul << 12), 21 | GH_MOD_BT = (1ul << 13), 22 | GH_MOD_WS = (1ul << 14), 23 | GH_MOD_MQTT = (1ul << 15), 24 | }; 25 | 26 | struct GHmodule { 27 | uint32_t mods = 0xffffffff; 28 | 29 | void set(uint32_t nmods) { 30 | mods |= nmods; 31 | } 32 | void unset(uint32_t nmods) { 33 | mods &= ~nmods; 34 | } 35 | 36 | void setAll() { 37 | mods = 0xffff; 38 | } 39 | void unsetAll() { 40 | mods = 0; 41 | } 42 | bool read(GHmodule_t m) { 43 | return mods & m; 44 | } 45 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/pos.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pos_geo.h" 4 | 5 | class GHpos { 6 | public: 7 | GHpos() {} 8 | GHpos(int16_t nx, int16_t ny) : x(nx), y(ny) {} 9 | 10 | bool changed() { 11 | return _changed ? (_changed = 0, 1) : 0; 12 | } 13 | 14 | // расстояние до точки 15 | int16_t dist(int16_t x1, int16_t y1) { 16 | return GHdist(x, y, x1, y1); 17 | } 18 | 19 | // точка лежит внутри прямоугольника 20 | bool inRect(int16_t rx, int16_t ry, int16_t w, int16_t h) { 21 | return GHinRect(x, y, rx, ry, w, h); 22 | } 23 | 24 | // точка лежит внутри окружности 25 | bool inCircle(int16_t cx, int16_t cy, int16_t r) { 26 | return GHinCircle(x, y, cx, cy, r); 27 | } 28 | 29 | // координаты 30 | int16_t x = 0; 31 | int16_t y = 0; 32 | 33 | bool _changed = 0; 34 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/pos_geo.cpp: -------------------------------------------------------------------------------- 1 | #include "pos_geo.h" 2 | 3 | int16_t GHdist(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { 4 | x1 -= x0; 5 | y1 -= y0; 6 | return sqrt(x1 * x1 + y1 * y1); 7 | } 8 | 9 | bool GHinRect(int16_t x, int16_t y, int16_t rx, int16_t ry, int16_t w, int16_t h) { 10 | return (x > rx) && (x < rx + w) && (y > ry) && (y < ry + h); 11 | } 12 | 13 | bool GHinCircle(int16_t x, int16_t y, int16_t cx, int16_t cy, int16_t r) { 14 | return GHdist(x, y, cx, cy) < r; 15 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/pos_geo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // расстояние между двумя точками 5 | int16_t GHdist(int16_t x0, int16_t y0, int16_t x1, int16_t y1); 6 | 7 | // точка лежит внутри прямоугольника (координаты угла и размеры) 8 | bool GHinRect(int16_t x, int16_t y, int16_t rx, int16_t ry, int16_t w, int16_t h); 9 | 10 | // точка лежит внутри окружности (координаты центра и радиус) 11 | bool GHinCircle(int16_t x, int16_t y, int16_t cx, int16_t cy, int16_t r); -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/stats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../config.hpp" 3 | 4 | // причина перезагрузки 5 | enum GHreason_t { 6 | GH_REB_NONE, 7 | GH_REB_BUTTON, 8 | GH_REB_OTA, 9 | GH_REB_OTA_URL, 10 | }; 11 | 12 | // тип подключения 13 | enum GHconn_t { 14 | GH_SERIAL, 15 | GH_BT, 16 | GH_WS, 17 | GH_MQTT, 18 | GH_SYSTEM, 19 | }; 20 | 21 | #define GH_CONN_AMOUNT 4 22 | 23 | // системные события 24 | enum GHevent_t { 25 | GH_IDLE, 26 | GH_START, 27 | GH_STOP, 28 | 29 | GH_CONNECTING, 30 | GH_CONNECTED, 31 | GH_DISCONNECTED, 32 | GH_ERROR, 33 | 34 | GH_UNKNOWN, 35 | GH_DISCOVER_ALL, 36 | GH_DISCOVER, 37 | GH_FOCUS, 38 | GH_UNFOCUS, 39 | 40 | GH_SET, 41 | GH_CLI, 42 | GH_PING, 43 | 44 | GH_READ_HOOK, 45 | GH_SET_HOOK, 46 | GH_INFO, 47 | GH_REBOOT, 48 | GH_FSBR, 49 | GH_FORMAT, 50 | GH_DELETE, 51 | GH_RENAME, 52 | 53 | GH_DOWNLOAD, 54 | GH_DOWNLOAD_CHUNK, 55 | GH_DOWNLOAD_ERROR, 56 | GH_DOWNLOAD_ABORTED, 57 | GH_DOWNLOAD_FINISH, 58 | 59 | GH_UPLOAD, 60 | GH_UPLOAD_CHUNK, 61 | GH_UPLOAD_ERROR, 62 | GH_UPLOAD_ABORTED, 63 | GH_UPLOAD_FINISH, 64 | 65 | GH_OTA, 66 | GH_OTA_CHUNK, 67 | GH_OTA_ERROR, 68 | GH_OTA_ABORTED, 69 | GH_OTA_FINISH, 70 | 71 | GH_OTA_URL, 72 | }; -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/stats_p.cpp: -------------------------------------------------------------------------------- 1 | #include "stats_p.h" 2 | 3 | GH_PGM(_GH_RES0, "NONE"); 4 | GH_PGM(_GH_RES1, "BUTTON"); 5 | GH_PGM(_GH_RES2, "OTA"); 6 | GH_PGM(_GH_RES3, "OTA_URL"); 7 | GH_PGM_LIST(_GH_res_list, _GH_RES0, _GH_RES1, _GH_RES2, _GH_RES3); 8 | FSTR GHreadReason(GHreason_t n) { 9 | return (FSTR)_GH_res_list[n]; 10 | } 11 | 12 | GH_PGM(_GH_BLD0, "NONE"); 13 | GH_PGM(_GH_BLD1, "ACTION"); 14 | GH_PGM(_GH_BLD2, "COUNT"); 15 | GH_PGM(_GH_BLD3, "READ"); 16 | GH_PGM(_GH_BLD4, "UI"); 17 | GH_PGM(_GH_BLD5, "TG"); 18 | GH_PGM_LIST(_GH_bld_list, _GH_BLD0, _GH_BLD1, _GH_BLD2, _GH_BLD3, _GH_BLD4, _GH_BLD5); 19 | FSTR GHreadBuild(GHbuild_t n) { 20 | return (FSTR)_GH_bld_list[n]; 21 | } 22 | 23 | GH_PGM(_GH_CON0, "SERIAL"); 24 | GH_PGM(_GH_CON1, "BT"); 25 | GH_PGM(_GH_CON2, "WS"); 26 | GH_PGM(_GH_CON3, "MQTT"); 27 | GH_PGM(_GH_CON4, "SYSTEM"); 28 | GH_PGM_LIST(_GH_con_list, _GH_CON0, _GH_CON1, _GH_CON2, _GH_CON3, _GH_CON4); 29 | FSTR GHreadConn(GHconn_t n) { 30 | return (FSTR)_GH_con_list[n]; 31 | } 32 | 33 | GH_PGM(_GH_STA0, "IDLE"); 34 | GH_PGM(_GH_STA1, "START"); 35 | GH_PGM(_GH_STA2, "STOP"); 36 | GH_PGM(_GH_STA3, "CONNECTING"); 37 | GH_PGM(_GH_STA4, "CONNECTED"); 38 | GH_PGM(_GH_STA5, "DISCONNECTED"); 39 | GH_PGM(_GH_STA6, "ERROR"); 40 | GH_PGM(_GH_STA7, "UNKNOWN"); 41 | GH_PGM(_GH_STA8, "DISCOVER_ALL"); 42 | GH_PGM(_GH_STA9, "DISCOVER"); 43 | GH_PGM(_GH_STA10, "FOCUS"); 44 | GH_PGM(_GH_STA11, "UNFOCUS"); 45 | GH_PGM(_GH_STA12, "SET"); 46 | GH_PGM(_GH_STA13, "CLI"); 47 | GH_PGM(_GH_STA14, "PING"); 48 | GH_PGM(_GH_STA15, "READ_HOOK"); 49 | GH_PGM(_GH_STA16, "SET_HOOK"); 50 | GH_PGM(_GH_STA17, "INFO"); 51 | GH_PGM(_GH_STA18, "REBOOT"); 52 | GH_PGM(_GH_STA19, "FSBR"); 53 | GH_PGM(_GH_STA20, "FORMAT"); 54 | GH_PGM(_GH_STA21, "DELETE"); 55 | GH_PGM(_GH_STA22, "RENAME"); 56 | GH_PGM(_GH_STA23, "DOWNLOAD"); 57 | GH_PGM(_GH_STA24, "DOWNLOAD_CHUNK"); 58 | GH_PGM(_GH_STA25, "DOWNLOAD_ERROR"); 59 | GH_PGM(_GH_STA26, "DOWNLOAD_ABORTED"); 60 | GH_PGM(_GH_STA27, "DOWNLOAD_FINISH"); 61 | GH_PGM(_GH_STA28, "UPLOAD"); 62 | GH_PGM(_GH_STA29, "UPLOAD_CHUNK"); 63 | GH_PGM(_GH_STA30, "UPLOAD_ERROR"); 64 | GH_PGM(_GH_STA31, "UPLOAD_ABORTED"); 65 | GH_PGM(_GH_STA32, "UPLOAD_FINISH"); 66 | GH_PGM(_GH_STA33, "OTA"); 67 | GH_PGM(_GH_STA34, "OTA_CHUNK"); 68 | GH_PGM(_GH_STA35, "OTA_ERROR"); 69 | GH_PGM(_GH_STA36, "OTA_ABORTED"); 70 | GH_PGM(_GH_STA37, "OTA_FINISH"); 71 | GH_PGM(_GH_STA38, "OTA_URL"); 72 | GH_PGM_LIST(_GH_sta_list, _GH_STA0, _GH_STA1, _GH_STA2, _GH_STA3, _GH_STA4, _GH_STA5, _GH_STA6, _GH_STA7, _GH_STA8, _GH_STA9, _GH_STA10, _GH_STA11, _GH_STA12, _GH_STA13, _GH_STA14, _GH_STA15, _GH_STA16, _GH_STA17, _GH_STA18, _GH_STA19, _GH_STA20, _GH_STA21, _GH_STA22, _GH_STA23, _GH_STA24, _GH_STA25, _GH_STA26, _GH_STA27, _GH_STA28, _GH_STA29, _GH_STA30, _GH_STA31, _GH_STA32, _GH_STA33, _GH_STA34, _GH_STA35, _GH_STA36, _GH_STA37, _GH_STA38); 73 | FSTR GHreadEvent(GHevent_t n) { 74 | return (FSTR)_GH_sta_list[n]; 75 | } -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/stats_p.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../config.hpp" 4 | #include "../macro.hpp" 5 | #include "stats.h" 6 | #include "action.h" 7 | #include "build.h" 8 | 9 | // получить текстовое значение типа GHevent_t для вывода в порт 10 | FSTR GHreadEvent(GHevent_t n); 11 | 12 | // получить текстовое значение типа GHconn_t для вывода в порт 13 | FSTR GHreadConn(GHconn_t n); 14 | 15 | // получить текстовое значение типа GHbuild_t для вывода в порт 16 | FSTR GHreadBuild(GHbuild_t n); 17 | 18 | // получить текстовое значение типа GHreason_t для вывода в порт 19 | FSTR GHreadReason(GHreason_t n); -------------------------------------------------------------------------------- /libraries/GyverHub/src/utils/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // ====================== TIMER ======================= 5 | struct GHtimer { 6 | GHtimer() {} 7 | GHtimer(uint32_t ms, uint8_t seconds = 0, uint8_t minutes = 0, uint8_t hours = 0, uint8_t days = 0) { 8 | start(ms, seconds, minutes, hours, days); 9 | } 10 | 11 | void start(uint32_t ms, uint8_t seconds = 0, uint8_t minutes = 0, uint8_t hours = 0, uint8_t days = 0) { 12 | prd = days * 86400ul + hours * 3600ul + minutes * 60 + seconds; 13 | prd *= 1000ul; 14 | prd += ms; 15 | if (prd) start(); 16 | } 17 | void start() { 18 | if (!prd) return; 19 | tmr = millis(); 20 | if (!tmr) tmr = 1; 21 | } 22 | void stop() { 23 | tmr = 0; 24 | } 25 | bool ready() { 26 | return (tmr && millis() - tmr >= prd) ? (start(), true) : false; 27 | } 28 | operator bool() { 29 | return ready(); 30 | } 31 | 32 | uint32_t tmr = 0, prd = 0; 33 | }; 34 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | AccessModifierOffset: '-2' 4 | AlignAfterOpenBracket: DontAlign 5 | AlignConsecutiveAssignments: 'true' 6 | AlignConsecutiveDeclarations: 'false' 7 | AlignEscapedNewlines: Left 8 | AlignTrailingComments: 'true' 9 | AllowAllParametersOfDeclarationOnNextLine: 'false' 10 | AllowShortBlocksOnASingleLine: 'false' 11 | AllowShortCaseLabelsOnASingleLine: 'false' 12 | AllowShortFunctionsOnASingleLine: InlineOnly 13 | AllowShortIfStatementsOnASingleLine: 'true' 14 | AllowShortLoopsOnASingleLine: 'true' 15 | AlwaysBreakAfterDefinitionReturnType: None 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakBeforeMultilineStrings: 'true' 18 | AlwaysBreakTemplateDeclarations: 'false' 19 | BinPackParameters: 'true' 20 | BreakAfterJavaFieldAnnotations: 'false' 21 | BreakBeforeBinaryOperators: None 22 | BreakBeforeBraces: Attach 23 | BreakBeforeInheritanceComma: 'false' 24 | BreakBeforeTernaryOperators: 'false' 25 | BreakConstructorInitializers: BeforeColon 26 | BreakStringLiterals: 'false' 27 | ColumnLimit: '0' 28 | CompactNamespaces: 'true' 29 | ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' 30 | ConstructorInitializerIndentWidth: '4' 31 | ContinuationIndentWidth: '4' 32 | Cpp11BracedListStyle: 'false' 33 | DerivePointerAlignment: 'false' 34 | FixNamespaceComments: 'true' 35 | IndentCaseLabels: 'true' 36 | IndentWidth: '4' 37 | IndentWrappedFunctionNames: 'false' 38 | JavaScriptQuotes: Single 39 | JavaScriptWrapImports: 'false' 40 | KeepEmptyLinesAtTheStartOfBlocks: 'false' 41 | MaxEmptyLinesToKeep: '1' 42 | NamespaceIndentation: All 43 | ObjCBlockIndentWidth: '4' 44 | ObjCSpaceAfterProperty: 'false' 45 | ObjCSpaceBeforeProtocolList: 'false' 46 | PointerAlignment: Middle 47 | SortIncludes: 'false' 48 | SortUsingDeclarations: 'true' 49 | SpaceAfterCStyleCast: 'false' 50 | SpaceAfterTemplateKeyword: 'false' 51 | SpaceBeforeAssignmentOperators: 'true' 52 | SpaceBeforeParens: Never 53 | SpaceInEmptyParentheses: 'false' 54 | SpacesBeforeTrailingComments: '4' 55 | SpacesInAngles: 'false' 56 | SpacesInCStyleCastParentheses: 'false' 57 | SpacesInContainerLiterals: 'false' 58 | SpacesInParentheses: 'false' 59 | SpacesInSquareBrackets: 'false' 60 | TabWidth: '4' 61 | UseTab: Never 62 | 63 | ... 64 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | /tests/webSocketServer/node_modules 30 | 31 | # IDE 32 | .vscode 33 | .cproject 34 | .project 35 | .settings 36 | *.swp 37 | 38 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | dist: 3 | - xenial 4 | addons: 5 | apt: 6 | packages: 7 | - xvfb 8 | language: bash 9 | os: 10 | - linux 11 | env: 12 | matrix: 13 | - CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80" IDE_VERSION=1.6.13 14 | - CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80,dbg=Serial1" IDE_VERSION=1.6.13 15 | - CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80,eesz=1M,FlashMode=qio,FlashFreq=80" IDE_VERSION=1.8.13 16 | - CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.5 17 | - CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.9 18 | - CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.13 19 | script: 20 | - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 21 | - export DISPLAY=:1.0 22 | - sleep 3 23 | - wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz 24 | - tar xf arduino-$IDE_VERSION-linux64.tar.xz 25 | - mv arduino-$IDE_VERSION $HOME/arduino_ide 26 | - export PATH="$HOME/arduino_ide:$PATH" 27 | - which arduino 28 | - mkdir -p $HOME/Arduino/libraries 29 | 30 | - wget https://github.com/bblanchon/ArduinoJson/archive/6.x.zip 31 | - unzip 6.x.zip 32 | - mv ArduinoJson-6.x $HOME/Arduino/libraries/ArduinoJson 33 | - cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/arduinoWebSockets 34 | - source $TRAVIS_BUILD_DIR/travis/common.sh 35 | - get_core $CPU 36 | - cd $TRAVIS_BUILD_DIR 37 | - arduino --board $BOARD --save-prefs 38 | - arduino --get-pref sketchbook.path 39 | - arduino --pref update.check=false 40 | - build_sketches arduino $HOME/Arduino/libraries/arduinoWebSockets/examples/$CPU $CPU 41 | 42 | notifications: 43 | email: 44 | on_success: change 45 | on_failure: change 46 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/README.md: -------------------------------------------------------------------------------- 1 | WebSocket Server and Client for Arduino [![Build Status](https://github.com/Links2004/arduinoWebSockets/workflows/CI/badge.svg?branch=master)](https://github.com/Links2004/arduinoWebSockets/actions?query=workflow%3ACI+branch%3Amaster) 2 | =========================================== 3 | 4 | a WebSocket Server and Client for Arduino based on RFC6455. 5 | 6 | 7 | ##### Supported features of RFC6455 ##### 8 | - text frame 9 | - binary frame 10 | - connection close 11 | - ping 12 | - pong 13 | - continuation frame 14 | 15 | ##### Limitations ##### 16 | - max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define 17 | - max output length has no limit (the hardware is the limit) 18 | - Client send big frames with mask 0x00000000 (on AVR all frames) 19 | - continuation frame reassembly need to be handled in the application code 20 | 21 | ##### Limitations for Async ##### 22 | - Functions called from within the context of the websocket event might not honor `yield()` and/or `delay()`. See [this issue](https://github.com/Links2004/arduinoWebSockets/issues/58#issuecomment-192376395) for more info and a potential workaround. 23 | - wss / SSL is not possible. 24 | 25 | ##### Supported Hardware ##### 26 | - ESP8266 [Arduino for ESP8266](https://github.com/esp8266/Arduino/) 27 | - ESP32 [Arduino for ESP32](https://github.com/espressif/arduino-esp32) 28 | - ESP31B 29 | - Particle with STM32 ARM Cortex M3 30 | - ATmega328 with Ethernet Shield (ATmega branch) 31 | - ATmega328 with enc28j60 (ATmega branch) 32 | - ATmega2560 with Ethernet Shield (ATmega branch) 33 | - ATmega2560 with enc28j60 (ATmega branch) 34 | 35 | ###### Note: ###### 36 | 37 | version 2.0.0 and up is not compatible with AVR/ATmega, check ATmega branch. 38 | 39 | version 2.3.0 has API changes for the ESP8266 BareSSL (may brakes existing code) 40 | 41 | Arduino for AVR not supports std namespace of c++. 42 | 43 | ### wss / SSL ### 44 | supported for: 45 | - wss client on the ESP8266 46 | - wss / SSL is not natively supported in WebSocketsServer however it is possible to achieve secure websockets 47 | by running the device behind an SSL proxy. See [Nginx](examples/Nginx/esp8266.ssl.reverse.proxy.conf) for a 48 | sample Nginx server configuration file to enable this. 49 | 50 | ### ESP Async TCP ### 51 | 52 | This libary can run in Async TCP mode on the ESP. 53 | 54 | The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE define). 55 | 56 | [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) libary is required. 57 | 58 | 59 | ### High Level Client API ### 60 | 61 | - `begin` : Initiate connection sequence to the websocket host. 62 | ```c++ 63 | void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); 64 | void begin(String host, uint16_t port, String url = "/", String protocol = "arduino"); 65 | ``` 66 | - `onEvent`: Callback to handle for websocket events 67 | 68 | ```c++ 69 | void onEvent(WebSocketClientEvent cbEvent); 70 | ``` 71 | 72 | - `WebSocketClientEvent`: Handler for websocket events 73 | ```c++ 74 | void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length) 75 | ``` 76 | Where `WStype_t type` is defined as: 77 | ```c++ 78 | typedef enum { 79 | WStype_ERROR, 80 | WStype_DISCONNECTED, 81 | WStype_CONNECTED, 82 | WStype_TEXT, 83 | WStype_BIN, 84 | WStype_FRAGMENT_TEXT_START, 85 | WStype_FRAGMENT_BIN_START, 86 | WStype_FRAGMENT, 87 | WStype_FRAGMENT_FIN, 88 | WStype_PING, 89 | WStype_PONG, 90 | } WStype_t; 91 | ``` 92 | 93 | ### Issues ### 94 | Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues 95 | 96 | [![Join the chat at https://gitter.im/Links2004/arduinoWebSockets](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Links2004/arduinoWebSockets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 97 | 98 | ### License and credits ### 99 | 100 | The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE) 101 | 102 | [libb64](http://libb64.sourceforge.net/) written by Chris Venter. It is distributed under Public Domain see [LICENSE](https://github.com/Links2004/arduinoWebSockets/blob/master/src/libb64/LICENSE). 103 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/Nginx/esp8266.ssl.reverse.proxy.conf: -------------------------------------------------------------------------------- 1 | # ESP8266 nginx SSL reverse proxy configuration file (tested and working on nginx v1.10.0) 2 | 3 | # proxy cache location 4 | proxy_cache_path /opt/etc/nginx/cache levels=1:2 keys_zone=ESP8266_cache:10m max_size=10g inactive=5m use_temp_path=off; 5 | 6 | # webserver proxy 7 | server { 8 | 9 | # general server parameters 10 | listen 50080; 11 | server_name myDomain.net; 12 | access_log /opt/var/log/nginx/myDomain.net.access.log; 13 | 14 | # SSL configuration 15 | ssl on; 16 | ssl_certificate /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/fullchain.pem; 17 | ssl_certificate_key /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/privkey.pem; 18 | ssl_session_cache builtin:1000 shared:SSL:10m; 19 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 20 | ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; 21 | ssl_prefer_server_ciphers on; 22 | 23 | location / { 24 | 25 | # proxy caching configuration 26 | proxy_cache ESP8266_cache; 27 | proxy_cache_revalidate on; 28 | proxy_cache_min_uses 1; 29 | proxy_cache_use_stale off; 30 | proxy_cache_lock on; 31 | # proxy_cache_bypass $http_cache_control; 32 | # include the sessionId cookie value as part of the cache key - keeps the cache per user 33 | # proxy_cache_key $proxy_host$request_uri$cookie_sessionId; 34 | 35 | # header pass through configuration 36 | proxy_set_header Host $host; 37 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 38 | proxy_set_header X-Forwarded-Proto $scheme; 39 | 40 | # ESP8266 custom headers which identify to the device that it's running through an SSL proxy 41 | proxy_set_header X-SSL On; 42 | proxy_set_header X-SSL-WebserverPort 50080; 43 | proxy_set_header X-SSL-WebsocketPort 50081; 44 | 45 | # extra debug headers 46 | add_header X-Proxy-Cache $upstream_cache_status; 47 | add_header X-Forwarded-For $proxy_add_x_forwarded_for; 48 | 49 | # actual proxying configuration 50 | proxy_ssl_session_reuse on; 51 | # target the IP address of the device with proxy_pass 52 | proxy_pass http://192.168.0.20; 53 | proxy_read_timeout 90; 54 | } 55 | } 56 | 57 | # websocket proxy 58 | server { 59 | 60 | # general server parameters 61 | listen 50081; 62 | server_name myDomain.net; 63 | access_log /opt/var/log/nginx/myDomain.net.wss.access.log; 64 | 65 | # SSL configuration 66 | ssl on; 67 | ssl_certificate /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/fullchain.pem; 68 | ssl_certificate_key /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/privkey.pem; 69 | ssl_session_cache builtin:1000 shared:SSL:10m; 70 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 71 | ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; 72 | ssl_prefer_server_ciphers on; 73 | 74 | location / { 75 | 76 | # websocket upgrade tunnel configuration 77 | proxy_pass http://192.168.0.20:81; 78 | proxy_http_version 1.1; 79 | proxy_set_header Upgrade $http_upgrade; 80 | proxy_set_header Connection "Upgrade"; 81 | proxy_read_timeout 86400; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/avr/WebSocketClientAVR/WebSocketClientAVR.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientAVR.ino 3 | * 4 | * Created on: 10.12.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | 16 | 17 | // Enter a MAC address for your controller below. 18 | // Newer Ethernet shields have a MAC address printed on a sticker on the shield 19 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 20 | 21 | // Set the static IP address to use if the DHCP fails to assign 22 | IPAddress ip(192, 168, 0, 177); 23 | 24 | WebSocketsClient webSocket; 25 | 26 | 27 | 28 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 29 | 30 | 31 | switch(type) { 32 | case WStype_DISCONNECTED: 33 | Serial.println("[WSc] Disconnected!\n"); 34 | break; 35 | case WStype_CONNECTED: 36 | { 37 | Serial.print("[WSc] Connected to url: "); 38 | Serial.println((char *)payload); 39 | // send message to server when Connected 40 | webSocket.sendTXT("Connected"); 41 | } 42 | break; 43 | case WStype_TEXT: 44 | Serial.print("[WSc] get text: "); 45 | Serial.println((char *)payload); 46 | // send message to server 47 | // webSocket.sendTXT("message here"); 48 | break; 49 | case WStype_BIN: 50 | Serial.print("[WSc] get binary length: "); 51 | Serial.println(length); 52 | // hexdump(payload, length); 53 | 54 | // send data to server 55 | // webSocket.sendBIN(payload, length); 56 | break; 57 | } 58 | 59 | } 60 | 61 | void setup() 62 | { 63 | // Open serial communications and wait for port to open: 64 | Serial.begin(115200); 65 | while (!Serial) {} 66 | 67 | // start the Ethernet connection: 68 | if (Ethernet.begin(mac) == 0) { 69 | Serial.println("Failed to configure Ethernet using DHCP"); 70 | // no point in carrying on, so do nothing forevermore: 71 | // try to congifure using IP address instead of DHCP: 72 | Ethernet.begin(mac, ip); 73 | } 74 | 75 | webSocket.begin("192.168.0.123", 8011); 76 | webSocket.onEvent(webSocketEvent); 77 | 78 | } 79 | 80 | 81 | void loop() 82 | { 83 | webSocket.loop(); 84 | } 85 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp32/WebSocketClient/WebSocketClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClient.ino 3 | * 4 | * Created on: 24.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | 17 | WiFiMulti WiFiMulti; 18 | WebSocketsClient webSocket; 19 | 20 | #define USE_SERIAL Serial1 21 | 22 | void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) { 23 | const uint8_t* src = (const uint8_t*) mem; 24 | USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len); 25 | for(uint32_t i = 0; i < len; i++) { 26 | if(i % cols == 0) { 27 | USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); 28 | } 29 | USE_SERIAL.printf("%02X ", *src); 30 | src++; 31 | } 32 | USE_SERIAL.printf("\n"); 33 | } 34 | 35 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 36 | 37 | switch(type) { 38 | case WStype_DISCONNECTED: 39 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 40 | break; 41 | case WStype_CONNECTED: 42 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 43 | 44 | // send message to server when Connected 45 | webSocket.sendTXT("Connected"); 46 | break; 47 | case WStype_TEXT: 48 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 49 | 50 | // send message to server 51 | // webSocket.sendTXT("message here"); 52 | break; 53 | case WStype_BIN: 54 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 55 | hexdump(payload, length); 56 | 57 | // send data to server 58 | // webSocket.sendBIN(payload, length); 59 | break; 60 | case WStype_ERROR: 61 | case WStype_FRAGMENT_TEXT_START: 62 | case WStype_FRAGMENT_BIN_START: 63 | case WStype_FRAGMENT: 64 | case WStype_FRAGMENT_FIN: 65 | break; 66 | } 67 | 68 | } 69 | 70 | void setup() { 71 | // USE_SERIAL.begin(921600); 72 | USE_SERIAL.begin(115200); 73 | 74 | //Serial.setDebugOutput(true); 75 | USE_SERIAL.setDebugOutput(true); 76 | 77 | USE_SERIAL.println(); 78 | USE_SERIAL.println(); 79 | USE_SERIAL.println(); 80 | 81 | for(uint8_t t = 4; t > 0; t--) { 82 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 83 | USE_SERIAL.flush(); 84 | delay(1000); 85 | } 86 | 87 | WiFiMulti.addAP("SSID", "passpasspass"); 88 | 89 | //WiFi.disconnect(); 90 | while(WiFiMulti.run() != WL_CONNECTED) { 91 | delay(100); 92 | } 93 | 94 | // server address, port and URL 95 | webSocket.begin("192.168.0.123", 81, "/"); 96 | 97 | // event handler 98 | webSocket.onEvent(webSocketEvent); 99 | 100 | // use HTTP Basic Authorization this is optional remove if not needed 101 | webSocket.setAuthorization("user", "Password"); 102 | 103 | // try ever 5000 again if connection has failed 104 | webSocket.setReconnectInterval(5000); 105 | 106 | } 107 | 108 | void loop() { 109 | webSocket.loop(); 110 | } 111 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp32/WebSocketClientSSL/WebSocketClientSSL.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSSL.ino 3 | * 4 | * Created on: 10.12.2015 5 | * 6 | * note SSL is only possible with the ESP8266 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | 19 | WiFiMulti WiFiMulti; 20 | WebSocketsClient webSocket; 21 | 22 | #define USE_SERIAL Serial1 23 | 24 | void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) { 25 | const uint8_t* src = (const uint8_t*) mem; 26 | USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len); 27 | for(uint32_t i = 0; i < len; i++) { 28 | if(i % cols == 0) { 29 | USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); 30 | } 31 | USE_SERIAL.printf("%02X ", *src); 32 | src++; 33 | } 34 | USE_SERIAL.printf("\n"); 35 | } 36 | 37 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 38 | 39 | 40 | switch(type) { 41 | case WStype_DISCONNECTED: 42 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 43 | break; 44 | case WStype_CONNECTED: 45 | { 46 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 47 | 48 | // send message to server when Connected 49 | webSocket.sendTXT("Connected"); 50 | } 51 | break; 52 | case WStype_TEXT: 53 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 54 | 55 | // send message to server 56 | // webSocket.sendTXT("message here"); 57 | break; 58 | case WStype_BIN: 59 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 60 | hexdump(payload, length); 61 | 62 | // send data to server 63 | // webSocket.sendBIN(payload, length); 64 | break; 65 | case WStype_ERROR: 66 | case WStype_FRAGMENT_TEXT_START: 67 | case WStype_FRAGMENT_BIN_START: 68 | case WStype_FRAGMENT: 69 | case WStype_FRAGMENT_FIN: 70 | break; 71 | } 72 | 73 | } 74 | 75 | void setup() { 76 | // USE_SERIAL.begin(921600); 77 | USE_SERIAL.begin(115200); 78 | 79 | //Serial.setDebugOutput(true); 80 | USE_SERIAL.setDebugOutput(true); 81 | 82 | USE_SERIAL.println(); 83 | USE_SERIAL.println(); 84 | USE_SERIAL.println(); 85 | 86 | for(uint8_t t = 4; t > 0; t--) { 87 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 88 | USE_SERIAL.flush(); 89 | delay(1000); 90 | } 91 | 92 | WiFiMulti.addAP("SSID", "passpasspass"); 93 | 94 | //WiFi.disconnect(); 95 | while(WiFiMulti.run() != WL_CONNECTED) { 96 | delay(100); 97 | } 98 | 99 | webSocket.beginSSL("192.168.0.123", 81); 100 | webSocket.onEvent(webSocketEvent); 101 | 102 | } 103 | 104 | void loop() { 105 | webSocket.loop(); 106 | } 107 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp32/WebSocketServer/WebSocketServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer.ino 3 | * 4 | * Created on: 22.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | WiFiMulti WiFiMulti; 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial1 20 | 21 | void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) { 22 | const uint8_t* src = (const uint8_t*) mem; 23 | USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len); 24 | for(uint32_t i = 0; i < len; i++) { 25 | if(i % cols == 0) { 26 | USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); 27 | } 28 | USE_SERIAL.printf("%02X ", *src); 29 | src++; 30 | } 31 | USE_SERIAL.printf("\n"); 32 | } 33 | 34 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 35 | 36 | switch(type) { 37 | case WStype_DISCONNECTED: 38 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 39 | break; 40 | case WStype_CONNECTED: 41 | { 42 | IPAddress ip = webSocket.remoteIP(num); 43 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 44 | 45 | // send message to client 46 | webSocket.sendTXT(num, "Connected"); 47 | } 48 | break; 49 | case WStype_TEXT: 50 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 51 | 52 | // send message to client 53 | // webSocket.sendTXT(num, "message here"); 54 | 55 | // send data to all connected clients 56 | // webSocket.broadcastTXT("message here"); 57 | break; 58 | case WStype_BIN: 59 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 60 | hexdump(payload, length); 61 | 62 | // send message to client 63 | // webSocket.sendBIN(num, payload, length); 64 | break; 65 | case WStype_ERROR: 66 | case WStype_FRAGMENT_TEXT_START: 67 | case WStype_FRAGMENT_BIN_START: 68 | case WStype_FRAGMENT: 69 | case WStype_FRAGMENT_FIN: 70 | break; 71 | } 72 | 73 | } 74 | 75 | void setup() { 76 | // USE_SERIAL.begin(921600); 77 | USE_SERIAL.begin(115200); 78 | 79 | //Serial.setDebugOutput(true); 80 | USE_SERIAL.setDebugOutput(true); 81 | 82 | USE_SERIAL.println(); 83 | USE_SERIAL.println(); 84 | USE_SERIAL.println(); 85 | 86 | for(uint8_t t = 4; t > 0; t--) { 87 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 88 | USE_SERIAL.flush(); 89 | delay(1000); 90 | } 91 | 92 | WiFiMulti.addAP("SSID", "passpasspass"); 93 | 94 | while(WiFiMulti.run() != WL_CONNECTED) { 95 | delay(100); 96 | } 97 | 98 | webSocket.begin(); 99 | webSocket.onEvent(webSocketEvent); 100 | } 101 | 102 | void loop() { 103 | webSocket.loop(); 104 | } 105 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClient/WebSocketClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClient.ino 3 | * 4 | * Created on: 24.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | ESP8266WiFiMulti WiFiMulti; 18 | WebSocketsClient webSocket; 19 | 20 | #define USE_SERIAL Serial1 21 | 22 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 23 | 24 | switch(type) { 25 | case WStype_DISCONNECTED: 26 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 27 | break; 28 | case WStype_CONNECTED: { 29 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 30 | 31 | // send message to server when Connected 32 | webSocket.sendTXT("Connected"); 33 | } 34 | break; 35 | case WStype_TEXT: 36 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 37 | 38 | // send message to server 39 | // webSocket.sendTXT("message here"); 40 | break; 41 | case WStype_BIN: 42 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 43 | hexdump(payload, length); 44 | 45 | // send data to server 46 | // webSocket.sendBIN(payload, length); 47 | break; 48 | case WStype_PING: 49 | // pong will be send automatically 50 | USE_SERIAL.printf("[WSc] get ping\n"); 51 | break; 52 | case WStype_PONG: 53 | // answer to a ping we send 54 | USE_SERIAL.printf("[WSc] get pong\n"); 55 | break; 56 | } 57 | 58 | } 59 | 60 | void setup() { 61 | // USE_SERIAL.begin(921600); 62 | USE_SERIAL.begin(115200); 63 | 64 | //Serial.setDebugOutput(true); 65 | USE_SERIAL.setDebugOutput(true); 66 | 67 | USE_SERIAL.println(); 68 | USE_SERIAL.println(); 69 | USE_SERIAL.println(); 70 | 71 | for(uint8_t t = 4; t > 0; t--) { 72 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 73 | USE_SERIAL.flush(); 74 | delay(1000); 75 | } 76 | 77 | WiFiMulti.addAP("SSID", "passpasspass"); 78 | 79 | //WiFi.disconnect(); 80 | while(WiFiMulti.run() != WL_CONNECTED) { 81 | delay(100); 82 | } 83 | 84 | // server address, port and URL 85 | webSocket.begin("192.168.0.123", 81, "/"); 86 | 87 | // event handler 88 | webSocket.onEvent(webSocketEvent); 89 | 90 | // use HTTP Basic Authorization this is optional remove if not needed 91 | webSocket.setAuthorization("user", "Password"); 92 | 93 | // try ever 5000 again if connection has failed 94 | webSocket.setReconnectInterval(5000); 95 | 96 | // start heartbeat (optional) 97 | // ping server every 15000 ms 98 | // expect pong from server within 3000 ms 99 | // consider connection disconnected if pong is not received 2 times 100 | webSocket.enableHeartbeat(15000, 3000, 2); 101 | 102 | } 103 | 104 | void loop() { 105 | webSocket.loop(); 106 | } 107 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClientOTA/README.md: -------------------------------------------------------------------------------- 1 | ## Minimal example of WebsocketClientOTA and Python server 2 | 3 | Take this as small example, how achieve OTA update on ESP8266 and ESP32. 4 | 5 | Python server was wrote from train so take it only as bare example. 6 | It's working, but it's not mean to run in production. 7 | 8 | 9 | ### Usage: 10 | 11 | Start server: 12 | ```bash 13 | cd python_ota_server 14 | python3 -m venv .venv 15 | source .venv/bin/activate 16 | pip3 install -r requirements.txt 17 | python3 main.py 18 | ``` 19 | 20 | Flash ESP with example sketch and start it. 21 | 22 | Change version inside example sketch to higher and compile it and save it to bin file. 23 | 24 | Rename it to `mydevice-1.0.1-esp8266.bin` and place it inside new folder firmware (server create it). 25 | 26 | When the ESP connect to server, it check if version flashed is equal to fw in firmware folder. If higher FW version is present, 27 | start the flash process. -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClientOTA/python_ota_server/requirements.txt: -------------------------------------------------------------------------------- 1 | packaging 2 | websockets -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClientSSL/WebSocketClientSSL.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSSL.ino 3 | * 4 | * Created on: 10.12.2015 5 | * 6 | * note SSL is only possible with the ESP8266 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | ESP8266WiFiMulti WiFiMulti; 20 | WebSocketsClient webSocket; 21 | 22 | 23 | #define USE_SERIAL Serial1 24 | 25 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 26 | 27 | 28 | switch(type) { 29 | case WStype_DISCONNECTED: 30 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 31 | break; 32 | case WStype_CONNECTED: 33 | { 34 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 35 | 36 | // send message to server when Connected 37 | webSocket.sendTXT("Connected"); 38 | } 39 | break; 40 | case WStype_TEXT: 41 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 42 | 43 | // send message to server 44 | // webSocket.sendTXT("message here"); 45 | break; 46 | case WStype_BIN: 47 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 48 | hexdump(payload, length); 49 | 50 | // send data to server 51 | // webSocket.sendBIN(payload, length); 52 | break; 53 | } 54 | 55 | } 56 | 57 | void setup() { 58 | // USE_SERIAL.begin(921600); 59 | USE_SERIAL.begin(115200); 60 | 61 | //Serial.setDebugOutput(true); 62 | USE_SERIAL.setDebugOutput(true); 63 | 64 | USE_SERIAL.println(); 65 | USE_SERIAL.println(); 66 | USE_SERIAL.println(); 67 | 68 | for(uint8_t t = 4; t > 0; t--) { 69 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 70 | USE_SERIAL.flush(); 71 | delay(1000); 72 | } 73 | 74 | WiFiMulti.addAP("SSID", "passpasspass"); 75 | 76 | //WiFi.disconnect(); 77 | while(WiFiMulti.run() != WL_CONNECTED) { 78 | delay(100); 79 | } 80 | 81 | webSocket.beginSSL("192.168.0.123", 81); 82 | webSocket.onEvent(webSocketEvent); 83 | 84 | } 85 | 86 | void loop() { 87 | webSocket.loop(); 88 | } 89 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClientSSLWithCA/WebSocketClientSSLWithCA.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSSLWithCA.ino 3 | * 4 | * Created on: 27.10.2019 5 | * 6 | * note SSL is only possible with the ESP8266 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | ESP8266WiFiMulti WiFiMulti; 18 | WebSocketsClient webSocket; 19 | 20 | #define USE_SERIAL Serial1 21 | 22 | 23 | // Can be obtained with: 24 | // openssl s_client -showcerts -connect echo.websocket.org:443 0; t--) { 82 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 83 | USE_SERIAL.flush(); 84 | delay(1000); 85 | } 86 | 87 | WiFiMulti.addAP("SSID", "passpasspass"); 88 | 89 | while(WiFiMulti.run() != WL_CONNECTED) { 90 | delay(100); 91 | } 92 | 93 | //When using BearSSL, client certificate and private key can be set: 94 | //webSocket.setSSLClientCertKey(clientCert, clientPrivateKey); 95 | //clientCert and clientPrivateKey can be of types (const char *, const char *) , or of types (BearSSL::X509List, BearSSL::PrivateKey) 96 | 97 | webSocket.beginSslWithCA("echo.websocket.org", 443, "/", ENDPOINT_CA_CERT); 98 | webSocket.onEvent(webSocketEvent); 99 | } 100 | 101 | void loop() { 102 | webSocket.loop(); 103 | } 104 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketClientSocketIO/WebSocketClientSocketIO.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSocketIO.ino 3 | * 4 | * Created on: 06.06.2016 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | ESP8266WiFiMulti WiFiMulti; 21 | SocketIOclient socketIO; 22 | 23 | #define USE_SERIAL Serial1 24 | 25 | void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) { 26 | switch(type) { 27 | case sIOtype_DISCONNECT: 28 | USE_SERIAL.printf("[IOc] Disconnected!\n"); 29 | break; 30 | case sIOtype_CONNECT: 31 | USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload); 32 | 33 | // join default namespace (no auto join in Socket.IO V3) 34 | socketIO.send(sIOtype_CONNECT, "/"); 35 | break; 36 | case sIOtype_EVENT: 37 | USE_SERIAL.printf("[IOc] get event: %s\n", payload); 38 | break; 39 | case sIOtype_ACK: 40 | USE_SERIAL.printf("[IOc] get ack: %u\n", length); 41 | hexdump(payload, length); 42 | break; 43 | case sIOtype_ERROR: 44 | USE_SERIAL.printf("[IOc] get error: %u\n", length); 45 | hexdump(payload, length); 46 | break; 47 | case sIOtype_BINARY_EVENT: 48 | USE_SERIAL.printf("[IOc] get binary: %u\n", length); 49 | hexdump(payload, length); 50 | break; 51 | case sIOtype_BINARY_ACK: 52 | USE_SERIAL.printf("[IOc] get binary ack: %u\n", length); 53 | hexdump(payload, length); 54 | break; 55 | } 56 | } 57 | 58 | void setup() { 59 | // USE_SERIAL.begin(921600); 60 | USE_SERIAL.begin(115200); 61 | 62 | //Serial.setDebugOutput(true); 63 | USE_SERIAL.setDebugOutput(true); 64 | 65 | USE_SERIAL.println(); 66 | USE_SERIAL.println(); 67 | USE_SERIAL.println(); 68 | 69 | for(uint8_t t = 4; t > 0; t--) { 70 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 71 | USE_SERIAL.flush(); 72 | delay(1000); 73 | } 74 | 75 | // disable AP 76 | if(WiFi.getMode() & WIFI_AP) { 77 | WiFi.softAPdisconnect(true); 78 | } 79 | 80 | WiFiMulti.addAP("SSID", "passpasspass"); 81 | 82 | //WiFi.disconnect(); 83 | while(WiFiMulti.run() != WL_CONNECTED) { 84 | delay(100); 85 | } 86 | 87 | String ip = WiFi.localIP().toString(); 88 | USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str()); 89 | 90 | // server address, port and URL 91 | socketIO.begin("10.11.100.100", 8880, "/socket.io/?EIO=4"); 92 | 93 | // event handler 94 | socketIO.onEvent(socketIOEvent); 95 | } 96 | 97 | unsigned long messageTimestamp = 0; 98 | void loop() { 99 | socketIO.loop(); 100 | 101 | uint64_t now = millis(); 102 | 103 | if(now - messageTimestamp > 2000) { 104 | messageTimestamp = now; 105 | 106 | // creat JSON message for Socket.IO (event) 107 | DynamicJsonDocument doc(1024); 108 | JsonArray array = doc.to(); 109 | 110 | // add evnet name 111 | // Hint: socket.on('event_name', .... 112 | array.add("event_name"); 113 | 114 | // add payload (parameters) for the event 115 | JsonObject param1 = array.createNestedObject(); 116 | param1["now"] = (uint32_t) now; 117 | 118 | // JSON to String (serializion) 119 | String output; 120 | serializeJson(doc, output); 121 | 122 | // Send event 123 | socketIO.sendEVENT(output); 124 | 125 | // Print JSON for debugging 126 | USE_SERIAL.println(output); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServer/WebSocketServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer.ino 3 | * 4 | * Created on: 22.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial1 20 | 21 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 22 | 23 | switch(type) { 24 | case WStype_DISCONNECTED: 25 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 26 | break; 27 | case WStype_CONNECTED: 28 | { 29 | IPAddress ip = webSocket.remoteIP(num); 30 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 31 | 32 | // send message to client 33 | webSocket.sendTXT(num, "Connected"); 34 | } 35 | break; 36 | case WStype_TEXT: 37 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 38 | 39 | // send message to client 40 | // webSocket.sendTXT(num, "message here"); 41 | 42 | // send data to all connected clients 43 | // webSocket.broadcastTXT("message here"); 44 | break; 45 | case WStype_BIN: 46 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 47 | hexdump(payload, length); 48 | 49 | // send message to client 50 | // webSocket.sendBIN(num, payload, length); 51 | break; 52 | } 53 | 54 | } 55 | 56 | void setup() { 57 | // USE_SERIAL.begin(921600); 58 | USE_SERIAL.begin(115200); 59 | 60 | //Serial.setDebugOutput(true); 61 | USE_SERIAL.setDebugOutput(true); 62 | 63 | USE_SERIAL.println(); 64 | USE_SERIAL.println(); 65 | USE_SERIAL.println(); 66 | 67 | for(uint8_t t = 4; t > 0; t--) { 68 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 69 | USE_SERIAL.flush(); 70 | delay(1000); 71 | } 72 | 73 | WiFiMulti.addAP("SSID", "passpasspass"); 74 | 75 | while(WiFiMulti.run() != WL_CONNECTED) { 76 | delay(100); 77 | } 78 | 79 | webSocket.begin(); 80 | webSocket.onEvent(webSocketEvent); 81 | } 82 | 83 | void loop() { 84 | webSocket.loop(); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServerFragmentation/WebSocketServerFragmentation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer.ino 3 | * 4 | * Created on: 22.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial 20 | 21 | String fragmentBuffer = ""; 22 | 23 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 24 | 25 | switch(type) { 26 | case WStype_DISCONNECTED: 27 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 28 | break; 29 | case WStype_CONNECTED: { 30 | IPAddress ip = webSocket.remoteIP(num); 31 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 32 | 33 | // send message to client 34 | webSocket.sendTXT(num, "Connected"); 35 | } 36 | break; 37 | case WStype_TEXT: 38 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 39 | break; 40 | case WStype_BIN: 41 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 42 | hexdump(payload, length); 43 | break; 44 | 45 | // Fragmentation / continuation opcode handling 46 | // case WStype_FRAGMENT_BIN_START: 47 | case WStype_FRAGMENT_TEXT_START: 48 | fragmentBuffer = (char*)payload; 49 | USE_SERIAL.printf("[%u] get start start of Textfragment: %s\n", num, payload); 50 | break; 51 | case WStype_FRAGMENT: 52 | fragmentBuffer += (char*)payload; 53 | USE_SERIAL.printf("[%u] get Textfragment : %s\n", num, payload); 54 | break; 55 | case WStype_FRAGMENT_FIN: 56 | fragmentBuffer += (char*)payload; 57 | USE_SERIAL.printf("[%u] get end of Textfragment: %s\n", num, payload); 58 | USE_SERIAL.printf("[%u] full frame: %s\n", num, fragmentBuffer.c_str()); 59 | break; 60 | } 61 | 62 | } 63 | 64 | void setup() { 65 | // USE_SERIAL.begin(921600); 66 | USE_SERIAL.begin(115200); 67 | 68 | //Serial.setDebugOutput(true); 69 | USE_SERIAL.setDebugOutput(true); 70 | 71 | USE_SERIAL.println(); 72 | USE_SERIAL.println(); 73 | USE_SERIAL.println(); 74 | 75 | for(uint8_t t = 4; t > 0; t--) { 76 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 77 | USE_SERIAL.flush(); 78 | delay(1000); 79 | } 80 | 81 | WiFiMulti.addAP("SSID", "passpasspass"); 82 | 83 | while(WiFiMulti.run() != WL_CONNECTED) { 84 | delay(100); 85 | } 86 | 87 | webSocket.begin(); 88 | webSocket.onEvent(webSocketEvent); 89 | } 90 | 91 | void loop() { 92 | webSocket.loop(); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServerHooked.ino 3 | * 4 | * Created on: 22.05.2015 5 | * Hooked on: 28.10.2020 6 | * 7 | */ 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | ESP8266WiFiMulti WiFiMulti; 18 | 19 | ESP8266WebServer server(80); 20 | WebSockets4WebServer webSocket; 21 | 22 | #define USE_SERIAL Serial 23 | 24 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 25 | 26 | switch(type) { 27 | case WStype_DISCONNECTED: 28 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 29 | break; 30 | case WStype_CONNECTED: 31 | { 32 | IPAddress ip = webSocket.remoteIP(num); 33 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 34 | 35 | // send message to client 36 | webSocket.sendTXT(num, "Connected"); 37 | } 38 | break; 39 | case WStype_TEXT: 40 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 41 | 42 | // send message to client 43 | // webSocket.sendTXT(num, "message here"); 44 | 45 | // send data to all connected clients 46 | // webSocket.broadcastTXT("message here"); 47 | break; 48 | case WStype_BIN: 49 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 50 | hexdump(payload, length); 51 | 52 | // send message to client 53 | // webSocket.sendBIN(num, payload, length); 54 | break; 55 | } 56 | 57 | } 58 | 59 | void setup() { 60 | // USE_SERIAL.begin(921600); 61 | USE_SERIAL.begin(115200); 62 | 63 | //Serial.setDebugOutput(true); 64 | USE_SERIAL.setDebugOutput(true); 65 | 66 | USE_SERIAL.println(); 67 | USE_SERIAL.println(); 68 | USE_SERIAL.println(); 69 | 70 | for(uint8_t t = 4; t > 0; t--) { 71 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 72 | USE_SERIAL.flush(); 73 | delay(1000); 74 | } 75 | 76 | WiFiMulti.addAP("SSID", "passpasspass"); 77 | 78 | while(WiFiMulti.run() != WL_CONNECTED) { 79 | delay(100); 80 | } 81 | 82 | server.on("/", []() { 83 | server.send(200, "text/plain", "I am a regular webserver on port 80!\r\n"); 84 | server.send(200, "text/plain", "I am also a websocket server on '/ws' on the same port 80\r\n"); 85 | }); 86 | 87 | server.addHook(webSocket.hookForWebserver("/ws", webSocketEvent)); 88 | 89 | server.begin(); 90 | Serial.println("HTTP server started on port 80"); 91 | Serial.println("WebSocket server started on the same port"); 92 | Serial.printf("my network address is either 'arduinoWebsockets.local' (mDNS) or '%s'\n", WiFi.localIP().toString().c_str()); 93 | 94 | if (!MDNS.begin("arduinoWebsockets")) { 95 | Serial.println("Error setting up MDNS responder!"); 96 | } 97 | } 98 | 99 | void loop() { 100 | server.handleClient(); 101 | webSocket.loop(); 102 | MDNS.update(); 103 | } 104 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServerHooked/emu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # linux script to compile&run arduinoWebSockets in a mock environment 4 | 5 | if [ -z "$ESP8266ARDUINO" ]; then 6 | echo "please set ESP8266ARDUINO env-var to where esp8266/arduino sits" 7 | exit 1 8 | fi 9 | 10 | set -e 11 | 12 | where=$(pwd) 13 | 14 | cd $ESP8266ARDUINO/tests/host/ 15 | 16 | make -j FORCE32=0 \ 17 | ULIBDIRS=../../libraries/Hash/:~/dev/proj/arduino/libraries/arduinoWebSockets \ 18 | ${where}/WebSocketServerHooked 19 | 20 | valgrind ./bin/WebSocketServerHooked/WebSocketServerHooked -b "$@" 21 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServerHooked/ws-testclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # python websocket client to test with 4 | # emulator: server is at ws://127.0.0.1:9080/ws 5 | # esp8266: server is at ws:///ws 6 | # (uncomment the right line below) 7 | 8 | #uri = "ws://127.0.0.1:9080/ws" 9 | uri = "ws://arduinoWebsockets.local/ws" 10 | 11 | import websocket 12 | try: 13 | import thread 14 | except ImportError: 15 | import _thread as thread 16 | import time 17 | 18 | def on_message(ws, message): 19 | print("message"); 20 | print(message) 21 | 22 | def on_error(ws, error): 23 | print("error") 24 | print(error) 25 | 26 | def on_close(ws): 27 | print("### closed ###") 28 | 29 | def on_open(ws): 30 | print("opened") 31 | def run(*args): 32 | for i in range(3): 33 | time.sleep(1) 34 | ws.send("Hello %d" % i) 35 | time.sleep(1) 36 | ws.close() 37 | print("thread terminating...") 38 | thread.start_new_thread(run, ()) 39 | 40 | 41 | if __name__ == "__main__": 42 | websocket.enableTrace(True) 43 | ws = websocket.WebSocketApp(uri, on_message = on_message, on_error = on_error, on_close = on_close) 44 | ws.on_open = on_open 45 | ws.run_forever() 46 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServerHttpHeaderValidation/WebSocketServerHttpHeaderValidation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServerHttpHeaderValidation.ino 3 | * 4 | * Created on: 08.06.2016 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial1 20 | 21 | const unsigned long int validSessionId = 12345; //some arbitrary value to act as a valid sessionId 22 | 23 | /* 24 | * Returns a bool value as an indicator to describe whether a user is allowed to initiate a websocket upgrade 25 | * based on the value of a cookie. This function expects the rawCookieHeaderValue to look like this "sessionId=|" 26 | */ 27 | bool isCookieValid(String rawCookieHeaderValue) { 28 | 29 | if (rawCookieHeaderValue.indexOf("sessionId") != -1) { 30 | String sessionIdStr = rawCookieHeaderValue.substring(rawCookieHeaderValue.indexOf("sessionId=") + 10, rawCookieHeaderValue.indexOf("|")); 31 | unsigned long int sessionId = strtoul(sessionIdStr.c_str(), NULL, 10); 32 | return sessionId == validSessionId; 33 | } 34 | return false; 35 | } 36 | 37 | /* 38 | * The WebSocketServerHttpHeaderValFunc delegate passed to webSocket.onValidateHttpHeader 39 | */ 40 | bool validateHttpHeader(String headerName, String headerValue) { 41 | 42 | //assume a true response for any headers not handled by this validator 43 | bool valid = true; 44 | 45 | if(headerName.equalsIgnoreCase("Cookie")) { 46 | //if the header passed is the Cookie header, validate it according to the rules in 'isCookieValid' function 47 | valid = isCookieValid(headerValue); 48 | } 49 | 50 | return valid; 51 | } 52 | 53 | void setup() { 54 | // USE_SERIAL.begin(921600); 55 | USE_SERIAL.begin(115200); 56 | 57 | //Serial.setDebugOutput(true); 58 | USE_SERIAL.setDebugOutput(true); 59 | 60 | USE_SERIAL.println(); 61 | USE_SERIAL.println(); 62 | USE_SERIAL.println(); 63 | 64 | for(uint8_t t = 4; t > 0; t--) { 65 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 66 | USE_SERIAL.flush(); 67 | delay(1000); 68 | } 69 | 70 | WiFiMulti.addAP("SSID", "passpasspass"); 71 | 72 | while(WiFiMulti.run() != WL_CONNECTED) { 73 | delay(100); 74 | } 75 | 76 | //connecting clients must supply a valid session cookie at websocket upgrade handshake negotiation time 77 | const char * headerkeys[] = { "Cookie" }; 78 | size_t headerKeyCount = sizeof(headerkeys) / sizeof(char*); 79 | webSocket.onValidateHttpHeader(validateHttpHeader, headerkeys, headerKeyCount); 80 | webSocket.begin(); 81 | } 82 | 83 | void loop() { 84 | webSocket.loop(); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/esp8266/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer_LEDcontrol.ino 3 | * 4 | * Created on: 26.11.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define LED_RED 15 18 | #define LED_GREEN 12 19 | #define LED_BLUE 13 20 | 21 | #define USE_SERIAL Serial 22 | 23 | 24 | ESP8266WiFiMulti WiFiMulti; 25 | 26 | ESP8266WebServer server(80); 27 | WebSocketsServer webSocket = WebSocketsServer(81); 28 | 29 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 30 | 31 | switch(type) { 32 | case WStype_DISCONNECTED: 33 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 34 | break; 35 | case WStype_CONNECTED: { 36 | IPAddress ip = webSocket.remoteIP(num); 37 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 38 | 39 | // send message to client 40 | webSocket.sendTXT(num, "Connected"); 41 | } 42 | break; 43 | case WStype_TEXT: 44 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 45 | 46 | if(payload[0] == '#') { 47 | // we get RGB data 48 | 49 | // decode rgb data 50 | uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16); 51 | 52 | analogWrite(LED_RED, ((rgb >> 16) & 0xFF)); 53 | analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF)); 54 | analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF)); 55 | } 56 | 57 | break; 58 | } 59 | 60 | } 61 | 62 | void setup() { 63 | //USE_SERIAL.begin(921600); 64 | USE_SERIAL.begin(115200); 65 | 66 | //USE_SERIAL.setDebugOutput(true); 67 | 68 | USE_SERIAL.println(); 69 | USE_SERIAL.println(); 70 | USE_SERIAL.println(); 71 | 72 | for(uint8_t t = 4; t > 0; t--) { 73 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 74 | USE_SERIAL.flush(); 75 | delay(1000); 76 | } 77 | 78 | pinMode(LED_RED, OUTPUT); 79 | pinMode(LED_GREEN, OUTPUT); 80 | pinMode(LED_BLUE, OUTPUT); 81 | 82 | digitalWrite(LED_RED, 1); 83 | digitalWrite(LED_GREEN, 1); 84 | digitalWrite(LED_BLUE, 1); 85 | 86 | WiFiMulti.addAP("SSID", "passpasspass"); 87 | 88 | while(WiFiMulti.run() != WL_CONNECTED) { 89 | delay(100); 90 | } 91 | 92 | // start webSocket server 93 | webSocket.begin(); 94 | webSocket.onEvent(webSocketEvent); 95 | 96 | if(MDNS.begin("esp8266")) { 97 | USE_SERIAL.println("MDNS responder started"); 98 | } 99 | 100 | // handle index 101 | server.on("/", []() { 102 | // send index.html 103 | server.send(200, "text/html", "LED Control:

R:
G:
B:
"); 104 | }); 105 | 106 | server.begin(); 107 | 108 | // Add service to MDNS 109 | MDNS.addService("http", "tcp", 80); 110 | MDNS.addService("ws", "tcp", 81); 111 | 112 | digitalWrite(LED_RED, 0); 113 | digitalWrite(LED_GREEN, 0); 114 | digitalWrite(LED_BLUE, 0); 115 | 116 | } 117 | 118 | void loop() { 119 | webSocket.loop(); 120 | server.handleClient(); 121 | } 122 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/examples/particle/ParticleWebSocketClient/application.cpp: -------------------------------------------------------------------------------- 1 | /* To compile using make CLI, create a folder under \firmware\user\applications and copy application.cpp there. 2 | * Then, copy src files under particleWebSocket folder. 3 | */ 4 | 5 | #include "application.h" 6 | #include "particleWebSocket/WebSocketsClient.h" 7 | 8 | WebSocketsClient webSocket; 9 | 10 | void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) 11 | { 12 | switch (type) 13 | { 14 | case WStype_DISCONNECTED: 15 | Serial.printlnf("[WSc] Disconnected!"); 16 | break; 17 | case WStype_CONNECTED: 18 | Serial.printlnf("[WSc] Connected to URL: %s", payload); 19 | webSocket.sendTXT("Connected\r\n"); 20 | break; 21 | case WStype_TEXT: 22 | Serial.printlnf("[WSc] get text: %s", payload); 23 | break; 24 | case WStype_BIN: 25 | Serial.printlnf("[WSc] get binary length: %u", length); 26 | break; 27 | } 28 | } 29 | 30 | void setup() 31 | { 32 | Serial.begin(9600); 33 | 34 | WiFi.setCredentials("[SSID]", "[PASSWORD]", WPA2, WLAN_CIPHER_AES_TKIP); 35 | WiFi.connect(); 36 | 37 | webSocket.begin("192.168.1.153", 85, "/ClientService/?variable=Test1212"); 38 | webSocket.onEvent(webSocketEvent); 39 | } 40 | 41 | void loop() 42 | { 43 | webSocket.sendTXT("Hello world!"); 44 | delay(500); 45 | webSocket.loop(); 46 | } 47 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | { 4 | "maintainer": true, 5 | "name": "Markus Sattler", 6 | "url": "https://github.com/Links2004" 7 | } 8 | ], 9 | "description": "WebSocket Server and Client for Arduino based on RFC6455", 10 | "export": { 11 | "exclude": [ 12 | "tests" 13 | ] 14 | }, 15 | "frameworks": "arduino", 16 | "keywords": "wifi, http, web, server, client, websocket", 17 | "license": "LGPL-2.1", 18 | "name": "WebSockets", 19 | "platforms": "atmelavr, espressif8266, espressif32", 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/Links2004/arduinoWebSockets.git" 23 | }, 24 | "version": "2.3.6" 25 | } -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/library.properties: -------------------------------------------------------------------------------- 1 | name=WebSockets 2 | version=2.3.6 3 | author=Markus Sattler 4 | maintainer=Markus Sattler 5 | sentence=WebSockets for Arduino (Server + Client) 6 | paragraph=use 2.x.x for ESP and 1.3 for AVR 7 | category=Communication 8 | url=https://github.com/Links2004/arduinoWebSockets 9 | architectures=* 10 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/WebSockets4WebServer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file WebSocketsServer.cpp 3 | * @date 28.10.2020 4 | * @author Markus Sattler & esp8266/arduino community 5 | * 6 | * Copyright (c) 2020 Markus Sattler. All rights reserved. 7 | * This file is part of the WebSockets for Arduino. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef __WEBSOCKETS4WEBSERVER_H 26 | #define __WEBSOCKETS4WEBSERVER_H 27 | 28 | #include 29 | #include 30 | 31 | #if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK 32 | 33 | class WebSockets4WebServer : public WebSocketsServerCore { 34 | public: 35 | WebSockets4WebServer(const String & origin = "", const String & protocol = "arduino") 36 | : WebSocketsServerCore(origin, protocol) { 37 | begin(); 38 | } 39 | 40 | ESP8266WebServer::HookFunction hookForWebserver(const String & wsRootDir, WebSocketServerEvent event) { 41 | onEvent(event); 42 | 43 | return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, ESP8266WebServer::ContentTypeFunction contentType) { 44 | (void)contentType; 45 | 46 | if(!(method == "GET" && url.indexOf(wsRootDir) == 0)) { 47 | return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE; 48 | } 49 | 50 | // allocate a WiFiClient copy (like in WebSocketsServer::handleNewClients()) 51 | WEBSOCKETS_NETWORK_CLASS * newTcpClient = new WEBSOCKETS_NETWORK_CLASS(*tcpClient); 52 | 53 | // Then initialize a new WSclient_t (like in WebSocketsServer::handleNewClient()) 54 | WSclient_t * client = handleNewClient(newTcpClient); 55 | 56 | if(client) { 57 | // give "GET " 58 | String headerLine; 59 | headerLine.reserve(url.length() + 5); 60 | headerLine = "GET "; 61 | headerLine += url; 62 | handleHeader(client, &headerLine); 63 | } 64 | 65 | // tell webserver to not close but forget about this client 66 | return ESP8266WebServer::CLIENT_IS_GIVEN; 67 | }; 68 | } 69 | }; 70 | #else // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK 71 | 72 | #ifndef WEBSERVER_HAS_HOOK 73 | #error Your current Framework / Arduino core version does not support Webserver Hook Functions 74 | #else 75 | #error Your Hardware Platform does not support Webserver Hook Functions 76 | #endif 77 | 78 | #endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK 79 | 80 | #endif // __WEBSOCKETS4WEBSERVER_H 81 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/WebSocketsVersion.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file WebSocketsVersion.h 3 | * @date 08.03.2021 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the WebSockets for Arduino. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef WEBSOCKETSVERSION_H_ 26 | #define WEBSOCKETSVERSION_H_ 27 | 28 | #define WEBSOCKETS_VERSION "2.3.6" 29 | 30 | #define WEBSOCKETS_VERSION_MAJOR 2 31 | #define WEBSOCKETS_VERSION_MINOR 3 32 | #define WEBSOCKETS_VERSION_PATCH 6 33 | 34 | #define WEBSOCKETS_VERSION_INT 2003006 35 | 36 | #endif /* WEBSOCKETSVERSION_H_ */ 37 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/AUTHORS: -------------------------------------------------------------------------------- 1 | libb64: Base64 Encoding/Decoding Routines 2 | ====================================== 3 | 4 | Authors: 5 | ------- 6 | 7 | Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com 8 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright-Only Dedication (based on United States law) 2 | or Public Domain Certification 3 | 4 | The person or persons who have associated work with this document (the 5 | "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of 6 | his knowledge, the work of authorship identified is in the public domain of the 7 | country from which the work is published, or (b) hereby dedicates whatever 8 | copyright the dedicators holds in the work of authorship identified below (the 9 | "Work") to the public domain. A certifier, moreover, dedicates any copyright 10 | interest he may have in the associated work, and for these purposes, is 11 | described as a "dedicator" below. 12 | 13 | A certifier has taken reasonable steps to verify the copyright status of this 14 | work. Certifier recognizes that his good faith efforts may not shield him from 15 | liability if in fact the work certified is not in the public domain. 16 | 17 | Dedicator makes this dedication for the benefit of the public at large and to 18 | the detriment of the Dedicator's heirs and successors. Dedicator intends this 19 | dedication to be an overt act of relinquishment in perpetuity of all present 20 | and future rights under copyright law, whether vested or contingent, in the 21 | Work. Dedicator understands that such relinquishment of all rights includes 22 | the relinquishment of all rights to enforce (by lawsuit or otherwise) those 23 | copyrights in the Work. 24 | 25 | Dedicator recognizes that, once placed in the public domain, the Work may be 26 | freely reproduced, distributed, transmitted, used, modified, built upon, or 27 | otherwise exploited by anyone for any purpose, commercial or non-commercial, 28 | and in any way, including by methods that have not yet been invented or 29 | conceived. -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/cdecode.c: -------------------------------------------------------------------------------- 1 | /* 2 | cdecoder.c - c source to a base64 decoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifdef ESP8266 9 | #include 10 | #endif 11 | 12 | #if defined(ESP32) 13 | #define CORE_HAS_LIBB64 14 | #endif 15 | 16 | #ifndef CORE_HAS_LIBB64 17 | #include "cdecode_inc.h" 18 | 19 | int base64_decode_value(char value_in) 20 | { 21 | static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; 22 | static const char decoding_size = sizeof(decoding); 23 | value_in -= 43; 24 | if (value_in < 0 || value_in > decoding_size) return -1; 25 | return decoding[(int)value_in]; 26 | } 27 | 28 | void base64_init_decodestate(base64_decodestate* state_in) 29 | { 30 | state_in->step = step_a; 31 | state_in->plainchar = 0; 32 | } 33 | 34 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) 35 | { 36 | const char* codechar = code_in; 37 | char* plainchar = plaintext_out; 38 | char fragment; 39 | 40 | *plainchar = state_in->plainchar; 41 | 42 | switch (state_in->step) 43 | { 44 | while (1) 45 | { 46 | case step_a: 47 | do { 48 | if (codechar == code_in+length_in) 49 | { 50 | state_in->step = step_a; 51 | state_in->plainchar = *plainchar; 52 | return plainchar - plaintext_out; 53 | } 54 | fragment = (char)base64_decode_value(*codechar++); 55 | } while (fragment < 0); 56 | *plainchar = (fragment & 0x03f) << 2; 57 | case step_b: 58 | do { 59 | if (codechar == code_in+length_in) 60 | { 61 | state_in->step = step_b; 62 | state_in->plainchar = *plainchar; 63 | return plainchar - plaintext_out; 64 | } 65 | fragment = (char)base64_decode_value(*codechar++); 66 | } while (fragment < 0); 67 | *plainchar++ |= (fragment & 0x030) >> 4; 68 | *plainchar = (fragment & 0x00f) << 4; 69 | case step_c: 70 | do { 71 | if (codechar == code_in+length_in) 72 | { 73 | state_in->step = step_c; 74 | state_in->plainchar = *plainchar; 75 | return plainchar - plaintext_out; 76 | } 77 | fragment = (char)base64_decode_value(*codechar++); 78 | } while (fragment < 0); 79 | *plainchar++ |= (fragment & 0x03c) >> 2; 80 | *plainchar = (fragment & 0x003) << 6; 81 | case step_d: 82 | do { 83 | if (codechar == code_in+length_in) 84 | { 85 | state_in->step = step_d; 86 | state_in->plainchar = *plainchar; 87 | return plainchar - plaintext_out; 88 | } 89 | fragment = (char)base64_decode_value(*codechar++); 90 | } while (fragment < 0); 91 | *plainchar++ |= (fragment & 0x03f); 92 | } 93 | } 94 | /* control should not reach here */ 95 | return plainchar - plaintext_out; 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/cdecode_inc.h: -------------------------------------------------------------------------------- 1 | /* 2 | cdecode.h - c header for a base64 decoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CDECODE_H 9 | #define BASE64_CDECODE_H 10 | 11 | typedef enum 12 | { 13 | step_a, step_b, step_c, step_d 14 | } base64_decodestep; 15 | 16 | typedef struct 17 | { 18 | base64_decodestep step; 19 | char plainchar; 20 | } base64_decodestate; 21 | 22 | void base64_init_decodestate(base64_decodestate* state_in); 23 | 24 | int base64_decode_value(char value_in); 25 | 26 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); 27 | 28 | #endif /* BASE64_CDECODE_H */ 29 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/cencode.c: -------------------------------------------------------------------------------- 1 | /* 2 | cencoder.c - c source to a base64 encoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifdef ESP8266 9 | #include 10 | #endif 11 | 12 | #if defined(ESP32) 13 | #define CORE_HAS_LIBB64 14 | #endif 15 | 16 | #ifndef CORE_HAS_LIBB64 17 | #include "cencode_inc.h" 18 | 19 | const int CHARS_PER_LINE = 72; 20 | 21 | void base64_init_encodestate(base64_encodestate* state_in) 22 | { 23 | state_in->step = step_A; 24 | state_in->result = 0; 25 | state_in->stepcount = 0; 26 | } 27 | 28 | char base64_encode_value(char value_in) 29 | { 30 | static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 31 | if (value_in > 63) return '='; 32 | return encoding[(int)value_in]; 33 | } 34 | 35 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) 36 | { 37 | const char* plainchar = plaintext_in; 38 | const char* const plaintextend = plaintext_in + length_in; 39 | char* codechar = code_out; 40 | char result; 41 | char fragment; 42 | 43 | result = state_in->result; 44 | 45 | switch (state_in->step) 46 | { 47 | while (1) 48 | { 49 | case step_A: 50 | if (plainchar == plaintextend) 51 | { 52 | state_in->result = result; 53 | state_in->step = step_A; 54 | return codechar - code_out; 55 | } 56 | fragment = *plainchar++; 57 | result = (fragment & 0x0fc) >> 2; 58 | *codechar++ = base64_encode_value(result); 59 | result = (fragment & 0x003) << 4; 60 | case step_B: 61 | if (plainchar == plaintextend) 62 | { 63 | state_in->result = result; 64 | state_in->step = step_B; 65 | return codechar - code_out; 66 | } 67 | fragment = *plainchar++; 68 | result |= (fragment & 0x0f0) >> 4; 69 | *codechar++ = base64_encode_value(result); 70 | result = (fragment & 0x00f) << 2; 71 | case step_C: 72 | if (plainchar == plaintextend) 73 | { 74 | state_in->result = result; 75 | state_in->step = step_C; 76 | return codechar - code_out; 77 | } 78 | fragment = *plainchar++; 79 | result |= (fragment & 0x0c0) >> 6; 80 | *codechar++ = base64_encode_value(result); 81 | result = (fragment & 0x03f) >> 0; 82 | *codechar++ = base64_encode_value(result); 83 | 84 | ++(state_in->stepcount); 85 | if (state_in->stepcount == CHARS_PER_LINE/4) 86 | { 87 | *codechar++ = '\n'; 88 | state_in->stepcount = 0; 89 | } 90 | } 91 | } 92 | /* control should not reach here */ 93 | return codechar - code_out; 94 | } 95 | 96 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in) 97 | { 98 | char* codechar = code_out; 99 | 100 | switch (state_in->step) 101 | { 102 | case step_B: 103 | *codechar++ = base64_encode_value(state_in->result); 104 | *codechar++ = '='; 105 | *codechar++ = '='; 106 | break; 107 | case step_C: 108 | *codechar++ = base64_encode_value(state_in->result); 109 | *codechar++ = '='; 110 | break; 111 | case step_A: 112 | break; 113 | } 114 | *codechar++ = 0x00; 115 | 116 | return codechar - code_out; 117 | } 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libb64/cencode_inc.h: -------------------------------------------------------------------------------- 1 | /* 2 | cencode.h - c header for a base64 encoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CENCODE_H 9 | #define BASE64_CENCODE_H 10 | 11 | typedef enum 12 | { 13 | step_A, step_B, step_C 14 | } base64_encodestep; 15 | 16 | typedef struct 17 | { 18 | base64_encodestep step; 19 | char result; 20 | int stepcount; 21 | } base64_encodestate; 22 | 23 | void base64_init_encodestate(base64_encodestate* state_in); 24 | 25 | char base64_encode_value(char value_in); 26 | 27 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); 28 | 29 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in); 30 | 31 | #endif /* BASE64_CENCODE_H */ 32 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/src/libsha1/libsha1.h: -------------------------------------------------------------------------------- 1 | /* ================ sha1.h ================ */ 2 | /* 3 | SHA-1 in C 4 | By Steve Reid 5 | 100% Public Domain 6 | */ 7 | 8 | #if !defined(ESP8266) && !defined(ESP32) 9 | 10 | typedef struct { 11 | uint32_t state[5]; 12 | uint32_t count[2]; 13 | unsigned char buffer[64]; 14 | } SHA1_CTX; 15 | 16 | void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]); 17 | void SHA1Init(SHA1_CTX* context); 18 | void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len); 19 | void SHA1Final(unsigned char digest[20], SHA1_CTX* context); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/tests/webSocket.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 40 | 41 | 42 | 43 | LED Control:
44 |
45 | R:
46 | G:
47 | B:
48 | 49 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/tests/webSocketServer/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var WebSocketServer = require('websocket').server; 3 | var http = require('http'); 4 | 5 | var server = http.createServer(function(request, response) { 6 | console.log((new Date()) + ' Received request for ' + request.url); 7 | response.writeHead(404); 8 | response.end(); 9 | }); 10 | server.listen(8011, function() { 11 | console.log((new Date()) + ' Server is listening on port 8011'); 12 | }); 13 | 14 | wsServer = new WebSocketServer({ 15 | httpServer: server, 16 | // You should not use autoAcceptConnections for production 17 | // applications, as it defeats all standard cross-origin protection 18 | // facilities built into the protocol and the browser. You should 19 | // *always* verify the connection's origin and decide whether or not 20 | // to accept it. 21 | autoAcceptConnections: false 22 | }); 23 | 24 | function originIsAllowed(origin) { 25 | // put logic here to detect whether the specified origin is allowed. 26 | return true; 27 | } 28 | 29 | wsServer.on('request', function(request) { 30 | 31 | if (!originIsAllowed(request.origin)) { 32 | // Make sure we only accept requests from an allowed origin 33 | request.reject(); 34 | console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.'); 35 | return; 36 | } 37 | 38 | var connection = request.accept('arduino', request.origin); 39 | console.log((new Date()) + ' Connection accepted.'); 40 | 41 | connection.on('message', function(message) { 42 | if (message.type === 'utf8') { 43 | console.log('Received Message: ' + message.utf8Data); 44 | // connection.sendUTF(message.utf8Data); 45 | } 46 | else if (message.type === 'binary') { 47 | console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); 48 | //connection.sendBytes(message.binaryData); 49 | } 50 | }); 51 | 52 | connection.on('close', function(reasonCode, description) { 53 | console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.'); 54 | }); 55 | 56 | connection.sendUTF("Hallo Client!"); 57 | }); 58 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/tests/webSocketServer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webSocketServer", 3 | "version": "1.0.0", 4 | "description": "WebSocketServer for testing", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Links2004/arduinoWebSockets" 12 | }, 13 | "keywords": [ 14 | "esp8266", 15 | "websocket", 16 | "arduino" 17 | ], 18 | "author": "Markus Sattler", 19 | "license": "LGPLv2", 20 | "bugs": { 21 | "url": "https://github.com/Links2004/arduinoWebSockets/issues" 22 | }, 23 | "homepage": "https://github.com/Links2004/arduinoWebSockets", 24 | "dependencies": { 25 | "websocket": "^1.0.18" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libraries/arduinoWebSockets-2.3.6/travis/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | function build_sketches() 6 | { 7 | local arduino=$1 8 | local srcpath=$2 9 | local platform=$3 10 | local sketches=$(find $srcpath -name *.ino) 11 | for sketch in $sketches; do 12 | local sketchdir=$(dirname $sketch) 13 | if [[ -f "$sketchdir/.$platform.skip" ]]; then 14 | echo -e "\n\n ------------ Skipping $sketch ------------ \n\n"; 15 | continue 16 | fi 17 | echo -e "\n\n ------------ Building $sketch ------------ \n\n"; 18 | $arduino --verify $sketch; 19 | local result=$? 20 | if [ $result -ne 0 ]; then 21 | echo "Build failed ($sketch) build verbose..." 22 | $arduino --verify --verbose --preserve-temp-files $sketch 23 | result=$? 24 | fi 25 | if [ $result -ne 0 ]; then 26 | echo "Build failed ($1) $sketch" 27 | return $result 28 | fi 29 | done 30 | } 31 | 32 | function build_sketch() 33 | { 34 | local arduino=$1 35 | local sketch=$2 36 | $arduino --verify $sketch; 37 | local result=$? 38 | if [ $result -ne 0 ]; then 39 | echo "Build failed ($sketch) build verbose..." 40 | $arduino --verify --verbose --preserve-temp-files $sketch 41 | result=$? 42 | fi 43 | if [ $result -ne 0 ]; then 44 | echo "Build failed ($1) $sketch" 45 | return $result 46 | fi 47 | } 48 | 49 | function get_sketches_json() 50 | { 51 | local arduino=$1 52 | local srcpath=$2 53 | local platform=$3 54 | local sketches=($(find $srcpath -name *.ino)) 55 | echo -en "[" 56 | for sketch in "${sketches[@]}" ; do 57 | local sketchdir=$(dirname $sketch) 58 | if [[ -f "$sketchdir/.$platform.skip" ]]; then 59 | continue 60 | fi 61 | echo -en "\"$sketch\"" 62 | if [[ $sketch != ${sketches[-1]} ]] ; then 63 | echo -en "," 64 | fi 65 | 66 | done 67 | echo -en "]" 68 | } 69 | 70 | function get_sketches_json_matrix() 71 | { 72 | local arduino=$1 73 | local srcpath=$2 74 | local platform=$3 75 | local ideversion=$4 76 | local board=$5 77 | local sketches=($(find $srcpath -name *.ino)) 78 | for sketch in "${sketches[@]}" ; do 79 | local sketchdir=$(dirname $sketch) 80 | local sketchname=$(basename $sketch) 81 | if [[ -f "$sketchdir/.$platform.skip" ]]; then 82 | continue 83 | fi 84 | echo -en "{\"name\":\"$sketchname\",\"board\":\"$board\",\"ideversion\":\"$ideversion\",\"cpu\":\"$platform\",\"sketch\":\"$sketch\"}" 85 | if [[ $sketch != ${sketches[-1]} ]] ; then 86 | echo -en "," 87 | fi 88 | done 89 | } 90 | 91 | function get_core() 92 | { 93 | echo Setup core for $1 94 | 95 | cd $HOME/arduino_ide/hardware 96 | 97 | if [ "$1" = "esp8266" ] ; then 98 | mkdir esp8266com 99 | cd esp8266com 100 | git clone --depth 1 https://github.com/esp8266/Arduino.git esp8266 101 | cd esp8266/ 102 | git submodule update --init 103 | rm -rf .git 104 | cd tools 105 | python get.py 106 | fi 107 | 108 | if [ "$1" = "esp32" ] ; then 109 | mkdir espressif 110 | cd espressif 111 | git clone --depth 1 https://github.com/espressif/arduino-esp32.git esp32 112 | cd esp32/ 113 | rm -rf .git 114 | cd tools 115 | python get.py 116 | fi 117 | 118 | } 119 | 120 | function clone_library() { 121 | local url=$1 122 | echo clone $(basename $url) 123 | mkdir -p $HOME/Arduino/libraries 124 | cd $HOME/Arduino/libraries 125 | git clone --depth 1 $url 126 | rm -rf */.git 127 | rm -rf */.github 128 | rm -rf */examples 129 | } 130 | 131 | function hash_library_names() { 132 | cd $HOME/Arduino/libraries 133 | ls | sha1sum -z | cut -c1-5 134 | } -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/.gitignore: -------------------------------------------------------------------------------- 1 | tests/bin 2 | .pioenvs 3 | .piolibdeps 4 | .clang_complete 5 | .gcc-flags.json 6 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: cpp 3 | compiler: 4 | - g++ 5 | script: cd tests && make && make test 6 | os: 7 | - linux 8 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/CHANGES.txt: -------------------------------------------------------------------------------- 1 | 2.8 2 | * Add setBufferSize() to override MQTT_MAX_PACKET_SIZE 3 | * Add setKeepAlive() to override MQTT_KEEPALIVE 4 | * Add setSocketTimeout() to overide MQTT_SOCKET_TIMEOUT 5 | * Added check to prevent subscribe/unsubscribe to empty topics 6 | * Declare wifi mode prior to connect in ESP example 7 | * Use `strnlen` to avoid overruns 8 | * Support pre-connected Client objects 9 | 10 | 2.7 11 | * Fix remaining-length handling to prevent buffer overrun 12 | * Add large-payload API - beginPublish/write/publish/endPublish 13 | * Add yield call to improve reliability on ESP 14 | * Add Clean Session flag to connect options 15 | * Add ESP32 support for functional callback signature 16 | * Various other fixes 17 | 18 | 2.4 19 | * Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely 20 | whilst waiting for inbound data 21 | * Fixed return code when publishing >256 bytes 22 | 23 | 2.3 24 | * Add publish(topic,payload,retained) function 25 | 26 | 2.2 27 | * Change code layout to match Arduino Library reqs 28 | 29 | 2.1 30 | * Add MAX_TRANSFER_SIZE def to chunk messages if needed 31 | * Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE 32 | 33 | 2.0 34 | * Add (and default to) MQTT 3.1.1 support 35 | * Fix PROGMEM handling for Intel Galileo/ESP8266 36 | * Add overloaded constructors for convenience 37 | * Add chainable setters for server/callback/client/stream 38 | * Add state function to return connack return code 39 | 40 | 1.9 41 | * Do not split MQTT packets over multiple calls to _client->write() 42 | * API change: All constructors now require an instance of Client 43 | to be passed in. 44 | * Fixed example to match 1.8 api changes - dpslwk 45 | * Added username/password support - WilHall 46 | * Added publish_P - publishes messages from PROGMEM - jobytaffey 47 | 48 | 1.8 49 | * KeepAlive interval is configurable in PubSubClient.h 50 | * Maximum packet size is configurable in PubSubClient.h 51 | * API change: Return boolean rather than int from various functions 52 | * API change: Length parameter in message callback changed 53 | from int to unsigned int 54 | * Various internal tidy-ups around types 55 | 1.7 56 | * Improved keepalive handling 57 | * Updated to the Arduino-1.0 API 58 | 1.6 59 | * Added the ability to publish a retained message 60 | 61 | 1.5 62 | * Added default constructor 63 | * Fixed compile error when used with arduino-0021 or later 64 | 65 | 1.4 66 | * Fixed connection lost handling 67 | 68 | 1.3 69 | * Fixed packet reading bug in PubSubClient.readPacket 70 | 71 | 1.2 72 | * Fixed compile error when used with arduino-0016 or later 73 | 74 | 75 | 1.1 76 | * Reduced size of library 77 | * Added support for Will messages 78 | * Clarified licensing - see LICENSE.txt 79 | 80 | 81 | 1.0 82 | * Only Quality of Service (QOS) 0 messaging is supported 83 | * The maximum message size, including header, is 128 bytes 84 | * The keepalive interval is set to 30 seconds 85 | * No support for Will messages 86 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2020 Nicholas O'Leary 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/README.md: -------------------------------------------------------------------------------- 1 | # Arduino Client for MQTT 2 | 3 | This library provides a client for doing simple publish/subscribe messaging with 4 | a server that supports MQTT. 5 | 6 | ## Examples 7 | 8 | The library comes with a number of example sketches. See File > Examples > PubSubClient 9 | within the Arduino application. 10 | 11 | Full API documentation is available here: https://pubsubclient.knolleary.net 12 | 13 | ## Limitations 14 | 15 | - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. 16 | - The maximum message size, including header, is **256 bytes** by default. This 17 | is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h` or can be changed 18 | by calling `PubSubClient::setBufferSize(size)`. 19 | - The keepalive interval is set to 15 seconds by default. This is configurable 20 | via `MQTT_KEEPALIVE` in `PubSubClient.h` or can be changed by calling 21 | `PubSubClient::setKeepAlive(keepAlive)`. 22 | - The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by 23 | changing value of `MQTT_VERSION` in `PubSubClient.h`. 24 | 25 | 26 | ## Compatible Hardware 27 | 28 | The library uses the Arduino Ethernet Client api for interacting with the 29 | underlying network hardware. This means it Just Works with a growing number of 30 | boards and shields, including: 31 | 32 | - Arduino Ethernet 33 | - Arduino Ethernet Shield 34 | - Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and 35 | be sure to do a `Bridge.begin()` first 36 | - Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield, 37 | enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`. 38 | - Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly) 39 | - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) 40 | - Intel Galileo/Edison 41 | - ESP8266 42 | - ESP32 43 | 44 | The library cannot currently be used with hardware based on the ENC28J60 chip – 45 | such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an 46 | [alternative library](https://github.com/njh/NanodeMQTT) available. 47 | 48 | ## License 49 | 50 | This code is released under the MIT License. 51 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/examples/mqtt_auth/mqtt_auth.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic MQTT example with Authentication 3 | 4 | - connects to an MQTT server, providing username 5 | and password 6 | - publishes "hello world" to the topic "outTopic" 7 | - subscribes to the topic "inTopic" 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // Update these with values suitable for your network. 15 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 16 | IPAddress ip(172, 16, 0, 100); 17 | IPAddress server(172, 16, 0, 2); 18 | 19 | void callback(char* topic, byte* payload, unsigned int length) { 20 | // handle message arrived 21 | } 22 | 23 | EthernetClient ethClient; 24 | PubSubClient client(server, 1883, callback, ethClient); 25 | 26 | void setup() 27 | { 28 | Ethernet.begin(mac, ip); 29 | // Note - the default maximum packet size is 128 bytes. If the 30 | // combined length of clientId, username and password exceed this use the 31 | // following to increase the buffer size: 32 | // client.setBufferSize(255); 33 | 34 | if (client.connect("arduinoClient", "testuser", "testpass")) { 35 | client.publish("outTopic","hello world"); 36 | client.subscribe("inTopic"); 37 | } 38 | } 39 | 40 | void loop() 41 | { 42 | client.loop(); 43 | } 44 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/examples/mqtt_basic/mqtt_basic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic MQTT example 3 | 4 | This sketch demonstrates the basic capabilities of the library. 5 | It connects to an MQTT server then: 6 | - publishes "hello world" to the topic "outTopic" 7 | - subscribes to the topic "inTopic", printing out any messages 8 | it receives. NB - it assumes the received payloads are strings not binary 9 | 10 | It will reconnect to the server if the connection is lost using a blocking 11 | reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to 12 | achieve the same result without blocking the main loop. 13 | 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | // Update these with values suitable for your network. 21 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 22 | IPAddress ip(172, 16, 0, 100); 23 | IPAddress server(172, 16, 0, 2); 24 | 25 | void callback(char* topic, byte* payload, unsigned int length) { 26 | Serial.print("Message arrived ["); 27 | Serial.print(topic); 28 | Serial.print("] "); 29 | for (int i=0;i Preferences -> Additional Boards Manager URLs": 16 | http://arduino.esp8266.com/stable/package_esp8266com_index.json 17 | - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" 18 | - Select your ESP8266 in "Tools -> Board" 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | // Update these with values suitable for your network. 25 | 26 | const char* ssid = "........"; 27 | const char* password = "........"; 28 | const char* mqtt_server = "broker.mqtt-dashboard.com"; 29 | 30 | WiFiClient espClient; 31 | PubSubClient client(espClient); 32 | unsigned long lastMsg = 0; 33 | #define MSG_BUFFER_SIZE (50) 34 | char msg[MSG_BUFFER_SIZE]; 35 | int value = 0; 36 | 37 | void setup_wifi() { 38 | 39 | delay(10); 40 | // We start by connecting to a WiFi network 41 | Serial.println(); 42 | Serial.print("Connecting to "); 43 | Serial.println(ssid); 44 | 45 | WiFi.mode(WIFI_STA); 46 | WiFi.begin(ssid, password); 47 | 48 | while (WiFi.status() != WL_CONNECTED) { 49 | delay(500); 50 | Serial.print("."); 51 | } 52 | 53 | randomSeed(micros()); 54 | 55 | Serial.println(""); 56 | Serial.println("WiFi connected"); 57 | Serial.println("IP address: "); 58 | Serial.println(WiFi.localIP()); 59 | } 60 | 61 | void callback(char* topic, byte* payload, unsigned int length) { 62 | Serial.print("Message arrived ["); 63 | Serial.print(topic); 64 | Serial.print("] "); 65 | for (int i = 0; i < length; i++) { 66 | Serial.print((char)payload[i]); 67 | } 68 | Serial.println(); 69 | 70 | // Switch on the LED if an 1 was received as first character 71 | if ((char)payload[0] == '1') { 72 | digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level 73 | // but actually the LED is on; this is because 74 | // it is active low on the ESP-01) 75 | } else { 76 | digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH 77 | } 78 | 79 | } 80 | 81 | void reconnect() { 82 | // Loop until we're reconnected 83 | while (!client.connected()) { 84 | Serial.print("Attempting MQTT connection..."); 85 | // Create a random client ID 86 | String clientId = "ESP8266Client-"; 87 | clientId += String(random(0xffff), HEX); 88 | // Attempt to connect 89 | if (client.connect(clientId.c_str())) { 90 | Serial.println("connected"); 91 | // Once connected, publish an announcement... 92 | client.publish("outTopic", "hello world"); 93 | // ... and resubscribe 94 | client.subscribe("inTopic"); 95 | } else { 96 | Serial.print("failed, rc="); 97 | Serial.print(client.state()); 98 | Serial.println(" try again in 5 seconds"); 99 | // Wait 5 seconds before retrying 100 | delay(5000); 101 | } 102 | } 103 | } 104 | 105 | void setup() { 106 | pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output 107 | Serial.begin(115200); 108 | setup_wifi(); 109 | client.setServer(mqtt_server, 1883); 110 | client.setCallback(callback); 111 | } 112 | 113 | void loop() { 114 | 115 | if (!client.connected()) { 116 | reconnect(); 117 | } 118 | client.loop(); 119 | 120 | unsigned long now = millis(); 121 | if (now - lastMsg > 2000) { 122 | lastMsg = now; 123 | ++value; 124 | snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value); 125 | Serial.print("Publish message: "); 126 | Serial.println(msg); 127 | client.publish("outTopic", msg); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Publishing in the callback 3 | 4 | - connects to an MQTT server 5 | - subscribes to the topic "inTopic" 6 | - when a message is received, republishes it to "outTopic" 7 | 8 | This example shows how to publish messages within the 9 | callback function. The callback function header needs to 10 | be declared before the PubSubClient constructor and the 11 | actual callback defined afterwards. 12 | This ensures the client reference in the callback function 13 | is valid. 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | // Update these with values suitable for your network. 22 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 23 | IPAddress ip(172, 16, 0, 100); 24 | IPAddress server(172, 16, 0, 2); 25 | 26 | // Callback function header 27 | void callback(char* topic, byte* payload, unsigned int length); 28 | 29 | EthernetClient ethClient; 30 | PubSubClient client(server, 1883, callback, ethClient); 31 | 32 | // Callback function 33 | void callback(char* topic, byte* payload, unsigned int length) { 34 | // In order to republish this payload, a copy must be made 35 | // as the orignal payload buffer will be overwritten whilst 36 | // constructing the PUBLISH packet. 37 | 38 | // Allocate the correct amount of memory for the payload copy 39 | byte* p = (byte*)malloc(length); 40 | // Copy the payload to the new buffer 41 | memcpy(p,payload,length); 42 | client.publish("outTopic", p, length); 43 | // Free the memory 44 | free(p); 45 | } 46 | 47 | void setup() 48 | { 49 | 50 | Ethernet.begin(mac, ip); 51 | if (client.connect("arduinoClient")) { 52 | client.publish("outTopic","hello world"); 53 | client.subscribe("inTopic"); 54 | } 55 | } 56 | 57 | void loop() 58 | { 59 | client.loop(); 60 | } 61 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reconnecting MQTT example - non-blocking 3 | 4 | This sketch demonstrates how to keep the client connected 5 | using a non-blocking reconnect function. If the client loses 6 | its connection, it attempts to reconnect every 5 seconds 7 | without blocking the main loop. 8 | 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Update these with values suitable for your hardware/network. 16 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 17 | IPAddress ip(172, 16, 0, 100); 18 | IPAddress server(172, 16, 0, 2); 19 | 20 | void callback(char* topic, byte* payload, unsigned int length) { 21 | // handle message arrived 22 | } 23 | 24 | EthernetClient ethClient; 25 | PubSubClient client(ethClient); 26 | 27 | long lastReconnectAttempt = 0; 28 | 29 | boolean reconnect() { 30 | if (client.connect("arduinoClient")) { 31 | // Once connected, publish an announcement... 32 | client.publish("outTopic","hello world"); 33 | // ... and resubscribe 34 | client.subscribe("inTopic"); 35 | } 36 | return client.connected(); 37 | } 38 | 39 | void setup() 40 | { 41 | client.setServer(server, 1883); 42 | client.setCallback(callback); 43 | 44 | Ethernet.begin(mac, ip); 45 | delay(1500); 46 | lastReconnectAttempt = 0; 47 | } 48 | 49 | 50 | void loop() 51 | { 52 | if (!client.connected()) { 53 | long now = millis(); 54 | if (now - lastReconnectAttempt > 5000) { 55 | lastReconnectAttempt = now; 56 | // Attempt to reconnect 57 | if (reconnect()) { 58 | lastReconnectAttempt = 0; 59 | } 60 | } 61 | } else { 62 | // Client connected 63 | 64 | client.loop(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/examples/mqtt_stream/mqtt_stream.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example of using a Stream object to store the message payload 3 | 4 | Uses SRAM library: https://github.com/ennui2342/arduino-sram 5 | but could use any Stream based class such as SD 6 | 7 | - connects to an MQTT server 8 | - publishes "hello world" to the topic "outTopic" 9 | - subscribes to the topic "inTopic" 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // Update these with values suitable for your network. 18 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 19 | IPAddress ip(172, 16, 0, 100); 20 | IPAddress server(172, 16, 0, 2); 21 | 22 | SRAM sram(4, SRAM_1024); 23 | 24 | void callback(char* topic, byte* payload, unsigned int length) { 25 | sram.seek(1); 26 | 27 | // do something with the message 28 | for(uint8_t i=0; i 4 | maintainer=Nick O'Leary 5 | sentence=A client library for MQTT messaging. 6 | paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It supports the latest MQTT 3.1.1 protocol and can be configured to use the older MQTT 3.1 if needed. It supports all Arduino Ethernet Client compatible hardware, including the Intel Galileo/Edison, ESP8266 and TI CC3000. 7 | category=Communication 8 | url=http://pubsubclient.knolleary.net 9 | architectures=* 10 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | tmpbin 3 | logs 4 | *.pyc 5 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/Makefile: -------------------------------------------------------------------------------- 1 | SRC_PATH=./src 2 | OUT_PATH=./bin 3 | TEST_SRC=$(wildcard ${SRC_PATH}/*_spec.cpp) 4 | TEST_BIN= $(TEST_SRC:${SRC_PATH}/%.cpp=${OUT_PATH}/%) 5 | VPATH=${SRC_PATH} 6 | SHIM_FILES=${SRC_PATH}/lib/*.cpp 7 | PSC_FILE=../src/PubSubClient.cpp 8 | CC=g++ 9 | CFLAGS=-I${SRC_PATH}/lib -I../src 10 | 11 | all: $(TEST_BIN) 12 | 13 | ${OUT_PATH}/%: ${SRC_PATH}/%.cpp ${PSC_FILE} ${SHIM_FILES} 14 | mkdir -p ${OUT_PATH} 15 | ${CC} ${CFLAGS} $^ -o $@ 16 | 17 | clean: 18 | @rm -rf ${OUT_PATH} 19 | 20 | test: 21 | @bin/connect_spec 22 | @bin/publish_spec 23 | @bin/receive_spec 24 | @bin/subscribe_spec 25 | @bin/keepalive_spec 26 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/README.md: -------------------------------------------------------------------------------- 1 | # Arduino Client for MQTT Test Suite 2 | 3 | This is a regression test suite for the `PubSubClient` library. 4 | 5 | There are two parts: 6 | 7 | - Tests that can be compiled and run on any machine 8 | - Tests that build the example sketches using the Arduino IDE 9 | 10 | 11 | It is a work-in-progress and is subject to complete refactoring as the whim takes 12 | me. 13 | 14 | 15 | ## Local tests 16 | 17 | These are a set of executables that can be run to test specific areas of functionality. 18 | They do not require a real Arduino to be attached, nor the use of the Arduino IDE. 19 | 20 | The tests include a set of mock files to stub out the parts of the Arduino environment the library 21 | depends on. 22 | 23 | ### Dependencies 24 | 25 | - g++ 26 | 27 | ### Running 28 | 29 | Build the tests using the provided `Makefile`: 30 | 31 | $ make 32 | 33 | This will create a set of executables in `./bin/`. Run each of these executables to test the corresponding functionality. 34 | 35 | *Note:* the `connect_spec` and `keepalive_spec` tests involve testing keepalive timers so naturally take a few minutes to run through. 36 | 37 | ## Arduino tests 38 | 39 | *Note:* INO Tool doesn't currently play nicely with Arduino 1.5. This has broken this test suite. 40 | 41 | Without a suitable arduino plugged in, the test suite will only check the 42 | example sketches compile cleanly against the library. 43 | 44 | With an arduino plugged in, each sketch that has a corresponding python 45 | test case is built, uploaded and then the tests run. 46 | 47 | ### Dependencies 48 | 49 | - Python 2.7+ 50 | - [INO Tool](http://inotool.org/) - this provides command-line build/upload of Arduino sketches 51 | 52 | ### Running 53 | 54 | The test suite _does not_ run an MQTT server - it is assumed to be running already. 55 | 56 | $ python testsuite.py 57 | 58 | A summary of activity is printed to the console. More comprehensive logs are written 59 | to the `logs` directory. 60 | 61 | ### What it does 62 | 63 | For each sketch in the library's `examples` directory, e.g. `mqtt_basic.ino`, the suite looks for a matching test case 64 | `testcases/mqtt_basic.py`. 65 | 66 | The test case must follow these conventions: 67 | - sub-class `unittest.TestCase` 68 | - provide the class methods `setUpClass` and `tearDownClass` (TODO: make this optional) 69 | - all test method names begin with `test_` 70 | 71 | The suite will call the `setUpClass` method _before_ uploading the sketch. This 72 | allows any test setup to be performed before the sketch runs - such as connecting 73 | a client and subscribing to topics. 74 | 75 | 76 | ### Settings 77 | 78 | The file `testcases/settings.py` is used to config the test environment. 79 | 80 | - `server_ip` - the IP address of the broker the client should connect to (the broker port is assumed to be 1883). 81 | - `arduino_ip` - the IP address the arduino should use (when not testing DHCP). 82 | 83 | Before each sketch is compiled, these values are automatically substituted in. To 84 | do this, the suite looks for lines that _start_ with the following: 85 | 86 | byte server[] = { 87 | byte ip[] = { 88 | 89 | and replaces them with the appropriate values. 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef Arduino_h 2 | #define Arduino_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Print.h" 9 | 10 | 11 | extern "C"{ 12 | typedef uint8_t byte ; 13 | typedef uint8_t boolean ; 14 | 15 | /* sketch */ 16 | extern void setup( void ) ; 17 | extern void loop( void ) ; 18 | uint32_t millis( void ); 19 | } 20 | 21 | #define PROGMEM 22 | #define pgm_read_byte_near(x) *(x) 23 | 24 | #define yield(x) {} 25 | 26 | #endif // Arduino_h 27 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/BDDTest.cpp: -------------------------------------------------------------------------------- 1 | #include "BDDTest.h" 2 | #include "trace.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int testCount = 0; 9 | int testPasses = 0; 10 | const char* testDescription; 11 | 12 | std::list failureList; 13 | 14 | void bddtest_suite(const char* name) { 15 | LOG(name << "\n"); 16 | } 17 | 18 | int bddtest_test(const char* file, int line, const char* assertion, int result) { 19 | if (!result) { 20 | LOG("✗\n"); 21 | std::ostringstream os; 22 | os << " ! "<::iterator it = failureList.begin(); it != failureList.end(); it++) { 40 | LOG("\n"); 41 | LOG(*it); 42 | LOG("\n"); 43 | } 44 | 45 | LOG(std::dec << testPasses << "/" << testCount << " tests passed\n\n"); 46 | if (testPasses == testCount) { 47 | return 0; 48 | } 49 | return 1; 50 | } 51 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/BDDTest.h: -------------------------------------------------------------------------------- 1 | #ifndef bddtest_h 2 | #define bddtest_h 3 | 4 | void bddtest_suite(const char* name); 5 | int bddtest_test(const char*, int, const char*, int); 6 | void bddtest_start(const char*); 7 | void bddtest_end(); 8 | int bddtest_summary(); 9 | 10 | #define SUITE(x) { bddtest_suite(x); } 11 | #define TEST(x) { if (!bddtest_test(__FILE__, __LINE__, #x, (x))) return false; } 12 | 13 | #define IT(x) { bddtest_start(x); } 14 | #define END_IT { bddtest_end();return true;} 15 | 16 | #define FINISH { return bddtest_summary(); } 17 | 18 | #define IS_TRUE(x) TEST(x) 19 | #define IS_FALSE(x) TEST(!(x)) 20 | #define IS_EQUAL(x,y) TEST(x==y) 21 | #define IS_NOT_EQUAL(x,y) TEST(x!=y) 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | #include "Arduino.h" 3 | 4 | Buffer::Buffer() { 5 | this->pos = 0; 6 | this->length = 0; 7 | } 8 | 9 | Buffer::Buffer(uint8_t* buf, size_t size) { 10 | this->pos = 0; 11 | this->length = 0; 12 | this->add(buf,size); 13 | } 14 | bool Buffer::available() { 15 | return this->pos < this->length; 16 | } 17 | 18 | uint8_t Buffer::next() { 19 | if (this->available()) { 20 | return this->buffer[this->pos++]; 21 | } 22 | return 0; 23 | } 24 | 25 | void Buffer::reset() { 26 | this->pos = 0; 27 | } 28 | 29 | void Buffer::add(uint8_t* buf, size_t size) { 30 | uint16_t i = 0; 31 | for (;ibuffer[this->length++] = buf[i]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef buffer_h 2 | #define buffer_h 3 | 4 | #include "Arduino.h" 5 | 6 | class Buffer { 7 | private: 8 | uint8_t buffer[2048]; 9 | uint16_t pos; 10 | uint16_t length; 11 | 12 | public: 13 | Buffer(); 14 | Buffer(uint8_t* buf, size_t size); 15 | 16 | virtual bool available(); 17 | virtual uint8_t next(); 18 | virtual void reset(); 19 | 20 | virtual void add(uint8_t* buf, size_t size); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Client.h: -------------------------------------------------------------------------------- 1 | #ifndef client_h 2 | #define client_h 3 | #include "IPAddress.h" 4 | 5 | class Client { 6 | public: 7 | virtual int connect(IPAddress ip, uint16_t port) =0; 8 | virtual int connect(const char *host, uint16_t port) =0; 9 | virtual size_t write(uint8_t) =0; 10 | virtual size_t write(const uint8_t *buf, size_t size) =0; 11 | virtual int available() = 0; 12 | virtual int read() = 0; 13 | virtual int read(uint8_t *buf, size_t size) = 0; 14 | virtual int peek() = 0; 15 | virtual void flush() = 0; 16 | virtual void stop() = 0; 17 | virtual uint8_t connected() = 0; 18 | virtual operator bool() = 0; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/IPAddress.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | IPAddress::IPAddress() 6 | { 7 | memset(_address, 0, sizeof(_address)); 8 | } 9 | 10 | IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) 11 | { 12 | _address[0] = first_octet; 13 | _address[1] = second_octet; 14 | _address[2] = third_octet; 15 | _address[3] = fourth_octet; 16 | } 17 | 18 | IPAddress::IPAddress(uint32_t address) 19 | { 20 | memcpy(_address, &address, sizeof(_address)); 21 | } 22 | 23 | IPAddress::IPAddress(const uint8_t *address) 24 | { 25 | memcpy(_address, address, sizeof(_address)); 26 | } 27 | 28 | IPAddress& IPAddress::operator=(const uint8_t *address) 29 | { 30 | memcpy(_address, address, sizeof(_address)); 31 | return *this; 32 | } 33 | 34 | IPAddress& IPAddress::operator=(uint32_t address) 35 | { 36 | memcpy(_address, (const uint8_t *)&address, sizeof(_address)); 37 | return *this; 38 | } 39 | 40 | bool IPAddress::operator==(const uint8_t* addr) 41 | { 42 | return memcmp(addr, _address, sizeof(_address)) == 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/IPAddress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * MIT License: 4 | * Copyright (c) 2011 Adrian McEwen 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | * 23 | * adrianm@mcqn.com 1/1/2011 24 | */ 25 | 26 | #ifndef IPAddress_h 27 | #define IPAddress_h 28 | 29 | 30 | // A class to make it easier to handle and pass around IP addresses 31 | 32 | class IPAddress { 33 | private: 34 | uint8_t _address[4]; // IPv4 address 35 | // Access the raw byte array containing the address. Because this returns a pointer 36 | // to the internal structure rather than a copy of the address this function should only 37 | // be used when you know that the usage of the returned uint8_t* will be transient and not 38 | // stored. 39 | uint8_t* raw_address() { return _address; }; 40 | 41 | public: 42 | // Constructors 43 | IPAddress(); 44 | IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); 45 | IPAddress(uint32_t address); 46 | IPAddress(const uint8_t *address); 47 | 48 | // Overloaded cast operator to allow IPAddress objects to be used where a pointer 49 | // to a four-byte uint8_t array is expected 50 | operator uint32_t() { return *((uint32_t*)_address); }; 51 | bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; 52 | bool operator==(const uint8_t* addr); 53 | 54 | // Overloaded index operator to allow getting and setting individual octets of the address 55 | uint8_t operator[](int index) const { return _address[index]; }; 56 | uint8_t& operator[](int index) { return _address[index]; }; 57 | 58 | // Overloaded copy operators to allow initialisation of IPAddress objects from other types 59 | IPAddress& operator=(const uint8_t *address); 60 | IPAddress& operator=(uint32_t address); 61 | 62 | 63 | friend class EthernetClass; 64 | friend class UDP; 65 | friend class Client; 66 | friend class Server; 67 | friend class DhcpClass; 68 | friend class DNSClient; 69 | }; 70 | 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Print.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print.h - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Print_h 21 | #define Print_h 22 | 23 | class Print { 24 | public: 25 | virtual size_t write(uint8_t) = 0; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/ShimClient.h: -------------------------------------------------------------------------------- 1 | #ifndef shimclient_h 2 | #define shimclient_h 3 | 4 | #include "Arduino.h" 5 | #include "Client.h" 6 | #include "IPAddress.h" 7 | #include "Buffer.h" 8 | 9 | 10 | class ShimClient : public Client { 11 | private: 12 | Buffer* responseBuffer; 13 | Buffer* expectBuffer; 14 | bool _allowConnect; 15 | bool _connected; 16 | bool expectAnything; 17 | bool _error; 18 | uint16_t _received; 19 | IPAddress _expectedIP; 20 | uint16_t _expectedPort; 21 | const char* _expectedHost; 22 | 23 | public: 24 | ShimClient(); 25 | virtual int connect(IPAddress ip, uint16_t port); 26 | virtual int connect(const char *host, uint16_t port); 27 | virtual size_t write(uint8_t); 28 | virtual size_t write(const uint8_t *buf, size_t size); 29 | virtual int available(); 30 | virtual int read(); 31 | virtual int read(uint8_t *buf, size_t size); 32 | virtual int peek(); 33 | virtual void flush(); 34 | virtual void stop(); 35 | virtual uint8_t connected(); 36 | virtual operator bool(); 37 | 38 | virtual ShimClient* respond(uint8_t *buf, size_t size); 39 | virtual ShimClient* expect(uint8_t *buf, size_t size); 40 | 41 | virtual void expectConnect(IPAddress ip, uint16_t port); 42 | virtual void expectConnect(const char *host, uint16_t port); 43 | 44 | virtual uint16_t received(); 45 | virtual bool error(); 46 | 47 | virtual void setAllowConnect(bool b); 48 | virtual void setConnected(bool b); 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Stream.cpp: -------------------------------------------------------------------------------- 1 | #include "Stream.h" 2 | #include "trace.h" 3 | #include 4 | #include 5 | 6 | Stream::Stream() { 7 | this->expectBuffer = new Buffer(); 8 | this->_error = false; 9 | this->_written = 0; 10 | } 11 | 12 | size_t Stream::write(uint8_t b) { 13 | this->_written++; 14 | TRACE(std::hex << (unsigned int)b); 15 | if (this->expectBuffer->available()) { 16 | uint8_t expected = this->expectBuffer->next(); 17 | if (expected != b) { 18 | this->_error = true; 19 | TRACE("!=" << (unsigned int)expected); 20 | } 21 | } else { 22 | this->_error = true; 23 | } 24 | TRACE("\n"<< std::dec); 25 | return 1; 26 | } 27 | 28 | 29 | bool Stream::error() { 30 | return this->_error; 31 | } 32 | 33 | void Stream::expect(uint8_t *buf, size_t size) { 34 | this->expectBuffer->add(buf,size); 35 | } 36 | 37 | uint16_t Stream::length() { 38 | return this->_written; 39 | } 40 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/Stream.h: -------------------------------------------------------------------------------- 1 | #ifndef Stream_h 2 | #define Stream_h 3 | 4 | #include "Arduino.h" 5 | #include "Buffer.h" 6 | 7 | class Stream { 8 | private: 9 | Buffer* expectBuffer; 10 | bool _error; 11 | uint16_t _written; 12 | 13 | public: 14 | Stream(); 15 | virtual size_t write(uint8_t); 16 | 17 | virtual bool error(); 18 | virtual void expect(uint8_t *buf, size_t size); 19 | virtual uint16_t length(); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/src/lib/trace.h: -------------------------------------------------------------------------------- 1 | #ifndef trace_h 2 | #define trace_h 3 | #include 4 | 5 | #include 6 | 7 | #define LOG(x) {std::cout << x << std::flush; } 8 | #define TRACE(x) {if (getenv("TRACE")) { std::cout << x << std::flush; }} 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/testcases/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGyver/TachoLED/af7504a83dde779187af78d57a48e02772c97df3/libraries/pubsubclient-2.8/tests/testcases/__init__.py -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/testcases/mqtt_basic.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import settings 3 | import time 4 | import mosquitto 5 | 6 | 7 | def on_message(mosq, obj, msg): 8 | obj.message_queue.append(msg) 9 | 10 | 11 | class mqtt_basic(unittest.TestCase): 12 | 13 | message_queue = [] 14 | 15 | @classmethod 16 | def setUpClass(self): 17 | self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) 18 | self.client.connect(settings.server_ip) 19 | self.client.on_message = on_message 20 | self.client.subscribe("outTopic", 0) 21 | 22 | @classmethod 23 | def tearDownClass(self): 24 | self.client.disconnect() 25 | 26 | def test_one(self): 27 | i = 30 28 | while len(self.message_queue) == 0 and i > 0: 29 | self.client.loop() 30 | time.sleep(0.5) 31 | i -= 1 32 | self.assertTrue(i > 0, "message receive timed-out") 33 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 34 | msg = self.message_queue[0] 35 | self.assertEqual(msg.mid, 0, "message id not 0") 36 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 37 | self.assertEqual(msg.payload, "hello world") 38 | self.assertEqual(msg.qos, 0, "message qos not 0") 39 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 40 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/testcases/mqtt_publish_in_callback.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import settings 3 | import time 4 | import mosquitto 5 | 6 | 7 | def on_message(mosq, obj, msg): 8 | obj.message_queue.append(msg) 9 | 10 | 11 | class mqtt_publish_in_callback(unittest.TestCase): 12 | 13 | message_queue = [] 14 | 15 | @classmethod 16 | def setUpClass(self): 17 | self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) 18 | self.client.connect(settings.server_ip) 19 | self.client.on_message = on_message 20 | self.client.subscribe("outTopic", 0) 21 | 22 | @classmethod 23 | def tearDownClass(self): 24 | self.client.disconnect() 25 | 26 | def test_connect(self): 27 | i = 30 28 | while len(self.message_queue) == 0 and i > 0: 29 | self.client.loop() 30 | time.sleep(0.5) 31 | i -= 1 32 | self.assertTrue(i > 0, "message receive timed-out") 33 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 34 | msg = self.message_queue.pop(0) 35 | self.assertEqual(msg.mid, 0, "message id not 0") 36 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 37 | self.assertEqual(msg.payload, "hello world") 38 | self.assertEqual(msg.qos, 0, "message qos not 0") 39 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 40 | 41 | def test_publish(self): 42 | self.assertEqual(len(self.message_queue), 0, "message queue not empty") 43 | payload = "abcdefghij" 44 | self.client.publish("inTopic", payload) 45 | 46 | i = 30 47 | while len(self.message_queue) == 0 and i > 0: 48 | self.client.loop() 49 | time.sleep(0.5) 50 | i -= 1 51 | 52 | self.assertTrue(i > 0, "message receive timed-out") 53 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 54 | msg = self.message_queue.pop(0) 55 | self.assertEqual(msg.mid, 0, "message id not 0") 56 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 57 | self.assertEqual(msg.payload, payload) 58 | self.assertEqual(msg.qos, 0, "message qos not 0") 59 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 60 | -------------------------------------------------------------------------------- /libraries/pubsubclient-2.8/tests/testcases/settings.py: -------------------------------------------------------------------------------- 1 | server_ip = "172.16.0.2" 2 | arduino_ip = "172.16.0.100" 3 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TachoLED", 3 | "about": "Динамическая подсветка скейтборда", 4 | "version": "1.0", 5 | "notes": "Релиз", 6 | "builds": [ 7 | { 8 | "chipFamily": "ESP8266", 9 | "parts": [ 10 | { 11 | "path": "https://raw.githubusercontent.com/AlexGyver/TachoLED/main/bin/firmware.bin", 12 | "offset": 0 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /schemes/scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGyver/TachoLED/af7504a83dde779187af78d57a48e02772c97df3/schemes/scheme.png --------------------------------------------------------------------------------