Merge branch 'master' into dev
Conflicts: package.json wled00/html_other.h wled00/html_settings.h wled00/wled.h
This commit is contained in:
commit
cf9cf9d7bb
67
.github/workflows/wled-ci.yml
vendored
67
.github/workflows/wled-ci.yml
vendored
@ -3,10 +3,37 @@ name: PlatformIO CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
get_default_envs:
|
||||
name: Gather Environments
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- uses: actions/setup-python@v2
|
||||
- name: Install PlatformIO
|
||||
run: pip install -r requirements.txt
|
||||
- name: Get default environments
|
||||
id: envs
|
||||
run: |
|
||||
echo "::set-output name=environments::$(pio project config --json-output | jq -cr '.[0][1][0][1]')"
|
||||
outputs:
|
||||
environments: ${{ steps.envs.outputs.environments }}
|
||||
|
||||
|
||||
build:
|
||||
name: Build Enviornments
|
||||
runs-on: ubuntu-latest
|
||||
needs: get_default_envs
|
||||
strategy:
|
||||
matrix:
|
||||
environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cache pip
|
||||
@ -24,8 +51,36 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade platformio
|
||||
- name: Run PlatformIO
|
||||
run: pio run
|
||||
run: pip install -r requirements.txt
|
||||
- name: Build firmware
|
||||
env:
|
||||
WLED_RELEASE: True
|
||||
run: pio run -e ${{ matrix.environment }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ matrix.environment }}
|
||||
path: |
|
||||
build_output/firmware/*.bin
|
||||
build_output/firmware/*.gz
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
name: firmware-release
|
||||
path: build_output/release/*.bin
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get_default_envs, build]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: firmware-release
|
||||
- name: Create draft release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: True
|
||||
files: |
|
||||
*.bin
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,3 +14,4 @@
|
||||
.clang-format
|
||||
node_modules
|
||||
.idea
|
||||
.direnv
|
||||
|
@ -2,6 +2,15 @@
|
||||
|
||||
### Builds after release 0.12.0
|
||||
|
||||
#### Build 2104220
|
||||
|
||||
- Version bump to 0.12.1-b1 "Hikari"
|
||||
- Release and build script improvements (PR #1844)
|
||||
|
||||
#### Build 2104211
|
||||
|
||||
- Replace default TV simulator effect with the version that saves 18k of flash and appears visually identical
|
||||
|
||||
#### Build 2104210
|
||||
|
||||
- Added `tb` to JSON state, allowing setting the timebase (set tb=0 to start e.g. wipe effect from the beginning). Receive only.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.12.1-a0",
|
||||
"version": "0.12.1-a1",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
|
@ -1,23 +0,0 @@
|
||||
Import('env')
|
||||
import os
|
||||
import shutil
|
||||
import gzip
|
||||
|
||||
OUTPUT_DIR = "build_output{}".format(os.path.sep)
|
||||
|
||||
def bin_gzip(source, target, env):
|
||||
variant = str(target[0]).split(os.path.sep)[2]
|
||||
|
||||
# create string with location and file names based on variant
|
||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
gzip_file = "{}firmware{}{}.bin.gz".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
|
||||
# check if new target files exist and remove if necessary
|
||||
if os.path.isfile(gzip_file): os.remove(gzip_file)
|
||||
|
||||
# write gzip firmware file
|
||||
with open(bin_file,"rb") as fp:
|
||||
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
|
||||
shutil.copyfileobj(fp, f)
|
||||
|
||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_gzip])
|
@ -1,34 +0,0 @@
|
||||
Import('env')
|
||||
import os
|
||||
import shutil
|
||||
|
||||
OUTPUT_DIR = "build_output{}".format(os.path.sep)
|
||||
|
||||
def bin_rename_copy(source, target, env):
|
||||
variant = str(target[0]).split(os.path.sep)[2]
|
||||
|
||||
# check if output directories exist and create if necessary
|
||||
if not os.path.isdir(OUTPUT_DIR):
|
||||
os.mkdir(OUTPUT_DIR)
|
||||
|
||||
for d in ['firmware', 'map']:
|
||||
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
|
||||
os.mkdir("{}{}".format(OUTPUT_DIR, d))
|
||||
|
||||
# create string with location and file names based on variant
|
||||
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
|
||||
# check if new target files exist and remove if necessary
|
||||
for f in [map_file, bin_file]:
|
||||
if os.path.isfile(f):
|
||||
os.remove(f)
|
||||
|
||||
# copy firmware.bin to firmware/<variant>.bin
|
||||
shutil.copy(str(target[0]), bin_file)
|
||||
|
||||
# copy firmware.map to map/<variant>.map
|
||||
if os.path.isfile("firmware.map"):
|
||||
shutil.move("firmware.map", map_file)
|
||||
|
||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy])
|
69
pio-scripts/output_bins.py
Normal file
69
pio-scripts/output_bins.py
Normal file
@ -0,0 +1,69 @@
|
||||
Import('env')
|
||||
import os
|
||||
import shutil
|
||||
import gzip
|
||||
|
||||
OUTPUT_DIR = "build_output{}".format(os.path.sep)
|
||||
|
||||
def _get_cpp_define_value(env, define):
|
||||
define_list = [item[-1] for item in env["CPPDEFINES"] if item[0] == define]
|
||||
|
||||
if define_list:
|
||||
return define_list[0]
|
||||
|
||||
return None
|
||||
|
||||
def _create_dirs(dirs=["firmware", "map"]):
|
||||
# check if output directories exist and create if necessary
|
||||
if not os.path.isdir(OUTPUT_DIR):
|
||||
os.mkdir(OUTPUT_DIR)
|
||||
|
||||
for d in dirs:
|
||||
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
|
||||
os.mkdir("{}{}".format(OUTPUT_DIR, d))
|
||||
|
||||
def bin_rename_copy(source, target, env):
|
||||
_create_dirs()
|
||||
variant = env["PIOENV"]
|
||||
|
||||
# create string with location and file names based on variant
|
||||
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
|
||||
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
|
||||
|
||||
if release_name and os.getenv("WLED_RELEASE"):
|
||||
_create_dirs(["release"])
|
||||
version = _get_cpp_define_value(env, "WLED_VERSION")
|
||||
release_file = "{}release{}WLED_{}_{}.bin".format(OUTPUT_DIR, os.path.sep, version, release_name)
|
||||
shutil.copy(str(target[0]), release_file)
|
||||
|
||||
# check if new target files exist and remove if necessary
|
||||
for f in [map_file, bin_file]:
|
||||
if os.path.isfile(f):
|
||||
os.remove(f)
|
||||
|
||||
# copy firmware.bin to firmware/<variant>.bin
|
||||
shutil.copy(str(target[0]), bin_file)
|
||||
|
||||
# copy firmware.map to map/<variant>.map
|
||||
if os.path.isfile("firmware.map"):
|
||||
shutil.move("firmware.map", map_file)
|
||||
|
||||
def bin_gzip(source, target, env):
|
||||
_create_dirs()
|
||||
variant = env["PIOENV"]
|
||||
|
||||
# create string with location and file names based on variant
|
||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
gzip_file = "{}firmware{}{}.bin.gz".format(OUTPUT_DIR, os.path.sep, variant)
|
||||
|
||||
# check if new target files exist and remove if necessary
|
||||
if os.path.isfile(gzip_file): os.remove(gzip_file)
|
||||
|
||||
# write gzip firmware file
|
||||
with open(bin_file,"rb") as fp:
|
||||
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
|
||||
shutil.copyfileobj(fp, f)
|
||||
|
||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy, bin_gzip])
|
8
pio-scripts/set_version.py
Normal file
8
pio-scripts/set_version.py
Normal file
@ -0,0 +1,8 @@
|
||||
Import('env')
|
||||
import json
|
||||
|
||||
PACKAGE_FILE = "package.json"
|
||||
|
||||
with open(PACKAGE_FILE, "r") as package:
|
||||
version = json.load(package)["version"]
|
||||
env.Append(BUILD_FLAGS=[f"-DWLED_VERSION={version}"])
|
@ -151,10 +151,11 @@ build_flags = -g
|
||||
-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
|
||||
[scripts_defaults]
|
||||
extra_scripts = pio-scripts/name-firmware.py
|
||||
pio-scripts/gzip-firmware.py
|
||||
pio-scripts/strip-floats.py
|
||||
pio-scripts/user_config_copy.py
|
||||
extra_scripts =
|
||||
pre:pio-scripts/set_version.py
|
||||
post:pio-scripts/output_bins.py
|
||||
post:pio-scripts/strip-floats.py
|
||||
pre:pio-scripts/user_config_copy.py
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# COMMON SETTINGS:
|
||||
@ -213,7 +214,7 @@ platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266
|
||||
|
||||
[env:esp01_1m_full]
|
||||
board = esp01_1m
|
||||
@ -221,7 +222,7 @@ platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_1m128k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA
|
||||
|
||||
[env:esp07]
|
||||
board = esp07
|
||||
@ -261,7 +262,7 @@ build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
board = esp32dev
|
||||
platform = espressif32@3.2
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
@ -271,7 +272,7 @@ board = esp32-poe
|
||||
platform = espressif32@3.2
|
||||
upload_speed = 921600
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
1
requirements.in
Normal file
1
requirements.in
Normal file
@ -0,0 +1 @@
|
||||
platformio
|
54
requirements.txt
Normal file
54
requirements.txt
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile
|
||||
#
|
||||
aiofiles==0.6.0
|
||||
# via platformio
|
||||
ajsonrpc==1.1.0
|
||||
# via platformio
|
||||
bottle==0.12.19
|
||||
# via platformio
|
||||
certifi==2020.12.5
|
||||
# via requests
|
||||
chardet==4.0.0
|
||||
# via requests
|
||||
click==7.1.2
|
||||
# via
|
||||
# platformio
|
||||
# uvicorn
|
||||
colorama==0.4.4
|
||||
# via platformio
|
||||
h11==0.12.0
|
||||
# via
|
||||
# uvicorn
|
||||
# wsproto
|
||||
idna==2.10
|
||||
# via requests
|
||||
ifaddr==0.1.7
|
||||
# via zeroconf
|
||||
marshmallow==3.11.1
|
||||
# via platformio
|
||||
platformio==5.1.1
|
||||
# via -r requirements.in
|
||||
pyelftools==0.27
|
||||
# via platformio
|
||||
pyserial==3.5
|
||||
# via platformio
|
||||
requests==2.25.1
|
||||
# via platformio
|
||||
semantic-version==2.8.5
|
||||
# via platformio
|
||||
starlette==0.14.2
|
||||
# via platformio
|
||||
tabulate==0.8.9
|
||||
# via platformio
|
||||
urllib3==1.26.4
|
||||
# via requests
|
||||
uvicorn==0.13.4
|
||||
# via platformio
|
||||
wsproto==1.0.0
|
||||
# via platformio
|
||||
zeroconf==0.28.8
|
||||
# via platformio
|
@ -3821,18 +3821,13 @@ typedef struct TvSim {
|
||||
} tvSim;
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_FX_HIGH_FLASH_USE
|
||||
#include "tv_colors.h"
|
||||
#define numTVPixels (sizeof(tv_colors) / 2) // 2 bytes per Pixel (5/6/5)
|
||||
#endif
|
||||
|
||||
/*
|
||||
TV Simulator
|
||||
Modified and adapted to WLED by Def3nder, based on "Fake TV Light for Engineers" by Phillip Burgess https://learn.adafruit.com/fake-tv-light-for-engineers/arduino-sketch
|
||||
*/
|
||||
uint16_t WS2812FX::mode_tv_simulator(void) {
|
||||
uint16_t nr, ng, nb, r, g, b, i, hue;
|
||||
uint8_t hi, lo, r8, g8, b8, sat, bri, j;
|
||||
uint8_t sat, bri, j;
|
||||
|
||||
if (!SEGENV.allocateData(sizeof(tvSim))) return mode_static(); //allocation failed
|
||||
TvSim* tvSimulator = reinterpret_cast<TvSim*>(SEGENV.data);
|
||||
@ -3846,35 +3841,6 @@ uint16_t WS2812FX::mode_tv_simulator(void) {
|
||||
SEGENV.aux1 = 0;
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_FX_HIGH_FLASH_USE
|
||||
/*
|
||||
* this code uses the real color data from tv_colos.h
|
||||
*/
|
||||
|
||||
// initialize start of the TV-Colors
|
||||
if (SEGENV.aux1 == 0) {
|
||||
tvSimulator->pixelNum = ((uint8_t)random8(18)) * numTVPixels / 18; // Begin at random movie (18 in total)
|
||||
SEGENV.aux1 = 1;
|
||||
}
|
||||
|
||||
// Read next 16-bit (5/6/5) color
|
||||
hi = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 ]);
|
||||
lo = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 + 1]);
|
||||
|
||||
// Expand to 24-bit (8/8/8)
|
||||
r8 = (hi & 0xF8) | (hi >> 5);
|
||||
g8 = ((hi << 5) & 0xff) | ((lo & 0xE0) >> 3) | ((hi & 0x06) >> 1);
|
||||
b8 = ((lo << 3) & 0xff) | ((lo & 0x1F) >> 2);
|
||||
|
||||
// Apply gamma correction, further expand to 16/16/16
|
||||
nr = (uint8_t)gamma8(r8) * 257; // New R/G/B
|
||||
ng = (uint8_t)gamma8(g8) * 257;
|
||||
nb = (uint8_t)gamma8(b8) * 257;
|
||||
#else
|
||||
/*
|
||||
* this code calculates the color to be used and save 18k of flash memory
|
||||
*/
|
||||
|
||||
// create a new sceene
|
||||
if (((millis() - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
|
||||
tvSimulator->sceeneStart = millis(); // remember the start of the new sceene
|
||||
@ -3919,17 +3885,10 @@ uint16_t WS2812FX::mode_tv_simulator(void) {
|
||||
nr = (uint8_t)gamma8(tvSimulator->actualColorR) * 257; // New R/G/B
|
||||
ng = (uint8_t)gamma8(tvSimulator->actualColorG) * 257;
|
||||
nb = (uint8_t)gamma8(tvSimulator->actualColorB) * 257;
|
||||
#endif
|
||||
|
||||
if (SEGENV.aux0 == 0) { // initialize next iteration
|
||||
SEGENV.aux0 = 1;
|
||||
|
||||
#ifndef WLED_DISABLE_FX_HIGH_FLASH_USE
|
||||
// increase color-index for next loop
|
||||
tvSimulator->pixelNum++;
|
||||
if (tvSimulator->pixelNum >= numTVPixels) tvSimulator->pixelNum = 0;
|
||||
#endif
|
||||
|
||||
// randomize total duration and fade duration for the actual color
|
||||
tvSimulator->totalTime = random16(250, 2500); // Semi-random pixel-to-pixel time
|
||||
tvSimulator->fadeTime = random16(0, tvSimulator->totalTime); // Pixel-to-pixel transition time
|
||||
|
@ -46,9 +46,6 @@
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
/* Disable effects with high flash memory usage (currently TV simulator) - saves 18.5kB */
|
||||
//#define WLED_DISABLE_FX_HIGH_FLASH_USE
|
||||
|
||||
/* Not used in all effects yet */
|
||||
#define WLED_FPS 42
|
||||
#define FRAMETIME (1000/WLED_FPS)
|
||||
|
@ -42,7 +42,7 @@ function B(){window.history.back()}function U(){document.getElementById("uf").st
|
||||
.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}#msg{display:none}
|
||||
</style></head><body><h2>WLED Software Update</h2><form method="POST"
|
||||
action="/update" id="uf" enctype="multipart/form-data" onsubmit="U()">
|
||||
Installed version: 0.12.1-a0<br>Download the latest binary: <a
|
||||
Installed version: 0.12.1-a1<br>Download the latest binary: <a
|
||||
href="https://github.com/Aircoookie/WLED/releases" target="_blank"><img
|
||||
src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square">
|
||||
</a><br><input type="file" class="bt" name="update" accept=".bin" required><br>
|
||||
|
@ -381,7 +381,7 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
|
||||
<h3>Software Update</h3><button type="button" onclick="U()">Manual OTA Update
|
||||
</button><br>Enable ArduinoOTA: <input type="checkbox" name="AO"><br><h3>About
|
||||
</h3><a href="https://github.com/Aircoookie/WLED/" target="_blank">WLED</a>
|
||||
version 0.12.1-a0<br><br><a
|
||||
version 0.12.1-a1<br><br><a
|
||||
href="https://github.com/Aircoookie/WLED/wiki/Contributors-and-credits"
|
||||
target="_blank">Contributors, dependencies and special thanks</a><br>
|
||||
A huge thank you to everyone who helped me create WLED!<br><br>
|
||||
|
1506
wled00/tv_colors.h
1506
wled00/tv_colors.h
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Main sketch, global variable declarations
|
||||
@title WLED project sketch
|
||||
@version 0.12.0-b5
|
||||
@version 0.12.1-a1
|
||||
@author Christian Schwinne
|
||||
*/
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
//#define WLED_DISABLE_ALEXA // saves 11kb
|
||||
//#define WLED_DISABLE_BLYNK // saves 6kb
|
||||
//#define WLED_DISABLE_CRONIXIE // saves 3kb
|
||||
//WLED_DISABLE_FX_HIGH_FLASH_USE (need to enable in PIO config or FX.h, saves 18kb)
|
||||
//#define WLED_DISABLE_HUESYNC // saves 4kb
|
||||
//#define WLED_DISABLE_INFRARED // there is no pin left for this on ESP8266-01, saves 12kb
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
@ -171,8 +170,15 @@
|
||||
# define _INIT_N(x) UNPACK x
|
||||
#endif
|
||||
|
||||
#define STRINGIFY(X) #X
|
||||
#define TOSTRING(X) STRINGIFY(X)
|
||||
|
||||
#ifndef WLED_VERSION
|
||||
#define WLED_VERSION "dev"
|
||||
#endif
|
||||
|
||||
// Global Variable definitions
|
||||
WLED_GLOBAL char versionString[] _INIT("0.12.1-a0");
|
||||
WLED_GLOBAL char versionString[] _INIT(TOSTRING(WLED_VERSION));
|
||||
#define WLED_CODENAME "Hikari"
|
||||
|
||||
// AP and OTA default passwords (for maximum security change them!)
|
||||
|
Loading…
Reference in New Issue
Block a user