ci(wokwi): Add Wokwi emulator to workflow (#9540)

* ci(wokwi): Add wokwi emulator to CI

* feat(wokwi): Support scenario

* feat(wokwi): Add simple CI test for push button

* sudo apt command

* sudo both apt commands

* Add missing test.py file

* Test pytest path changes

* empty push

* move wokwi cli token variable

* move token back to wokwi job

* Update hil.yml

* Update hil.yml

* revert run on pr

* run on PR target

* run only on master

* ci(wokwi): Support wokwi

* ci(wokwi): Skip unsupported and performance test

* ci(wokwi): run wokwi tests without label

* debug: run build on windows

* RUN WIFI WITH PSRAM ON-OFF

* fix psram for S3

* Revert "debug: run build on windows"

This reverts commit bc085e5050.

* ci(wokwi): Run workflow only if build was sucessful

* ci(pre-commit): Apply automatic fixes

* ci(wokwi): Add generated files to gitignore

---------

Co-authored-by: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
Lucas Saavedra Vaz 2024-05-07 12:46:19 -03:00 committed by GitHub
parent b59a3687c2
commit 789b1a8425
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 510 additions and 18 deletions

View File

@ -8,6 +8,11 @@ function run_test() {
local sketchdir=$(dirname $sketch)
local sketchname=$(basename $sketchdir)
if [[ -f "$sketchdir/.skip.$platform" ]]; then
echo "Skipping $sketchname test in $target"
exit 0
fi
if [ $options -eq 0 ] && [ -f $sketchdir/cfg.json ]; then
len=`jq -r --arg chip $target '.targets[] | select(.name==$chip) | .fqbn | length' $sketchdir/cfg.json`
else
@ -33,7 +38,16 @@ function run_test() {
report_file="$sketchdir/$sketchname$i.xml"
fi
pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file
if [ $platform == "wokwi" ]; then
extra_args="--target $target --embedded-services arduino,wokwi --wokwi-timeout=$wokwi_timeout"
if [[ -f "$sketchdir/scenario.yaml" ]]; then
extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml"
fi
else
extra_args="--embedded-services esp,arduino"
fi
pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args
result=$?
if [ $result -ne 0 ]; then
return $result
@ -44,6 +58,8 @@ function run_test() {
SCRIPTS_DIR="./.github/scripts"
COUNT_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh count"
platform="hardware"
wokwi_timeout=60000
chunk_run=0
options=0
erase=0
@ -53,6 +69,11 @@ while [ ! -z "$1" ]; do
-c )
chunk_run=1
;;
-w )
shift
wokwi_timeout=$1
platform="wokwi"
;;
-o )
options=1
;;

View File

@ -1,4 +1,4 @@
name: Run tests in hardware
name: Run tests
on:
pull_request:
@ -9,6 +9,8 @@ on:
env:
MAX_CHUNKS: 15
WOKWI_TIMEOUT: 120000 # Milliseconds
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
concurrency:
group: hil-${{github.event.pull_request.number || github.ref}}
@ -17,8 +19,7 @@ concurrency:
jobs:
gen_chunks:
if: |
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
contains(github.event.pull_request.labels.*.name, 'perf_test') ||
github.event_name == 'pull_request' ||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
name: Generate Chunks matrix
runs-on: ubuntu-latest
@ -58,7 +59,7 @@ jobs:
echo "test_folder=${test_folder}" >> $GITHUB_OUTPUT
echo "test_type=${test_type}" >> $GITHUB_OUTPUT
Build:
build:
needs: gen_chunks
name: ${{matrix.chip}}-Build#${{matrix.chunks}}
runs-on: ubuntu-latest
@ -82,11 +83,65 @@ jobs:
path: |
~/.build_skipped
~/.arduino/tests/**/build*.tmp/*.bin
~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/**/build*.tmp/*.json
Test:
needs: [gen_chunks, Build]
name: ${{matrix.chip}}-Test#${{matrix.chunks}}
wokwi-test:
needs: [gen_chunks, build]
if: github.event_name == 'schedule'
name: ${{matrix.chip}}-Wokwi_Test#${{matrix.chunks}}
strategy:
fail-fast: false
matrix:
chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download ${{matrix.chip}}-${{matrix.chunks}} artifacts
uses: actions/download-artifact@v4
with:
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
path: ~/
- name: Install Wokwi CLI
run: curl -L https://wokwi.com/ci/install.sh | sh
- name: Install dependencies
run: |
pip install -U pip
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
sudo apt update && sudo apt install -y -qq jq
- name: Run Tests
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -w ${{env.WOKWI_TIMEOUT}}
- name: Check if tests were skipped
id: check-test-skipped
run: |
if [ -f ~/.test_skipped ]; then
echo "skipped=true" >> $GITHUB_OUTPUT
else
echo "skipped=false" >> $GITHUB_OUTPUT
fi
- name: Upload test result artifacts
uses: actions/upload-artifact@v4
if: ${{ always() && steps.check-test-skipped.outputs.skipped == 'false' }}
with:
name: wokwi_results-${{matrix.chip}}-${{matrix.chunks}}
path: tests/**/*.xml
hardware-test:
needs: [gen_chunks, build]
name: ${{matrix.chip}}-Hardware_Test#${{matrix.chunks}}
if: |
contains(github.event.pull_request.labels.*.name, 'hil_test') || github.event_name == 'schedule'
strategy:
fail-fast: false
matrix:
@ -130,7 +185,7 @@ jobs:
uses: actions/upload-artifact@v4
if: ${{ always() && steps.check-test-skipped.outputs.skipped == 'false' }}
with:
name: test_results-${{matrix.chip}}-${{matrix.chunks}}
name: hw_results-${{matrix.chip}}-${{matrix.chunks}}
if-no-files-found: error
path: |
tests/**/*.xml
@ -142,7 +197,7 @@ jobs:
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
contains(github.event.pull_request.labels.*.name, 'perf_test') ||
github.event_name == 'schedule'
needs: Test
needs: hardware-test
runs-on: ubuntu-latest
steps:
- name: Upload
@ -150,3 +205,4 @@ jobs:
with:
name: Event File
path: ${{github.event_path}}

View File

@ -2,7 +2,7 @@ name: Unit Test Results
on:
workflow_run:
workflows: [Run tests in hardware]
workflows: [Run tests]
branches-ignore: [master]
types:

View File

@ -21,7 +21,7 @@ concurrency:
jobs:
gen_chunks:
if: github.event.workflow_run.event == 'pull_request'
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
name: Generate Chunks matrix
runs-on: ubuntu-latest
outputs:

2
tests/.gitignore vendored
View File

@ -2,3 +2,5 @@ build*/
__pycache__/
*.xml
result_*.json
diagram.json
wokwi.toml

View File

View File

View File

View File

View File

View File

@ -1,5 +1,5 @@
[pytest]
addopts = --embedded-services esp,arduino
addopts = --embedded-services esp,arduino,wokwi
# log related
log_cli = True

View File

@ -1,5 +1,6 @@
cryptography>=2.1.4
--only-binary cryptography
pytest-cov
pytest-embedded-serial-esp>=1.10.0
pytest-embedded-arduino>=1.10.0
pytest-embedded-serial-esp>=1.10.2
pytest-embedded-arduino>=1.10.2
pytest-embedded-wokwi>=1.10.2

View File

View File

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-devkit-c-v4",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -13,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-19.2", "v48", "h-38.4" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v173", "h-269.2", "v-98.23" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-c3-devkitm-1",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -22.6,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-28.8", "v144", "h-144", "v-95.7" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v173", "h-269.2", "v-98.23" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-c6-devkitc-1",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -22.6,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-19.2", "v-96", "h-163.2", "v93.77" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v173", "h-269.2", "v-98.23" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-h2-devkitm-1",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -22.6,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-19.2", "v-96", "h-163.2", "v93.77" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v173", "h-269.2", "v-98.23" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-s2-devkitm-1",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -22.6,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-28.8", "v-57.6", "h-144", "v42.71" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v173", "h-269.2", "v-98.23" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,28 @@
{
"version": 1,
"author": "P-R-O-C-H-Y",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-s3-devkitc-1",
"id": "esp32",
"top": -57.6,
"left": -177.56,
"attrs": {}
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": -22.6,
"left": -19.2,
"attrs": { "color": "green" }
}
],
"connections": [
[ "esp32:RX", "$serialMonitor:TX", "", [] ],
[ "esp32:TX", "$serialMonitor:RX", "", [] ],
[ "btn1:1.l", "esp32:0", "blue", [ "h-38.4", "v105.78" ] ],
[ "btn1:2.r", "esp32:GND.1", "black", [ "h19.4", "v221", "h-269.2", "v-57.42" ] ]
],
"dependencies": {}
}

View File

@ -0,0 +1,31 @@
#include <Arduino.h>
#include <unity.h>
#define BTN 0
void test_button() {
Serial.println("Button test");
static int count = 0;
static int lastState = HIGH;
while (count < 3) {
int state = digitalRead(BTN);
if (state != lastState) {
if (state == LOW) {
count++;
Serial.print("Button pressed ");
Serial.print(count);
Serial.println(" times");
}
lastState = state;
}
delay(10);
}
}
void setup() {
Serial.begin(115200);
pinMode(BTN, INPUT_PULLUP);
test_button();
}
void loop() {}

View File

@ -0,0 +1,40 @@
name: Pushbutton counter test
version: 1
author: Jan Prochazka (jan.prochazka@espressif.com)
steps:
- wait-serial: "Button test"
# Need for 1s delay for scenario to run properly
- delay: 1000ms
# Press once
- set-control:
part-id: btn1
control: pressed
value: 1
- delay: 200ms
- set-control:
part-id: btn1
control: pressed
value: 0
- delay: 300ms
# Press 2nd time
- set-control:
part-id: btn1
control: pressed
value: 1
- delay: 200ms
- set-control:
part-id: btn1
control: pressed
value: 0
- delay: 300ms
# Press for the 3rd time
- set-control:
part-id: btn1
control: pressed
value: 1
- wait-serial: "Button pressed 3 times"

View File

@ -0,0 +1,5 @@
def test_gpio(dut):
dut.expect_exact("Button test")
dut.expect_exact("Button pressed 1 times")
dut.expect_exact("Button pressed 2 times")
dut.expect_exact("Button pressed 3 times")

View File

@ -2,6 +2,3 @@ def test_nvs(dut):
dut.expect("Current counter value: 0")
dut.expect("Current counter value: 1")
dut.expect("Current counter value: 2")
dut.expect("Current counter value: 3")
dut.expect("Current counter value: 4")
dut.expect("Current counter value: 5")

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,44 @@
{
"targets": [
{
"name": "esp32",
"fqbn":[
"espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio",
"espressif:esp32:esp32:PSRAM=disabled,PartitionScheme=huge_app,FlashMode=qio"
]
},
{
"name": "esp32s2",
"fqbn": [
"espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app,FlashMode=dio",
"espressif:esp32:esp32s2:PSRAM=disabled,PartitionScheme=huge_app,FlashMode=dio"
]
},
{
"name": "esp32c3",
"fqbn": [
"espressif:esp32:esp32c3:PartitionScheme=huge_app,FlashMode=dio"
]
},
{
"name": "esp32s3",
"fqbn": [
"espressif:esp32:esp32s3:PSRAM=opi,USBMode=default,PartitionScheme=huge_app,FlashMode=qio",
"espressif:esp32:esp32s3:PSRAM=disabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio",
"espressif:esp32:esp32s3:PSRAM=enabled,USBMode=default,PartitionScheme=huge_app,FlashMode=qio"
]
},
{
"name": "esp32c6",
"fqbn": [
"espressif:esp32:esp32c6:PartitionScheme=huge_app,FlashMode=dio"
]
},
{
"name": "esp32h2",
"fqbn": [
"espressif:esp32:esp32h2:PartitionScheme=huge_app,FlashMode=dio"
]
}
]
}

View File

@ -0,0 +1,3 @@
def test_wifi(dut):
dut.expect_exact("WiFi connected")
dut.expect_exact("IP address:")

View File

@ -0,0 +1,124 @@
/*
* This sketch shows the WiFi event usage
*
*/
/*
* WiFi Events
0 ARDUINO_EVENT_WIFI_READY < ESP32 WiFi ready
1 ARDUINO_EVENT_WIFI_SCAN_DONE < ESP32 finish scanning AP
2 ARDUINO_EVENT_WIFI_STA_START < ESP32 station start
3 ARDUINO_EVENT_WIFI_STA_STOP < ESP32 station stop
4 ARDUINO_EVENT_WIFI_STA_CONNECTED < ESP32 station connected to AP
5 ARDUINO_EVENT_WIFI_STA_DISCONNECTED < ESP32 station disconnected from AP
6 ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE < the auth mode of AP connected by ESP32 station changed
7 ARDUINO_EVENT_WIFI_STA_GOT_IP < ESP32 station got IP from connected AP
8 ARDUINO_EVENT_WIFI_STA_LOST_IP < ESP32 station lost IP and the IP is reset to 0
9 ARDUINO_EVENT_WPS_ER_SUCCESS < ESP32 station wps succeeds in enrollee mode
10 ARDUINO_EVENT_WPS_ER_FAILED < ESP32 station wps fails in enrollee mode
11 ARDUINO_EVENT_WPS_ER_TIMEOUT < ESP32 station wps timeout in enrollee mode
12 ARDUINO_EVENT_WPS_ER_PIN < ESP32 station wps pin code in enrollee mode
13 ARDUINO_EVENT_WIFI_AP_START < ESP32 soft-AP start
14 ARDUINO_EVENT_WIFI_AP_STOP < ESP32 soft-AP stop
15 ARDUINO_EVENT_WIFI_AP_STACONNECTED < a station connected to ESP32 soft-AP
16 ARDUINO_EVENT_WIFI_AP_STADISCONNECTED < a station disconnected from ESP32 soft-AP
17 ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED < ESP32 soft-AP assign an IP to a connected station
18 ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED < Receive probe request packet in soft-AP interface
19 ARDUINO_EVENT_WIFI_AP_GOT_IP6 < ESP32 ap interface v6IP addr is preferred
19 ARDUINO_EVENT_WIFI_STA_GOT_IP6 < ESP32 station interface v6IP addr is preferred
20 ARDUINO_EVENT_ETH_START < ESP32 ethernet start
21 ARDUINO_EVENT_ETH_STOP < ESP32 ethernet stop
22 ARDUINO_EVENT_ETH_CONNECTED < ESP32 ethernet phy link up
23 ARDUINO_EVENT_ETH_DISCONNECTED < ESP32 ethernet phy link down
24 ARDUINO_EVENT_ETH_GOT_IP < ESP32 ethernet got IP from connected AP
19 ARDUINO_EVENT_ETH_GOT_IP6 < ESP32 ethernet interface v6IP addr is preferred
25 ARDUINO_EVENT_MAX
*/
#include <WiFi.h>
const char *ssid = "Wokwi-GUEST";
const char *password = "";
// WARNING: This function is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch (event) {
case ARDUINO_EVENT_WIFI_READY: Serial.println("WiFi interface ready"); break;
case ARDUINO_EVENT_WIFI_SCAN_DONE: Serial.println("Completed scan for access points"); break;
case ARDUINO_EVENT_WIFI_STA_START: Serial.println("WiFi client started"); break;
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("WiFi clients stopped"); break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("Connected to access point"); break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("Disconnected from WiFi access point"); break;
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: Serial.println("Authentication mode of access point has changed"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.print("Obtained IP address: ");
Serial.println(WiFi.localIP());
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP: Serial.println("Lost IP address and IP address is reset to 0"); break;
case ARDUINO_EVENT_WPS_ER_SUCCESS: Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_FAILED: Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_TIMEOUT: Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_PIN: Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode"); break;
case ARDUINO_EVENT_WIFI_AP_START: Serial.println("WiFi access point started"); break;
case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("WiFi access point stopped"); break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("Client connected"); break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("Client disconnected"); break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: Serial.println("Assigned IP address to client"); break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("Received probe request"); break;
case ARDUINO_EVENT_WIFI_AP_GOT_IP6: Serial.println("AP IPv6 is preferred"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: Serial.println("STA IPv6 is preferred"); break;
case ARDUINO_EVENT_ETH_GOT_IP6: Serial.println("Ethernet IPv6 is preferred"); break;
case ARDUINO_EVENT_ETH_START: Serial.println("Ethernet started"); break;
case ARDUINO_EVENT_ETH_STOP: Serial.println("Ethernet stopped"); break;
case ARDUINO_EVENT_ETH_CONNECTED: Serial.println("Ethernet connected"); break;
case ARDUINO_EVENT_ETH_DISCONNECTED: Serial.println("Ethernet disconnected"); break;
case ARDUINO_EVENT_ETH_GOT_IP: Serial.println("Obtained IP address"); break;
default: break;
}
}
// WARNING: This function is called from a separate FreeRTOS task (thread)!
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}
void setup() {
Serial.begin(115200);
// delete old config
WiFi.disconnect(true);
delay(1000);
// Examples of different ways to register wifi events;
// these handlers will be called from another thread.
WiFi.onEvent(WiFiEvent);
WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFiEventId_t eventID = WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("WiFi lost connection. Reason: ");
Serial.println(info.wifi_sta_disconnected.reason);
},
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED
);
// Remove WiFi event
Serial.print("WiFi Event ID: ");
Serial.println(eventID);
// WiFi.removeEvent(eventID);
WiFi.begin(ssid, password);
Serial.println();
Serial.println();
Serial.println("Wait for WiFi... ");
}
void loop() {
delay(1000);
}