mirror of
https://gitlab.com/zwirbel/tardis.git
synced 2025-12-14 17:35:23 +01:00
tardis base
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.pioenvs
|
||||||
|
.piolibdeps
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
data/config.json
|
||||||
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 < https://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
|
||||||
|
# < https://docs.platformio.org/page/ci/travis.html >
|
||||||
|
#
|
||||||
|
# * User Guide for `platformio ci` command
|
||||||
|
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Please choose 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 be 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
13
data/example.config.json
Normal file
13
data/example.config.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"stationMode": 0,
|
||||||
|
"hostname": "illucat",
|
||||||
|
"apSSID": "illucat",
|
||||||
|
"apPassword": "illumination",
|
||||||
|
"connectTimeout": 20000,
|
||||||
|
"stationSSID": "MyWifi",
|
||||||
|
"stationPassword": "myWifiPassword",
|
||||||
|
"meshSSID": "illucat",
|
||||||
|
"meshPassword": "illumination",
|
||||||
|
"meshPort": 5555,
|
||||||
|
"channel": 5
|
||||||
|
}
|
||||||
6
data/ircConfig.json
Normal file
6
data/ircConfig.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"ircServer": "chat.freenode.net",
|
||||||
|
"ircPort": 6665,
|
||||||
|
"ircNickname": "wobbly",
|
||||||
|
"ircUser": "wibblywobbly"
|
||||||
|
}
|
||||||
6
data/mqttConfig.json
Normal file
6
data/mqttConfig.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mqttClientName" : "tardis",
|
||||||
|
"mqttBrokerHost" : "192.168.1.2",
|
||||||
|
"mqttBrokerPort" : 1883,
|
||||||
|
"mqttRootTopic" : "wirelos/led/tardis"
|
||||||
|
}
|
||||||
7
data/pixelConfig.json
Normal file
7
data/pixelConfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"pin": 4,
|
||||||
|
"length": 8,
|
||||||
|
"brightness": 127,
|
||||||
|
"updateInterval": 100,
|
||||||
|
"defaultColor": 100
|
||||||
|
}
|
||||||
4
data/pixelState.json
Normal file
4
data/pixelState.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"mode": 3,
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
BIN
data/www/favicon-32x32.png
Normal file
BIN
data/www/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
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 |
1347
data/www/gradients.json
Normal file
1347
data/www/gradients.json
Normal file
File diff suppressed because it is too large
Load Diff
96
data/www/index.html
Normal file
96
data/www/index.html
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>IlluCat</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">
|
||||||
|
<form class="param-control container collapsible open" action="#" method="POST">
|
||||||
|
<span class="heading">Pixels</span>
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
<li class="form-row ParamSelect"
|
||||||
|
data-label="Hue"
|
||||||
|
data-name="hue"
|
||||||
|
data-topic="pixels/hue"
|
||||||
|
data-default="0"
|
||||||
|
data-external="/gradients.json"
|
||||||
|
></li>
|
||||||
|
<li class="form-row ParamColor"
|
||||||
|
data-name="color"
|
||||||
|
data-topic="pixels/color"
|
||||||
|
data-label="Color">
|
||||||
|
</li>
|
||||||
|
<li class="form-row ParamColor"
|
||||||
|
data-name="color"
|
||||||
|
data-topic="pixels/color2"
|
||||||
|
data-label="Color 2">
|
||||||
|
</li>
|
||||||
|
<!-- data-entries='[{"text": "Color", "value": "0"}, {"text": "Rainbow", "value": "1"}, {"text": "TheaterChase", "value": "2"}, {"text": "Wipe", "value": "3"}, {"text": "Scanner", "value": "4"}, {"text": "Fade", "value": "5"}]' -->
|
||||||
|
<li class="form-row ParamSelect"
|
||||||
|
data-label="Pattern"
|
||||||
|
data-name="pattern"
|
||||||
|
data-topic="pixels/pattern"
|
||||||
|
data-default="0"
|
||||||
|
data-entries='[{"text": "None", "value": "0"}, {"text": "Rainbow", "value": "1"}, {"text": "TheaterChase", "value": "2"}, {"text": "Color Wipe", "value": "3"}, {"text": "Scanner", "value": "4"}, {"text": "Fade", "value": "5"}, {"text": "Fire", "value": "6"}]'
|
||||||
|
></li>
|
||||||
|
<li class="form-row ParamSlider"
|
||||||
|
data-name="brightness"
|
||||||
|
data-min="0"
|
||||||
|
data-max="255"
|
||||||
|
data-value="64"
|
||||||
|
data-topic="pixels/brightness"
|
||||||
|
data-label="Brightness">
|
||||||
|
</li>
|
||||||
|
<li class="form-row ParamSlider"
|
||||||
|
data-name="totalSteps"
|
||||||
|
data-min="1"
|
||||||
|
data-max="255"
|
||||||
|
data-value="16"
|
||||||
|
data-topic="pixels/totalSteps"
|
||||||
|
data-label="Steps">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="settings container collapsible open">
|
||||||
|
<span class="heading">IlluChat</span>
|
||||||
|
<div class="content">
|
||||||
|
<div class="Chat" data-name="Ruedi" data-label="foo" data-placeholder="msg" data-topic="out/chat/log"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
<h2>NeoPixel</h2>
|
||||||
|
<div class="Form" data-fileName="/pixelConfig.json" data-name="configForm" data-from="/pixelConfig.json" data-endpoint="/config"></div>
|
||||||
|
<h2>MQTT</h2>
|
||||||
|
<div class="Form" data-fileName="/mqttConfig.json" data-name="configForm" data-from="/mqttConfig.json" data-endpoint="/config"></div>
|
||||||
|
<h2>IRC</h2>
|
||||||
|
<div class="Form" data-fileName="/ircConfig.json" data-name="configForm" data-from="/ircConfig.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>
|
||||||
|
<form method='POST' action='/update' enctype='multipart/form-data'>
|
||||||
|
<input type='file' name='update'><input type='submit' value='Update'>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
<button class="js-restart">Restart</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
12359
data/www/script.js
Normal file
12359
data/www/script.js
Normal file
File diff suppressed because it is too large
Load Diff
329
data/www/styles.css
Normal file
329
data/www/styles.css
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
.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;
|
||||||
|
}
|
||||||
|
.Chat .message-container {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.Chat .message-container .messages {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
.Chat .message-container .messages .user-label {
|
||||||
|
color: lightblue;
|
||||||
|
}
|
||||||
|
.Chat .message-container .messages .user-label:before {
|
||||||
|
color: #097479;
|
||||||
|
content: '<';
|
||||||
|
}
|
||||||
|
.Chat .message-container .messages .user-label:after {
|
||||||
|
color: #097479;
|
||||||
|
content: '>';
|
||||||
|
}
|
||||||
|
.Chat .message-container .messages .message-text {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
106
data/www/test-controls.html
Normal file
106
data/www/test-controls.html
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<!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" sizes="16x16" href="/favicon-32x32.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="sui">
|
||||||
|
<div class="content">
|
||||||
|
<!-- <form class="param-control container open collapsible">
|
||||||
|
<span class="heading">Debug</span>
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
<li class="form-row ParamWs"
|
||||||
|
data-name="scrollText"
|
||||||
|
data-label="Audio"
|
||||||
|
data-placeholder="some scroll text"
|
||||||
|
data-endpoint="audiosprocket.lan/audio">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</form> -->
|
||||||
|
<form class="param-control container collapsible open" action="#" method="POST">
|
||||||
|
<span class="heading">Strip</span>
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
<li class="form-row ParamColor"
|
||||||
|
data-mode="2"
|
||||||
|
data-name="color"
|
||||||
|
data-label="Color">
|
||||||
|
</li>
|
||||||
|
<li class="form-row ParamColor"
|
||||||
|
data-mode="2"
|
||||||
|
data-name="color2"
|
||||||
|
data-label="Color 2">
|
||||||
|
</li>
|
||||||
|
<li class="form-row ParamSelect"
|
||||||
|
data-label="Pattern"
|
||||||
|
data-name="pattern"
|
||||||
|
></li>
|
||||||
|
<li class="form-row LedStripPatternSwitch"
|
||||||
|
data-group="stripPattern"
|
||||||
|
data-id="1"
|
||||||
|
data-mode="3"
|
||||||
|
data-name="Rainbow"
|
||||||
|
data-label="Rainbow">
|
||||||
|
</li>
|
||||||
|
<li class="form-row LedStripPatternSwitch"
|
||||||
|
data-group="stripPattern"
|
||||||
|
data-name="TheaterChase"
|
||||||
|
data-label="Theater Chase"
|
||||||
|
data-id="2"
|
||||||
|
data-mode="3">
|
||||||
|
</li>
|
||||||
|
<li class="form-row LedStripPatternSwitch"
|
||||||
|
data-group="stripPattern"
|
||||||
|
data-name="Scanner"
|
||||||
|
data-label="Scanner"
|
||||||
|
data-id="4"
|
||||||
|
data-mode="3">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="settings container collapsible open">
|
||||||
|
<span class="heading">WiFi Settings</span>
|
||||||
|
<div class="content">
|
||||||
|
<!-- <div class="Form" data-name="configForm" data-endpoint="/config.json"></div> -->
|
||||||
|
<form action="/wifiConfig" method="POST">
|
||||||
|
<!-- <li class="form-row">
|
||||||
|
<label for="ap">AP Mode</label>
|
||||||
|
<label class="switch ap-mode">
|
||||||
|
<input type="checkbox" name="apMode">
|
||||||
|
<span class="slider round" data-bind="apMode" data-state="false"></span>
|
||||||
|
</label>
|
||||||
|
</li -->
|
||||||
|
<li class="form-row">
|
||||||
|
<label for="ssid">SSID</label>
|
||||||
|
<input type="text" name="ssid" placeholder="Default AP: Th1ngs4P">
|
||||||
|
</li>
|
||||||
|
<li class="form-row">
|
||||||
|
<label for="password">PW</label>
|
||||||
|
<input type="password" name="password" placeholder="Default: th3r31sn0sp00n">
|
||||||
|
</li>
|
||||||
|
<li class="form-row">
|
||||||
|
<label for="hostName">Hostname</label>
|
||||||
|
<input type="text" name="hostName" placeholder="Default: 192.168.1.143">
|
||||||
|
</li>
|
||||||
|
<li class="form-row">
|
||||||
|
<button type="submit">Save</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
39
include/README
Normal file
39
include/README
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||||
46
lib/README
Normal file
46
lib/README
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
38
platformio.ini
Normal file
38
platformio.ini
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
[platformio]
|
||||||
|
env_default = build
|
||||||
|
|
||||||
|
[common]
|
||||||
|
framework = arduino
|
||||||
|
platform = espressif8266
|
||||||
|
board = esp12e
|
||||||
|
upload_speed = 921600
|
||||||
|
monitor_baud = 115200
|
||||||
|
lib_deps =
|
||||||
|
Hash
|
||||||
|
TaskScheduler
|
||||||
|
SPIFFS
|
||||||
|
ArduinoOTA
|
||||||
|
ArduinoJson
|
||||||
|
ArduinoIRC
|
||||||
|
Adafruit NeoPixel
|
||||||
|
PubSubClient
|
||||||
|
ESPAsyncTCP
|
||||||
|
ESP8266mDNS
|
||||||
|
ESP Async WebServer
|
||||||
|
rc-switch
|
||||||
|
https://gitlab.com/wirelos/sprocket-lib.git#develop
|
||||||
|
https://gitlab.com/wirelos/sprocket-plugin-neopixel.git
|
||||||
|
https://gitlab.com/wirelos/sprocket-network-wifi.git
|
||||||
|
https://gitlab.com/wirelos/sprocket-plugin-web.git
|
||||||
|
https://gitlab.com/wirelos/sprocket-plugin-mqtt.git
|
||||||
|
https://gitlab.com/wirelos/sprocket-plugin-irc.git
|
||||||
|
https://gitlab.com/wirelos/sprocket-plugin-rcswitch.git
|
||||||
|
|
||||||
|
[env:build]
|
||||||
|
;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}
|
||||||
62
src/config.h
Normal file
62
src/config.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef __TARDIS_CONFIG__
|
||||||
|
#define __TARDIS_CONFIG__
|
||||||
|
|
||||||
|
// Scheduler config
|
||||||
|
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||||
|
#define _TASK_STD_FUNCTION
|
||||||
|
#define _TASK_PRIORITY
|
||||||
|
|
||||||
|
// Chip config
|
||||||
|
#define SPROCKET_TYPE "ILLUCAT"
|
||||||
|
#define SERIAL_BAUD_RATE 115200
|
||||||
|
#define STARTUP_DELAY 1000
|
||||||
|
|
||||||
|
// Network config
|
||||||
|
#define WIFI_MODE 1
|
||||||
|
#define WIFI_CHANNEL 11
|
||||||
|
#define AP_SSID "tardis"
|
||||||
|
#define AP_PASSWORD "th3r31sn0sp00n"
|
||||||
|
#define STATION_SSID "MyAP"
|
||||||
|
#define STATION_PASSWORD "th3r31sn0sp00n"
|
||||||
|
#define HOSTNAME "tardis"
|
||||||
|
#define CONNECT_TIMEOUT 10000
|
||||||
|
|
||||||
|
// config files
|
||||||
|
#define PIXEL_CONFIG_FILE "/pixelConfig.json"
|
||||||
|
#define MQTT_CONFIG_FILE "/mqttConfig.json"
|
||||||
|
#define IRC_CONFIG_FILE "/ircConfig.json"
|
||||||
|
|
||||||
|
// NeoPixel
|
||||||
|
#define LED_STRIP_PIN D2
|
||||||
|
#define LED_STRIP_LENGTH 8
|
||||||
|
#define LED_STRIP_BRIGHTNESS 48
|
||||||
|
#define LED_STRIP_UPDATE_INTERVAL 200
|
||||||
|
#define LED_STRIP_DEFAULT_COLOR 100
|
||||||
|
#define COLOR_CONNECTED LED_STRIP_DEFAULT_COLOR
|
||||||
|
#define COLOR_NOT_CONNECTED 255
|
||||||
|
|
||||||
|
#define IRC_SERVER "chat.freenode.net"
|
||||||
|
#define IRC_PORT 6665
|
||||||
|
#define IRC_NICKNAME ""
|
||||||
|
#define IRC_USER ""
|
||||||
|
|
||||||
|
// OTA config
|
||||||
|
#define OTA_PORT 8266
|
||||||
|
#define OTA_PASSWORD ""
|
||||||
|
|
||||||
|
// WebServer
|
||||||
|
#define WEB_CONTEXT_PATH "/"
|
||||||
|
#define WEB_DOC_ROOT "/www"
|
||||||
|
#define WEB_DEFAULT_FILE "index.html"
|
||||||
|
#define WEB_PORT 80
|
||||||
|
|
||||||
|
// mqtt config
|
||||||
|
#define MQTT_CLIENT_NAME "tardis"
|
||||||
|
#define MQTT_HOST "192.168.1.2"
|
||||||
|
#define MQTT_PORT 1883
|
||||||
|
#define MQTT_ROOT_TOPIC "wirelos/led/tardis"
|
||||||
|
|
||||||
|
// RC Switch
|
||||||
|
#define PIN_RC_TX D8
|
||||||
|
|
||||||
|
#endif
|
||||||
106
src/main.cpp
Normal file
106
src/main.cpp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include <WiFiNet.h>
|
||||||
|
#include <Sprocket.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <WebServerConfig.h>
|
||||||
|
#include <WebServerPlugin.h>
|
||||||
|
#include <WebConfigPlugin.h>
|
||||||
|
#include <WebApiPlugin.h>
|
||||||
|
#include <PixelPlugin.h>
|
||||||
|
#include <IrcPlugin.h>
|
||||||
|
#include <OtaTcpPlugin.cpp>
|
||||||
|
#include <MqttPlugin.h>
|
||||||
|
#include <RcSwitchPlugin.h>
|
||||||
|
|
||||||
|
WiFiNet *network;
|
||||||
|
Sprocket *sprocket;
|
||||||
|
WebServerPlugin *webServerPlugin;
|
||||||
|
WebConfigPlugin *webConfigPlugin;
|
||||||
|
WebApiPlugin *webApiPlugin;
|
||||||
|
PixelPlugin *pixelPlugin;
|
||||||
|
IrcPlugin *ircPlugin;
|
||||||
|
OtaTcpPlugin *otaTcpPlugin;
|
||||||
|
MqttPlugin *mqttPlugin;
|
||||||
|
RcSwitchPlugin *rcSwitchPlugin;
|
||||||
|
|
||||||
|
void serveWebConfig(AsyncWebServer *server)
|
||||||
|
{
|
||||||
|
server->serveStatic(PIXEL_CONFIG_FILE, SPIFFS, "pixelConfig.json");
|
||||||
|
server->serveStatic(IRC_CONFIG_FILE, SPIFFS, "ircConfig.json");
|
||||||
|
server->serveStatic(MQTT_CONFIG_FILE, SPIFFS, "mqttConfig.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
void subscribeChat(Sprocket *sprocket)
|
||||||
|
{
|
||||||
|
sprocket->subscribe("irc/connected", [sprocket](String msg) {
|
||||||
|
if (atoi(msg.c_str()))
|
||||||
|
{
|
||||||
|
sprocket->subscribe("irc/log", [sprocket](String msg) {
|
||||||
|
PRINT_MSG(Serial, "CHAT", String("irc/log: " + msg).c_str());
|
||||||
|
sprocket->publish("ws/broadcast", msg);
|
||||||
|
});
|
||||||
|
sprocket->subscribe("out/chat/log", [sprocket](String msg) {
|
||||||
|
PRINT_MSG(Serial, "CHAT", String("out/chat/log: " + msg).c_str());
|
||||||
|
sprocket->publish("irc/sendMessage", msg);
|
||||||
|
sprocket->publish("ws/broadcast", "You:" + msg);
|
||||||
|
});
|
||||||
|
sprocket->publish("chat/connected", "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void subscribeTardis(Sprocket *sprocket, NeoPattern *pixels)
|
||||||
|
{
|
||||||
|
sprocket->subscribe("tardis/wibbly", [pixels](String msg) {
|
||||||
|
pixels->Fade(0, pixels->Color(255, 255, 255), 4, 100, FORWARD);
|
||||||
|
});
|
||||||
|
sprocket->subscribe("tardis/wobbly", [pixels](String msg) {
|
||||||
|
pixels->Scanner(pixels->Color(0, 255, 255), 100);
|
||||||
|
});
|
||||||
|
sprocket->subscribe("irc/connected", [sprocket](String msg) {
|
||||||
|
sprocket->publish("tardis/wobbly", msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void start(Sprocket *sprocket)
|
||||||
|
{
|
||||||
|
sprocket->activate();
|
||||||
|
sprocket->publish("tardis/wibbly", "");
|
||||||
|
sprocket->publish("irc/connect", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
sprocket = new Sprocket({STARTUP_DELAY, SERIAL_BAUD_RATE});
|
||||||
|
pixelPlugin = new PixelPlugin({LED_STRIP_PIN, LED_STRIP_LENGTH, LED_STRIP_BRIGHTNESS, LED_STRIP_UPDATE_INTERVAL});
|
||||||
|
ircPlugin = new IrcPlugin({IRC_SERVER, IRC_PORT, IRC_NICKNAME, IRC_USER});
|
||||||
|
mqttPlugin = new MqttPlugin({MQTT_CLIENT_NAME, MQTT_HOST, MQTT_PORT, MQTT_ROOT_TOPIC});
|
||||||
|
webServerPlugin = new WebServerPlugin({WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE, WEB_PORT});
|
||||||
|
webConfigPlugin = new WebConfigPlugin(webServerPlugin->server);
|
||||||
|
webApiPlugin = new WebApiPlugin(webServerPlugin->server);
|
||||||
|
otaTcpPlugin = new OtaTcpPlugin({OTA_PORT, OTA_PASSWORD});
|
||||||
|
rcSwitchPlugin = new RcSwitchPlugin({PIN_RC_TX});
|
||||||
|
network = new WiFiNet(WIFI_MODE, STATION_SSID, STATION_PASSWORD, AP_SSID, AP_PASSWORD, HOSTNAME, CONNECT_TIMEOUT);
|
||||||
|
|
||||||
|
sprocket->addPlugin(pixelPlugin);
|
||||||
|
sprocket->addPlugin(webServerPlugin);
|
||||||
|
sprocket->addPlugin(webConfigPlugin);
|
||||||
|
sprocket->addPlugin(webApiPlugin);
|
||||||
|
sprocket->addPlugin(otaTcpPlugin);
|
||||||
|
sprocket->addPlugin(ircPlugin);
|
||||||
|
sprocket->addPlugin(rcSwitchPlugin);
|
||||||
|
sprocket->addPlugin(mqttPlugin);
|
||||||
|
network->connect();
|
||||||
|
|
||||||
|
serveWebConfig(webServerPlugin->server);
|
||||||
|
subscribeChat(sprocket);
|
||||||
|
subscribeTardis(sprocket, pixelPlugin->pixels);
|
||||||
|
start(sprocket);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
sprocket->loop();
|
||||||
|
yield();
|
||||||
|
}
|
||||||
11
test/README
Normal file
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PIO Unit Testing and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/page/plus/unit-testing.html
|
||||||
Reference in New Issue
Block a user