mirror of
https://gitlab.com/wirelos/sprocket-plugin-web.git
synced 2025-12-14 22:02:23 +01:00
initial commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pioenvs
|
||||||
|
.piolibdeps
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
14
.gitlab-ci.yml
Normal file
14
.gitlab-ci.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
image: python:2.7-stretch
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- "pip install -U platformio"
|
||||||
|
|
||||||
|
examples:
|
||||||
|
stage: build
|
||||||
|
image: python:2.7-stretch
|
||||||
|
script:
|
||||||
|
- pio run -t clean
|
||||||
|
- pio run -e basic
|
||||||
67
.travis.yml
Normal file
67
.travis.yml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Continuous Integration (CI) is the practice, in software
|
||||||
|
# engineering, of merging all developer working copies with a shared mainline
|
||||||
|
# several times a day < http://docs.platformio.org/page/ci/index.html >
|
||||||
|
#
|
||||||
|
# Documentation:
|
||||||
|
#
|
||||||
|
# * Travis CI Embedded Builds with PlatformIO
|
||||||
|
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||||
|
#
|
||||||
|
# * PlatformIO integration with Travis CI
|
||||||
|
# < http://docs.platformio.org/page/ci/travis.html >
|
||||||
|
#
|
||||||
|
# * User Guide for `platformio ci` command
|
||||||
|
# < http://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Please choice one of the following templates (proposed below) and uncomment
|
||||||
|
# it (remove "# " before each line) or use own configuration according to the
|
||||||
|
# Travis CI documentation (see above).
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Template #1: General project. Test it using existing `platformio.ini`.
|
||||||
|
#
|
||||||
|
|
||||||
|
# language: python
|
||||||
|
# python:
|
||||||
|
# - "2.7"
|
||||||
|
#
|
||||||
|
# sudo: false
|
||||||
|
# cache:
|
||||||
|
# directories:
|
||||||
|
# - "~/.platformio"
|
||||||
|
#
|
||||||
|
# install:
|
||||||
|
# - pip install -U platformio
|
||||||
|
# - platformio update
|
||||||
|
#
|
||||||
|
# script:
|
||||||
|
# - platformio run
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Template #2: The project is intended to by used as a library with examples
|
||||||
|
#
|
||||||
|
|
||||||
|
# language: python
|
||||||
|
# python:
|
||||||
|
# - "2.7"
|
||||||
|
#
|
||||||
|
# sudo: false
|
||||||
|
# cache:
|
||||||
|
# directories:
|
||||||
|
# - "~/.platformio"
|
||||||
|
#
|
||||||
|
# env:
|
||||||
|
# - PLATFORMIO_CI_SRC=path/to/test/file.c
|
||||||
|
# - PLATFORMIO_CI_SRC=examples/file.ino
|
||||||
|
# - PLATFORMIO_CI_SRC=path/to/test/directory
|
||||||
|
#
|
||||||
|
# install:
|
||||||
|
# - pip install -U platformio
|
||||||
|
# - platformio update
|
||||||
|
#
|
||||||
|
# script:
|
||||||
|
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
|
||||||
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"platformio.platformio-ide"
|
||||||
|
]
|
||||||
|
}
|
||||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"terminal.integrated.env.linux": {
|
||||||
|
"PATH": "/home/master/.platformio/penv/bin:/home/master/.platformio/penv:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl",
|
||||||
|
"PLATFORMIO_CALLER": "vscode"
|
||||||
|
}
|
||||||
|
}
|
||||||
9
data/config.json
Normal file
9
data/config.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"stationMode": 1,
|
||||||
|
"hostname": "websprocket",
|
||||||
|
"apSSID": "WebSprocket",
|
||||||
|
"apPassword": "th3r31sn0sp00n",
|
||||||
|
"connectTimeout": 20000,
|
||||||
|
"stationSSID": "MyWifi",
|
||||||
|
"stationPassword": "myWifiPassword"
|
||||||
|
}
|
||||||
BIN
data/www/favicon.png
Normal file
BIN
data/www/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
1351
data/www/gradients.json
Normal file
1351
data/www/gradients.json
Normal file
File diff suppressed because it is too large
Load Diff
32
data/www/index.html
Normal file
32
data/www/index.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>ESP Kit</title>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="sui">
|
||||||
|
<div class="content">
|
||||||
|
<div class="settings container collapsible">
|
||||||
|
<span class="heading">Settings</span>
|
||||||
|
<div class="content">
|
||||||
|
<h2>Network</h2>
|
||||||
|
<div class="Form" data-fileName="/config.json" data-name="configForm" data-from="/config.json" data-endpoint="/config"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="settings container collapsible">
|
||||||
|
<span class="heading">System</span>
|
||||||
|
<div class="content">
|
||||||
|
<div><label>Free Heap: </label><span class="js-heap"></span><span> bytes</span><br><br></div>
|
||||||
|
<button class="js-restart">Restart</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
12245
data/www/script.js
Normal file
12245
data/www/script.js
Normal file
File diff suppressed because it is too large
Load Diff
308
data/www/styles.css
Normal file
308
data/www/styles.css
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.shown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
.sui {
|
||||||
|
background: #000000;
|
||||||
|
color: #0eb8c0;
|
||||||
|
font-family: Tahoma, Geneva, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.sui * {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.sui > .content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 968px) {
|
||||||
|
.sui > .content {
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sui label {
|
||||||
|
color: #b3b2b2;
|
||||||
|
}
|
||||||
|
.sui button {
|
||||||
|
background: #097479;
|
||||||
|
color: #eeeeee;
|
||||||
|
font-size: 0.9em;
|
||||||
|
border: 0;
|
||||||
|
padding: .8em;
|
||||||
|
margin: 0 .4em;
|
||||||
|
}
|
||||||
|
.heading {
|
||||||
|
font-size: 1.2em;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.sui h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background: #333333;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: solid 1px #555555;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.container.collapsible > .heading {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.container.collapsible > .heading:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.container.collapsible > .content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.container.collapsible.open > .heading {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.container.collapsible.open > .content {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
input[type=range] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
margin: 8.4px 0;
|
||||||
|
padding: 0 !important;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
input[type=range]:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
input[type=range]::-webkit-slider-runnable-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 3.2px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
|
||||||
|
background: #097479;
|
||||||
|
border-radius: 1.3px;
|
||||||
|
border: 0.2px solid #010101;
|
||||||
|
}
|
||||||
|
input[type=range]::-webkit-slider-thumb {
|
||||||
|
box-shadow: 0.6px 0.6px 2.8px #000000, 0px 0px 0.6px #0d0d0d;
|
||||||
|
border: 0.4px solid #000000;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 50px;
|
||||||
|
background: #0eb8c0;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin-top: -8.6px;
|
||||||
|
}
|
||||||
|
input[type=range]:focus::-webkit-slider-runnable-track {
|
||||||
|
background: #0eb4bb;
|
||||||
|
}
|
||||||
|
input[type=range]::-moz-range-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 3.2px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
|
||||||
|
background: #097479;
|
||||||
|
border-radius: 1.3px;
|
||||||
|
border: 0.2px solid #010101;
|
||||||
|
}
|
||||||
|
input[type=range]::-moz-range-thumb {
|
||||||
|
box-shadow: 0.6px 0.6px 2.8px #000000, 0px 0px 0.6px #0d0d0d;
|
||||||
|
border: 0.4px solid #000000;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 50px;
|
||||||
|
background: #0eb8c0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
input[type=range]::-ms-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 3.2px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
input[type=range]::-ms-fill-lower {
|
||||||
|
background: #043437;
|
||||||
|
border: 0.2px solid #010101;
|
||||||
|
border-radius: 2.6px;
|
||||||
|
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
|
||||||
|
}
|
||||||
|
input[type=range]::-ms-fill-upper {
|
||||||
|
background: #097479;
|
||||||
|
border: 0.2px solid #010101;
|
||||||
|
border-radius: 2.6px;
|
||||||
|
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
|
||||||
|
}
|
||||||
|
input[type=range]::-ms-thumb {
|
||||||
|
box-shadow: 0.6px 0.6px 2.8px #000000, 0px 0px 0.6px #0d0d0d;
|
||||||
|
border: 0.4px solid #000000;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 50px;
|
||||||
|
background: #0eb8c0;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 3.2px;
|
||||||
|
}
|
||||||
|
input[type=range]:focus::-ms-fill-lower {
|
||||||
|
background: #097479;
|
||||||
|
}
|
||||||
|
input[type=range]:focus::-ms-fill-upper {
|
||||||
|
background: #0eb4bb;
|
||||||
|
}
|
||||||
|
.form-row input[type="range"] {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
/* The switch - the box around the slider */
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline;
|
||||||
|
/* The slider */
|
||||||
|
/* Rounded sliders */
|
||||||
|
}
|
||||||
|
.switch input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.switch .slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #7b7b7b;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
margin-left: -50px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
.switch .slider:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
left: 4px;
|
||||||
|
bottom: 4px;
|
||||||
|
background-color: white;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
.switch input:checked + .slider {
|
||||||
|
background-color: #097479;
|
||||||
|
}
|
||||||
|
.switch input:focus + .slider {
|
||||||
|
box-shadow: 0 0 1px #0eb8c0;
|
||||||
|
}
|
||||||
|
.switch input:checked + .slider:before {
|
||||||
|
-webkit-transform: translateX(26px);
|
||||||
|
-ms-transform: translateX(26px);
|
||||||
|
transform: translateX(26px);
|
||||||
|
}
|
||||||
|
.switch .slider.round {
|
||||||
|
border-radius: 34px;
|
||||||
|
height: 34px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
.switch .slider.round:before {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
form .form-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: .2em;
|
||||||
|
}
|
||||||
|
form .form-row > label {
|
||||||
|
padding: .5em 1em .5em 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
form .form-row > label + label {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
form .form-row > label.switch + label {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
form .form-row > input {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
form .form-row > span {
|
||||||
|
flex: 2;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
form .form-row input[type="checkbox"] {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
form .form-row > input,
|
||||||
|
form .form-row > span {
|
||||||
|
flex: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 460px) {
|
||||||
|
form .form-row.wrapped {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
form .form-row.wrapped * {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 992px) {
|
||||||
|
form .form-row > input,
|
||||||
|
form .form-row > span {
|
||||||
|
flex: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 1200px) {
|
||||||
|
form .form-row > input,
|
||||||
|
form .form-row > span {
|
||||||
|
flex: 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sui input[type="text"],
|
||||||
|
.sui input[type="password"] {
|
||||||
|
height: 32px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #eeeeee;
|
||||||
|
border-bottom: solid 1px #097479;
|
||||||
|
}
|
||||||
|
.sui input[type="text"]:focus,
|
||||||
|
.sui input[type="password"]:focus,
|
||||||
|
.sui input[type="text"]:hover,
|
||||||
|
.sui input[type="password"]:hover {
|
||||||
|
outline: none;
|
||||||
|
border-bottom: 1px solid #0eb8c0;
|
||||||
|
}
|
||||||
|
.sui input[type="checkbox"] {
|
||||||
|
transform: scale(2);
|
||||||
|
}
|
||||||
|
.ColorPicker {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
}
|
||||||
|
.sui select {
|
||||||
|
flex: 5;
|
||||||
|
padding: .5em;
|
||||||
|
color: #eeeeee;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-bottom: solid 1px #097479;
|
||||||
|
}
|
||||||
|
.sui select:focus,
|
||||||
|
.sui select:hover {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
border-bottom: solid 1px #0eb8c0 !important;
|
||||||
|
}
|
||||||
|
.sui select option {
|
||||||
|
background: #333333;
|
||||||
|
}
|
||||||
41
lib/readme.txt
Normal file
41
lib/readme.txt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
This directory is intended for the project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link to executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in separate directory, like
|
||||||
|
"lib/private_lib/[here are source files]".
|
||||||
|
|
||||||
|
For example, see how can be organized `Foo` and `Bar` libraries:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- readme.txt --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
Then in `src/main.c` you should use:
|
||||||
|
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
// rest H/C/CPP code
|
||||||
|
|
||||||
|
PlatformIO will find your libraries automatically, configure preprocessor's
|
||||||
|
include paths and build them.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- http://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
25
library.json
Normal file
25
library.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "sprocket-plugin-template",
|
||||||
|
"keywords": "sprocket, plugin",
|
||||||
|
"description": "Template for a sprocket plugin",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Patrick Balsiger",
|
||||||
|
"email": "patrick.balsiger@wirelos.net",
|
||||||
|
"url": "https://gitlab.com/0x1d"
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.com/wirelos/sprocket-plugin-template"
|
||||||
|
},
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "espressif8266, esp32",
|
||||||
|
"examples": "examples/*",
|
||||||
|
"export": {
|
||||||
|
"exclude":
|
||||||
|
[
|
||||||
|
"src/examples/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
29
platformio.ini
Normal file
29
platformio.ini
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
[platformio]
|
||||||
|
env_default = basic
|
||||||
|
|
||||||
|
[common]
|
||||||
|
framework = arduino
|
||||||
|
platform = espressif8266
|
||||||
|
board = esp12e
|
||||||
|
upload_speed = 921600
|
||||||
|
monitor_baud = 115200
|
||||||
|
lib_deps =
|
||||||
|
Hash
|
||||||
|
TaskScheduler
|
||||||
|
SPIFFS
|
||||||
|
ArduinoJson
|
||||||
|
ArduinoOTA
|
||||||
|
ESPAsyncTCP
|
||||||
|
ESP8266mDNS
|
||||||
|
ESP Async WebServer
|
||||||
|
painlessMesh
|
||||||
|
https://gitlab.com/wirelos/sprocket-lib.git#develop
|
||||||
|
|
||||||
|
[env:basic]
|
||||||
|
src_filter = +<*> -<examples/> +<examples/basic/>
|
||||||
|
platform = ${common.platform}
|
||||||
|
board = ${common.board}
|
||||||
|
upload_speed = ${common.upload_speed}
|
||||||
|
monitor_baud = ${common.monitor_baud}
|
||||||
|
framework = ${common.framework}
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
126
src/WebApiPlugin.cpp
Normal file
126
src/WebApiPlugin.cpp
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef __WEBAPI_PLUGIN__
|
||||||
|
#define __WEBAPI_PLUGIN__
|
||||||
|
|
||||||
|
#include <TaskSchedulerDeclarations.h>
|
||||||
|
#include <Sprocket.h>
|
||||||
|
#include <Updater.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "utils/utils_print.h"
|
||||||
|
#include "utils/utils_web.h"
|
||||||
|
#include "WebServerPlugin.cpp"
|
||||||
|
#include "WebConfigPlugin.cpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
// TODO headerfile
|
||||||
|
// FIXME constants
|
||||||
|
|
||||||
|
class WebApiPlugin : public Plugin
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebServer *server;
|
||||||
|
AsyncWebSocket *ws;
|
||||||
|
SprocketMessage currentMessage;
|
||||||
|
|
||||||
|
WebApiPlugin(AsyncWebServer *_server)
|
||||||
|
{
|
||||||
|
server = _server;
|
||||||
|
Update.runAsync(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate(Scheduler *_scheduler)
|
||||||
|
{
|
||||||
|
ws = new AsyncWebSocket("/ws");
|
||||||
|
ws->onEvent(bind(&WebApiPlugin::onWsEvent, this, _1, _2, _3, _4, _5, _6));
|
||||||
|
server->addHandler(ws);
|
||||||
|
server->on("/api", HTTP_POST, bind(&WebApiPlugin::postRequestHandler, this, _1));
|
||||||
|
server->on("/update", HTTP_GET, bind(&WebApiPlugin::simpleFirmwareUploadFormvoid, this, _1));
|
||||||
|
server->on("/update", HTTP_POST, bind(&WebApiPlugin::onFirmwareUpdateRequest, this, _1), bind(&WebApiPlugin::onFirmwareUpload, this, _1, _2, _3, _4, _5, _6));
|
||||||
|
subscribe("ws/broadcast", bind(&WebApiPlugin::wsBroadcast, this, _1));
|
||||||
|
PRINT_MSG(Serial, "WEB", "API activated");
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsBroadcast(String msg)
|
||||||
|
{
|
||||||
|
ws->textAll(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void postRequestHandler(AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
PRINT_MSG(Serial, "WEB", "POST WebApiPlugin");
|
||||||
|
currentMessage.topic = WebUtils::getRequestParameterOrDefault(request, "topic", "");
|
||||||
|
currentMessage.payload = WebUtils::getRequestParameterOrDefault(request, "payload", "");
|
||||||
|
currentMessage.broadcast = atoi(WebUtils::getRequestParameterOrDefault(request, "broadcast", "0").c_str());
|
||||||
|
String msg = currentMessage.toJsonString();
|
||||||
|
publish(currentMessage.topic, currentMessage.payload);
|
||||||
|
request->send(200, "text/plain", msg);
|
||||||
|
}
|
||||||
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
// FIXME to limitted
|
||||||
|
if (type == WS_EVT_DATA)
|
||||||
|
{
|
||||||
|
String frame = WebUtils::parseFrameAsString(type, arg, data, len, 0);
|
||||||
|
dispatch(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simpleFirmwareUploadFormvoid(AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
request->send(200, "text/html", "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void onFirmwareUpdateRequest(AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
bool hasError = !Update.hasError();
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", hasError ? "OK" : "FAIL");
|
||||||
|
response->addHeader("Connection", "close");
|
||||||
|
request->send(response);
|
||||||
|
publish("esp/reboot", String(hasError));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onFirmwareUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||||
|
{
|
||||||
|
if (!index)
|
||||||
|
{
|
||||||
|
PRINT_MSG(Serial, "OTA", "Update Start %s", filename.c_str());
|
||||||
|
Update.runAsync(true);
|
||||||
|
if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000))
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Update.hasError())
|
||||||
|
{
|
||||||
|
if (Update.write(data, len) != len)
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (final)
|
||||||
|
{
|
||||||
|
if (Update.end(true))
|
||||||
|
{
|
||||||
|
PRINT_MSG(Serial, "OTA", "Update Success with %uB", index + len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatch(String &msg)
|
||||||
|
{
|
||||||
|
currentMessage.fromJsonString(msg);
|
||||||
|
if (currentMessage.valid)
|
||||||
|
{
|
||||||
|
publish(currentMessage.topic, currentMessage.payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
56
src/WebConfigPlugin.cpp
Normal file
56
src/WebConfigPlugin.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef __WEB_CONFIG_PLUGIN_H__
|
||||||
|
#define __WEB_CONFIG_PLUGIN_H__
|
||||||
|
|
||||||
|
#include <FS.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <TaskSchedulerDeclarations.h>
|
||||||
|
#include "Plugin.h"
|
||||||
|
#include "WebServerConfig.h"
|
||||||
|
#include "utils/utils_print.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
class WebConfigPlugin : public Plugin
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
AsyncWebServer *server;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebConfigPlugin(AsyncWebServer *webServer)
|
||||||
|
{
|
||||||
|
server = webServer;
|
||||||
|
server->serveStatic("/config.json", SPIFFS, "config.json");
|
||||||
|
}
|
||||||
|
void activate(Scheduler *userScheduler)
|
||||||
|
{
|
||||||
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
PRINT_MSG(Serial, "WEB", "GET /heap");
|
||||||
|
request->send(200, "text/plain", String(ESP.getFreeHeap()));
|
||||||
|
});
|
||||||
|
server->on("/restart", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
|
PRINT_MSG(Serial, "WEB", "POST /restart");
|
||||||
|
ESP.restart();
|
||||||
|
});
|
||||||
|
server->on("/config", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||||
|
PRINT_MSG(Serial, "WEB", "POST /config");
|
||||||
|
if (request->hasParam("config", true) && request->hasParam("fileName", true))
|
||||||
|
{
|
||||||
|
String inStr = request->getParam("config", true)->value();
|
||||||
|
String fileName = request->getParam("fileName", true)->value();
|
||||||
|
File f = SPIFFS.open(fileName, "w");
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
PRINT_MSG(Serial, "WEB", String(String("file open for read failed: ") + fileName).c_str());
|
||||||
|
}
|
||||||
|
PRINT_MSG(Serial, "WEB", String(String("writing to SPIFFS file: ") + fileName).c_str());
|
||||||
|
f.print(inStr);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
request->redirect("/");
|
||||||
|
});
|
||||||
|
PRINT_MSG(Serial, "WEB", "WebConfig activated");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
15
src/WebServerConfig.h
Normal file
15
src/WebServerConfig.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __WEB_SERVER_CONFIG__
|
||||||
|
#define __WEB_SERVER_CONFIG__
|
||||||
|
|
||||||
|
struct WebServerConfig
|
||||||
|
{
|
||||||
|
const char *contextPath;
|
||||||
|
const char *docRoot;
|
||||||
|
const char *defaultFile;
|
||||||
|
int port;
|
||||||
|
int useBasicAuth;
|
||||||
|
const char *user;
|
||||||
|
const char *password;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
43
src/WebServerPlugin.cpp
Normal file
43
src/WebServerPlugin.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __WEB_SERVER_PLUGIN__
|
||||||
|
#define __WEB_SERVER_PLUGIN__
|
||||||
|
|
||||||
|
#include <FS.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include "TaskSchedulerDeclarations.h"
|
||||||
|
#include "Plugin.h"
|
||||||
|
#include "WebServerConfig.h"
|
||||||
|
#include "utils/utils_print.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
class WebServerPlugin : public Plugin
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
WebServerConfig config;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebServer *server;
|
||||||
|
WebServerPlugin(WebServerConfig cfg)
|
||||||
|
{
|
||||||
|
config = cfg;
|
||||||
|
server = new AsyncWebServer(config.port);
|
||||||
|
}
|
||||||
|
WebServerPlugin(WebServerConfig cfg, AsyncWebServer *webServer)
|
||||||
|
{
|
||||||
|
config = cfg;
|
||||||
|
server = webServer;
|
||||||
|
}
|
||||||
|
void activate(Scheduler *userScheduler)
|
||||||
|
{
|
||||||
|
AsyncStaticWebHandler &staticWebHandler = server->serveStatic(config.contextPath, SPIFFS, config.docRoot).setDefaultFile(config.defaultFile);
|
||||||
|
if (config.useBasicAuth)
|
||||||
|
{
|
||||||
|
staticWebHandler.setAuthentication(config.user, config.password);
|
||||||
|
}
|
||||||
|
server->begin();
|
||||||
|
PRINT_MSG(Serial, "WEB", "Server activated");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
24
src/examples/basic/config.h
Normal file
24
src/examples/basic/config.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __DEVICE_CONFIG__
|
||||||
|
#define __DEVICE_CONFIG__
|
||||||
|
|
||||||
|
// Scheduler config
|
||||||
|
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||||
|
#define _TASK_STD_FUNCTION
|
||||||
|
#define _TASK_PRIORITY
|
||||||
|
|
||||||
|
// Chip config
|
||||||
|
#define SPROCKET_TYPE "SPROCKET"
|
||||||
|
#define SERIAL_BAUD_RATE 115200
|
||||||
|
#define STARTUP_DELAY 1000
|
||||||
|
|
||||||
|
// network config
|
||||||
|
#define SPROCKET_MODE 1
|
||||||
|
#define WIFI_CHANNEL 11
|
||||||
|
#define AP_SSID "sprocket"
|
||||||
|
#define AP_PASSWORD "th3r31sn0sp00n"
|
||||||
|
#define STATION_SSID "MyAP"
|
||||||
|
#define STATION_PASSWORD "th3r31sn0sp00n"
|
||||||
|
#define HOSTNAME "sprocket"
|
||||||
|
#define CONNECT_TIMEOUT 10000
|
||||||
|
|
||||||
|
#endif
|
||||||
46
src/examples/basic/main.cpp
Normal file
46
src/examples/basic/main.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "WiFiNet.h"
|
||||||
|
#include "Sprocket.h"
|
||||||
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
|
#include "WebServerConfig.h"
|
||||||
|
#include "WebServerPlugin.cpp"
|
||||||
|
#include "WebConfigPlugin.cpp"
|
||||||
|
#include "WebApiPlugin.cpp"
|
||||||
|
|
||||||
|
WiFiNet *network;
|
||||||
|
Sprocket *sprocket;
|
||||||
|
AsyncWebServer *server;
|
||||||
|
WebServerPlugin *webServerPlugin;
|
||||||
|
WebConfigPlugin *webConfigPlugin;
|
||||||
|
WebApiPlugin *webApiPlugin;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
sprocket = new Sprocket({STARTUP_DELAY, SERIAL_BAUD_RATE});
|
||||||
|
webServerPlugin = new WebServerPlugin({"/", "/www", "index.html", 80});
|
||||||
|
webConfigPlugin = new WebConfigPlugin(webServerPlugin->server);
|
||||||
|
webApiPlugin = new WebApiPlugin(webServerPlugin->server);
|
||||||
|
|
||||||
|
sprocket->addPlugin(webServerPlugin);
|
||||||
|
sprocket->addPlugin(webConfigPlugin);
|
||||||
|
sprocket->addPlugin(webApiPlugin);
|
||||||
|
|
||||||
|
network = new WiFiNet(
|
||||||
|
SPROCKET_MODE,
|
||||||
|
STATION_SSID,
|
||||||
|
STATION_PASSWORD,
|
||||||
|
AP_SSID,
|
||||||
|
AP_PASSWORD,
|
||||||
|
HOSTNAME,
|
||||||
|
CONNECT_TIMEOUT);
|
||||||
|
network->connect();
|
||||||
|
|
||||||
|
sprocket->activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
sprocket->loop();
|
||||||
|
yield();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user