Prepare web server with embedded files
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*~
|
||||||
|
.pio
|
||||||
148
README
Normal file
148
README
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
OBP Keypad
|
||||||
|
==========
|
||||||
|
|
||||||
|
- Stromversorgung über M12-Anschluß über NMEA2000
|
||||||
|
Eingangsbereich 6~21V
|
||||||
|
- Ein- und Ausschalten durch langen Tastendruck auf DST/ ONOFF
|
||||||
|
- Konfiguration über Web-Interface
|
||||||
|
- PWR leuchtet grün wen NMEA2000-Verbindung etabliert
|
||||||
|
- PWR leuchtet rot wenn nur Stromversorgung aktiv ist
|
||||||
|
|
||||||
|
Optionen
|
||||||
|
- I²C Temp/Hum-Sensor
|
||||||
|
- Seatalk1 Anschluß für Fernbedienung Raymarine Pinnenpilot
|
||||||
|
- EPaper-Display 2.9" zur Anzeige der Tastenbelegung
|
||||||
|
|
||||||
|
Damit die LEDs nicht stören, kann umgeschaltet werden zwischen
|
||||||
|
permanentem Leuchten und nur kurzem Aufblinken bei Betätigung.
|
||||||
|
|
||||||
|
|
||||||
|
Bohrung Taster: 12mm
|
||||||
|
Taster Außenmaß: 17.5mm
|
||||||
|
|
||||||
|
Verbindungskabel CPU-Platine
|
||||||
|
JST 2.54 XH 6 Pin Steckverbinder -> LED
|
||||||
|
|
||||||
|
Anschlußmöglichkeiten
|
||||||
|
|
||||||
|
für Stromversorgung +12V und NMEA2000
|
||||||
|
4pin Terminalblock steck-/schraubbar +12V, DNG, CAN-L, CAN-H
|
||||||
|
|
||||||
|
für I²C-Module
|
||||||
|
2x 4pin Buchsenleiste weibl.
|
||||||
|
1x QWIIC-Buchse (JST_SH_BM04B-SRSS-TB_04x1.00mm)
|
||||||
|
|
||||||
|
für mechanische Taster
|
||||||
|
1x JST 2.54 XH 7 Pin Steckverbinder -> Tasten
|
||||||
|
Masseverbindung über einzelnes getrenntes Kabel
|
||||||
|
|
||||||
|
für LEDs
|
||||||
|
|
||||||
|
|
||||||
|
Bemerkungen
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Bei den aktuell verwendeten Tasten sind die Anschlußdrähte extrem
|
||||||
|
filigran. Leichtes Brechen und schlechte Verarbeitung.
|
||||||
|
|
||||||
|
Beschaltung MCU Nano
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Wiki: https://www.waveshare.com/wiki/ESP32-S3-Nano
|
||||||
|
|
||||||
|
Der Nano hat 30 Pins.
|
||||||
|
|
||||||
|
Stromversorgung über VIN. Lt. Spezifikation können dort 6 bis 21V
|
||||||
|
anliegen. Vmtl. ist ein Betrieb mit 5V auch möglich.
|
||||||
|
Den 3.3V-Pin nicht benutzen. Dieser ist als Ausgang gedacht!
|
||||||
|
|
||||||
|
Das Mapping von Nano-Pin zu GPIO muß noch überprüft werden.
|
||||||
|
Der nano kann in zwei verschiedenen Mapping-Modi betrieben
|
||||||
|
werden!
|
||||||
|
|
||||||
|
Die Pins für i²C (A4, A5)und SPI (D11, D12, D13) sind absichtlich
|
||||||
|
nicht belegt um frei für Erweiterungen zu sein. An SPI kann
|
||||||
|
ggf. ein Epaper angeschlossen werden.
|
||||||
|
|
||||||
|
|
||||||
|
Key Color Pin Remarks
|
||||||
|
----- ------- -------- --------------------
|
||||||
|
1 B D2 GPIO5
|
||||||
|
2 B D3 GPIO6
|
||||||
|
3 B D4 GPIO7
|
||||||
|
4 B D5 GPIO8
|
||||||
|
5 B D6 GPIO9
|
||||||
|
6 Y D7 GPIO10 Illumination
|
||||||
|
DST Y D8 GPIO17 Destination, On/Off
|
||||||
|
|
||||||
|
LED Pin
|
||||||
|
------ ----------
|
||||||
|
A A0 GPIO1
|
||||||
|
B A1 GPIO2
|
||||||
|
C A2 GPIO3
|
||||||
|
(D A3 reserved for future)
|
||||||
|
RGBA A6 GPIO4
|
||||||
|
RGBB A7 GPIO13
|
||||||
|
RGBC B1 GPIO14
|
||||||
|
|
||||||
|
CAN Pin
|
||||||
|
------ ----------
|
||||||
|
RX D9
|
||||||
|
TX D10
|
||||||
|
|
||||||
|
|
||||||
|
Beschaltung MCU Pico !!! Nicht fertig / ungültig !!!
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Stromversorgung über VSYS mit 5V.
|
||||||
|
|
||||||
|
|
||||||
|
Key Color Pin Remarks
|
||||||
|
----- ------- -------- --------------------
|
||||||
|
1 B GP11
|
||||||
|
2 B GP12
|
||||||
|
3 B GP13
|
||||||
|
4 B GP14
|
||||||
|
5 B GP15
|
||||||
|
6 Y GP16 Illumination
|
||||||
|
DST Y GP17 Destination, On/Off
|
||||||
|
|
||||||
|
LED Pin
|
||||||
|
------ ----------
|
||||||
|
A GP1
|
||||||
|
B GP2
|
||||||
|
C GP4
|
||||||
|
RGBA GP5
|
||||||
|
RGBB GP6
|
||||||
|
RGBC GP7
|
||||||
|
|
||||||
|
CAN Pin
|
||||||
|
------ ----------
|
||||||
|
RX GP9
|
||||||
|
TX GP10
|
||||||
|
|
||||||
|
Bauteilliste
|
||||||
|
------------
|
||||||
|
|
||||||
|
1x ESP32-S3 Nano oder ESP32-S3 Pico
|
||||||
|
5x Taster schwarz
|
||||||
|
2x Taster gelb
|
||||||
|
1x M12 Einbaubuchse
|
||||||
|
1x Spannungswandler 12V -> 3.3V
|
||||||
|
1x RGB LED (gemeinsame Anode)
|
||||||
|
3x LED grün
|
||||||
|
1x SN65HVD230 CAN Transceiver
|
||||||
|
1x Gehäuse 150x60x40
|
||||||
|
4x Befestigungsschraube M4
|
||||||
|
1x Kabelsatz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Konfiguration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Instanz-Nummer, es können mehrere Keypads im System sein
|
||||||
|
- Namen des gekoppelten Geräts, an dieses werden die Tasten gesendet
|
||||||
|
- Tastencodes Tasten 1 bis 6
|
||||||
|
- Tastennamen
|
||||||
|
- Web-AP
|
||||||
55
boards/esp32_s3_nano.json
Normal file
55
boards/esp32_s3_nano.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "default_16MB.csv",
|
||||||
|
"memory_type": "qio_opi"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_ESP32S3_DEV",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x303A",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"bluetooth",
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": [
|
||||||
|
"esp-builtin"
|
||||||
|
],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "OBPkb61 ESP32-S3-N16R8 16 MB QD, 8 MB PSRAM)",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://computerclub.hoogi.de/obpkeypad/",
|
||||||
|
"vendor": "Open Boat Projects"
|
||||||
|
}
|
||||||
164
extra_pre.py
164
extra_pre.py
@@ -0,0 +1,164 @@
|
|||||||
|
print("running extra script...")
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import inspect
|
||||||
|
import gzip
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
|
||||||
|
GEN_DIR = 'lib/generated'
|
||||||
|
OWN_FILE = "extra_script.py"
|
||||||
|
|
||||||
|
INDEXJS = "index.js"
|
||||||
|
INDEXCSS = "index.css"
|
||||||
|
|
||||||
|
# embedded files definition is generated inside here
|
||||||
|
EMBEDDED_INCLUDE="embeddedfiles.h"
|
||||||
|
|
||||||
|
def basePath():
|
||||||
|
#see: https://stackoverflow.com/questions/16771894/python-nameerror-global-name-file-is-not-defined
|
||||||
|
return os.path.dirname(inspect.getfile(lambda: None))
|
||||||
|
|
||||||
|
def is_current(infile, outfile):
|
||||||
|
if os.path.exists(outfile):
|
||||||
|
otime = os.path.getmtime(outfile)
|
||||||
|
itime = os.path.getmtime(infile)
|
||||||
|
if (otime >= itime):
|
||||||
|
own = os.path.join(basePath(), OWN_FILE)
|
||||||
|
if os.path.exists(own):
|
||||||
|
owntime = os.path.getmtime(own)
|
||||||
|
if owntime > otime:
|
||||||
|
return False
|
||||||
|
print(f"{outfile} is newer than {infile}, no need to recreate")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def compress_file(infile, outfile):
|
||||||
|
if is_current(infile, outfile):
|
||||||
|
return
|
||||||
|
print(f"compressing {infile}")
|
||||||
|
with open(infile, 'rb') as f_in:
|
||||||
|
with gzip.open(outfile, 'wb') as f_out:
|
||||||
|
shutil.copyfileobj(f_in, f_out)
|
||||||
|
|
||||||
|
def write_file_if_changed(filename, data):
|
||||||
|
"""
|
||||||
|
Create or update file if it not contains data as content
|
||||||
|
"""
|
||||||
|
if os.path.exists(filename):
|
||||||
|
changetype = 'updating'
|
||||||
|
with open(filename, 'r') as fh:
|
||||||
|
if fh.read() == data:
|
||||||
|
print(f"{filename} is up to date")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
changetype = 'generating'
|
||||||
|
print(f"#{changetype} {filename}")
|
||||||
|
with open(filename, 'w') as fh:
|
||||||
|
fh.write(data)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_embedded_files(env):
|
||||||
|
filelist = []
|
||||||
|
efiles = env.GetProjectOption("board_build.embed_files")
|
||||||
|
for f in efiles.split("\n"):
|
||||||
|
if f == '':
|
||||||
|
continue
|
||||||
|
filelist.append(f)
|
||||||
|
return filelist
|
||||||
|
|
||||||
|
def get_content_type(fn):
|
||||||
|
if (fn.endswith('.gz')):
|
||||||
|
fn = fn[0:-3]
|
||||||
|
if (fn.endswith('html')):
|
||||||
|
return "text/html"
|
||||||
|
if (fn.endswith('json')):
|
||||||
|
return "application/json"
|
||||||
|
if (fn.endswith('js')):
|
||||||
|
return "text/javascript"
|
||||||
|
if (fn.endswith('css')):
|
||||||
|
return "text/css"
|
||||||
|
if (fn.endswith('png')):
|
||||||
|
return "image/png"
|
||||||
|
if (fn.endswith('jpg') or fn.endswith('jpeg')):
|
||||||
|
return "image/jpeg"
|
||||||
|
return "application/octet-stream"
|
||||||
|
|
||||||
|
def join_files(target, filename, dirlist):
|
||||||
|
"""
|
||||||
|
Join files named filename within different directories
|
||||||
|
into one single gzip archive (located in generated dir)
|
||||||
|
"""
|
||||||
|
print("joinfiles: {} into {} from dirs [{}]".format(filename, target, ','.join(dirlist)))
|
||||||
|
flist = []
|
||||||
|
for dir in dirlist:
|
||||||
|
fn = os.path.join(dir, filename)
|
||||||
|
if os.path.exists(fn):
|
||||||
|
flist.append(fn)
|
||||||
|
current = False
|
||||||
|
if os.path.exists(target):
|
||||||
|
current = True
|
||||||
|
for f in flist:
|
||||||
|
if not is_current(f, target):
|
||||||
|
current = False
|
||||||
|
break
|
||||||
|
if current:
|
||||||
|
print(f"{target} is up to date")
|
||||||
|
return
|
||||||
|
print(f"creating {target}")
|
||||||
|
|
||||||
|
# add multiple files
|
||||||
|
with gzip.open(target, "wb") as oh:
|
||||||
|
for fn in flist:
|
||||||
|
print("adding {} to {}".format(fn, target))
|
||||||
|
with open(fn, "rb") as rh:
|
||||||
|
shutil.copyfileobj(rh, oh)
|
||||||
|
|
||||||
|
def prebuild(env):
|
||||||
|
print("#prebuild running")
|
||||||
|
|
||||||
|
# directory for dynamically generated files
|
||||||
|
gendir = os.path.join(basePath(), GEN_DIR)
|
||||||
|
if not os.path.exists(gendir):
|
||||||
|
os.makedirs(gendir)
|
||||||
|
if not os.path.isdir(gendir):
|
||||||
|
print("unable to create directory {}".format(gendir))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# join static web server files
|
||||||
|
|
||||||
|
# only useful for different task dirs with custom configs
|
||||||
|
# join_files(os.path.join(gendir, INDEXJS+".gz"), INDEXJS, ["web"])
|
||||||
|
# join_files(os.path.join(gendir, INDEXCSS+".gz"), INDEXCSS, ["web"])
|
||||||
|
|
||||||
|
# platformio defined embedded files as list
|
||||||
|
pio_embedded = get_embedded_files(env)
|
||||||
|
|
||||||
|
filedefs = []
|
||||||
|
for ef in pio_embedded:
|
||||||
|
print(f"#checking embedded file {ef}")
|
||||||
|
# files are defined with relative path to platformio.ini
|
||||||
|
# the name can be with extension gz or without
|
||||||
|
(dn, fn) = os.path.split(ef)
|
||||||
|
pureName = fn
|
||||||
|
if pureName.endswith('.gz'):
|
||||||
|
pureName = pureName[0:-3]
|
||||||
|
usname = ef.replace('/','_').replace('.','_') # sanitize filenames
|
||||||
|
filedefs.append((pureName, usname, get_content_type(pureName)))
|
||||||
|
infile = os.path.join(basePath(), "web", pureName)
|
||||||
|
if os.path.exists(infile):
|
||||||
|
compress_file(infile, ef)
|
||||||
|
else:
|
||||||
|
print("#WARNING: infile {infile} for {ef} not found")
|
||||||
|
|
||||||
|
# generate c-header file for embedding zip files
|
||||||
|
content = ""
|
||||||
|
for entry in filedefs:
|
||||||
|
content += 'EMBED_GZ_FILE("{}", {}, "{}");\n'.format(*entry)
|
||||||
|
write_file_if_changed(os.path.join(gendir, EMBEDDED_INCLUDE), content)
|
||||||
|
|
||||||
|
print("#prescript...")
|
||||||
|
prebuild(env)
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
// General hardware definitions
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Keys
|
|
||||||
#define KEY_1 1 // Key or touchpad
|
|
||||||
#define KEY_2 2 // Key or touchpad
|
|
||||||
|
|
||||||
// I2S audio output -> PCM5102 DAC
|
|
||||||
#define I2S_DOUT 4 // data out
|
|
||||||
#define I2S_BCLK 5 // bit clock
|
|
||||||
#define I2S_LRC 6 // left right channel select
|
|
||||||
#define I2S_XSMT 7 // PCM5102 soft mute
|
|
||||||
|
|
||||||
// SPI for SD-Card; VSPI pins for higher performance
|
|
||||||
#define SD_CS 10
|
|
||||||
#define SD_MOSI 11
|
|
||||||
#define SD_MISO 13
|
|
||||||
#define SD_SCK 12
|
|
||||||
|
|
||||||
// I2C for control interface
|
|
||||||
#define I2C_SDA 8
|
|
||||||
#define I2C_CLK 9
|
|
||||||
|
|
||||||
// CAN bus for NMEA2000 connection
|
|
||||||
#define CAN_RX 47
|
|
||||||
#define CAN_TX 48
|
|
||||||
|
|
||||||
// RS485 for NMEA0183 connection / UART1
|
|
||||||
#define SER_RX 18
|
|
||||||
#define SER_TX 17
|
|
||||||
|
|
||||||
// I2C Addresses
|
|
||||||
// Address of DAC module
|
|
||||||
// Address of switchbank
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma
|
#pragma once
|
||||||
|
|
||||||
// WIFI AP
|
// WIFI AP
|
||||||
#define WIFI_CHANNEL 9
|
#define WIFI_CHANNEL 9
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ lib_deps =
|
|||||||
robtillaart/SHT31@^0.5.2
|
robtillaart/SHT31@^0.5.2
|
||||||
# adafruit/Adafruit NeoPixel
|
# adafruit/Adafruit NeoPixel
|
||||||
|
|
||||||
|
# only these files will be emedded into firmware
|
||||||
|
board_build.embed_files =
|
||||||
|
lib/generated/index.html.gz
|
||||||
|
lib/generated/index.js.gz
|
||||||
|
lib/generated/index.css.gz
|
||||||
|
lib/generated/config.json.gz
|
||||||
|
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:extra_pre.py
|
pre:extra_pre.py
|
||||||
post:extra_post.py
|
post:extra_post.py
|
||||||
@@ -27,8 +34,9 @@ build_flags =
|
|||||||
|
|
||||||
[env:esp32-s3-nano]
|
[env:esp32-s3-nano]
|
||||||
build_type = release # debug | release
|
build_type = release # debug | release
|
||||||
#board = esp32-s3-devkitc-1
|
# board = esp32-s3-devkitc-1
|
||||||
board = arduino_nano_esp32
|
board = esp32_s3_nano
|
||||||
|
#board = arduino_nano_esp32 # ATTENTION! Pin numbering scheme changes
|
||||||
board_upload.flash_size = 16MB
|
board_upload.flash_size = 16MB
|
||||||
board_build.partitions = default.csv
|
board_build.partitions = default.csv
|
||||||
upload_port = /dev/ttyACM0
|
upload_port = /dev/ttyACM0
|
||||||
|
|||||||
68
src/main.cpp
68
src/main.cpp
@@ -10,25 +10,47 @@
|
|||||||
#include <N2kMessages.h>
|
#include <N2kMessages.h>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "Nmea2kTwai.h"
|
#include "Nmea2kTwai.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
Preferences preferences; // persistent storage for configuration
|
Preferences preferences; // persistent storage for configuration
|
||||||
|
|
||||||
|
class EmbeddedFile;
|
||||||
|
static std::map<String, EmbeddedFile*> embeddedFiles;
|
||||||
|
class EmbeddedFile {
|
||||||
|
public:
|
||||||
|
const uint8_t *start;
|
||||||
|
int len;
|
||||||
|
String contentType;
|
||||||
|
EmbeddedFile(String name, String contentType, const uint8_t *start, int len) {
|
||||||
|
this->start = start;
|
||||||
|
this->len = len;
|
||||||
|
this->contentType = contentType;
|
||||||
|
embeddedFiles[name] = this;
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define EMBED_GZ_FILE(fileName, binName, contentType) \
|
||||||
|
extern const uint8_t binName##_File[] asm("_binary_" #binName "_start"); \
|
||||||
|
extern const uint8_t binName##_FileLen[] asm("_binary_" #binName "_size"); \
|
||||||
|
const EmbeddedFile binName##_Config(fileName,contentType,(const uint8_t*)binName##_File,(int)binName##_FileLen);
|
||||||
|
#include "embeddedfiles.h"
|
||||||
|
|
||||||
|
void send_embedded_file(String name, AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
std::map<String, EmbeddedFile*>::iterator it = embeddedFiles.find(name);
|
||||||
|
if (it != embeddedFiles.end()) {
|
||||||
|
EmbeddedFile* found = it->second;
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse(200, found->contentType, found->start, found->len);
|
||||||
|
response->addHeader(F("Content-Encoding"), F("gzip"));
|
||||||
|
request->send(response);
|
||||||
|
} else {
|
||||||
|
request->send(404, "text/plain", "Not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* wifi_ssid = "OBPKP61";
|
const char* wifi_ssid = "OBPKP61";
|
||||||
const char* wifi_pass = "keypad61";
|
const char* wifi_pass = "keypad61";
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
const char index_html[] PROGMEM = R"rawliteral(
|
|
||||||
<!DOCTYPE HTML><html>
|
|
||||||
<head>
|
|
||||||
<title>ESP Web Server</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" href="data:,">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>ESP Web Server</h2>
|
|
||||||
<p>Work in progress</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
)rawliteral";
|
|
||||||
|
|
||||||
unsigned long lastPrint = 0;
|
unsigned long lastPrint = 0;
|
||||||
unsigned long counter = 0;
|
unsigned long counter = 0;
|
||||||
@@ -110,20 +132,29 @@ void setup() {
|
|||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
WiFi.mode(WIFI_MODE_AP);
|
WiFi.mode(WIFI_MODE_AP);
|
||||||
|
|
||||||
IPAddress ap_addr(192, 168, 15, 1);
|
|
||||||
IPAddress ap_subnet(255, 255, 255, 0);
|
|
||||||
IPAddress ap_gateway(ap_addr);
|
|
||||||
|
|
||||||
int channel = WIFI_CHANNEL;
|
int channel = WIFI_CHANNEL;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
WiFi.softAP(wifi_ssid, wifi_pass, channel, hidden, WIFI_MAX_STA);
|
WiFi.softAP(wifi_ssid, wifi_pass, channel, hidden, WIFI_MAX_STA);
|
||||||
|
|
||||||
|
IPAddress ap_addr(192, 168, 15, 1);
|
||||||
|
IPAddress ap_subnet(255, 255, 255, 0);
|
||||||
|
IPAddress ap_gateway(ap_addr);
|
||||||
|
WiFi.softAPConfig(ap_addr, ap_gateway, ap_subnet);
|
||||||
|
|
||||||
// Route for root / web page
|
// Route for root / web page
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(200, "text/html", index_html, processor);
|
send_embedded_file("index.html", request);
|
||||||
|
});
|
||||||
|
// Route for all other defined pages
|
||||||
|
for (auto it = embeddedFiles.begin(); it != embeddedFiles.end(); it++) {
|
||||||
|
String uri = String("/") + it->first;
|
||||||
|
server.on(uri.c_str(), HTTP_GET, [it](AsyncWebServerRequest *request) {
|
||||||
|
send_embedded_file(it->first, request);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|
||||||
|
|
||||||
NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
|
NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
|
||||||
74, // Manufacturer's product code
|
74, // Manufacturer's product code
|
||||||
"OBPkeypad6/1", // Manufacturer's Model ID
|
"OBPkeypad6/1", // Manufacturer's Model ID
|
||||||
@@ -284,7 +315,6 @@ void loop() {
|
|||||||
delay(200);
|
delay(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---- PRINT NUMBER EVERY SECOND ----
|
// ---- PRINT NUMBER EVERY SECOND ----
|
||||||
if (millis() - lastPrint >= 1000) {
|
if (millis() - lastPrint >= 1000) {
|
||||||
lastPrint = millis();
|
lastPrint = millis();
|
||||||
|
|||||||
20
web/config.json
Normal file
20
web/config.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "systemName",
|
||||||
|
"label": "system name",
|
||||||
|
"type": "string",
|
||||||
|
"default": "OBPkeypad61",
|
||||||
|
"check": "checkSystemName",
|
||||||
|
"description": "system name, used for the access point and for services",
|
||||||
|
"category": "system"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "apPassword",
|
||||||
|
"type": "password",
|
||||||
|
"default": "keypad61",
|
||||||
|
"check": "checkApPass",
|
||||||
|
"description": "set the password for the Wifi access point",
|
||||||
|
"category": "system",
|
||||||
|
"capabilities":{"apPwChange":["true"]}
|
||||||
|
}
|
||||||
|
]
|
||||||
0
web/index.css
Normal file
0
web/index.css
Normal file
17
web/index.html
Normal file
17
web/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OBPkeypad 6/1</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
|
<script type="text/javascript" src="index.js"></script>
|
||||||
|
<link rel="stylesheet" href="index.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<h1>OBPkeypad 6/1</h1>
|
||||||
|
<p>Work in progress</p>
|
||||||
|
<p><a href="https://computerclub.hoogi.de/obpkeypad/">Furter Information</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
0
web/index.js
Normal file
0
web/index.js
Normal file
Reference in New Issue
Block a user