mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
reverting version
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
|
lib/libraies-master
|
||||||
|
|
||||||
2
data/.exclude.files
Normal file
2
data/.exclude.files
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/*.js.gz
|
||||||
|
/.exclude.files
|
||||||
22
data/config.json
Normal file
22
data/config.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "IoTmanager",
|
||||||
|
"chipID": "",
|
||||||
|
"apssid": "IoTmanager",
|
||||||
|
"appass": "",
|
||||||
|
"routerssid": "VOLODYA",
|
||||||
|
"routerpass": "BELCHENKO",
|
||||||
|
"timezone": 2,
|
||||||
|
"ntp": "pool.ntp.org",
|
||||||
|
"mqttServer": "91.204.228.124",
|
||||||
|
"mqttPort": 1883,
|
||||||
|
"mqttPrefix": "/iotTeam",
|
||||||
|
"mqttUser": "test",
|
||||||
|
"mqttPass": "test",
|
||||||
|
"scen": "1",
|
||||||
|
"pushingboxid": "v7C133E426B0C69E",
|
||||||
|
"weblogin": "admin",
|
||||||
|
"webpass": "admin",
|
||||||
|
"udponoff": "1",
|
||||||
|
"blink": "1",
|
||||||
|
"oneWirePin": "2"
|
||||||
|
}
|
||||||
BIN
data/css/build.css.gz
Normal file
BIN
data/css/build.css.gz
Normal file
Binary file not shown.
658
data/edit.htm
Normal file
658
data/edit.htm
Normal file
@@ -0,0 +1,658 @@
|
|||||||
|
<!--This is the plain html source of the hex encoded Editor-Page embedded in SPIFFSEditor.cpp -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>FS Editor</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
.cm {
|
||||||
|
z-index: 300;
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
display: none;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, .4);
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm ul {
|
||||||
|
list-style: none;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm li {
|
||||||
|
position: relative;
|
||||||
|
min-width: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm span {
|
||||||
|
color: #444;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm li:hover {
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm li:hover span {
|
||||||
|
color: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tvu ul,
|
||||||
|
.tvu li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tvu input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tvu {
|
||||||
|
font: normal 12px Verdana, Arial, Sans-serif;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
color: #444;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tvu span {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding: 0 0 0 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2ceegTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMjIyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9OTlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0lc9eTHYTAAAAAElFTkSuQmCC') no-repeat;
|
||||||
|
background-position: 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tvu span:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||||
|
.tvu {
|
||||||
|
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes webkit-adjacent-element-selector-bugfix {
|
||||||
|
from {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploader {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 28px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding-left: 10px;
|
||||||
|
background-color: #444;
|
||||||
|
color: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tree {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 160px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor,
|
||||||
|
#preview {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 160px;
|
||||||
|
border-left: 1px solid #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview {
|
||||||
|
background-color: #EEE;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loader {
|
||||||
|
position: absolute;
|
||||||
|
top: 36%;
|
||||||
|
right: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
z-index: 10000;
|
||||||
|
border: 8px solid #b5b5b5;
|
||||||
|
/* Grey */
|
||||||
|
border-top: 8px solid #3498db;
|
||||||
|
/* Blue */
|
||||||
|
border-bottom: 8px solid #3498db;
|
||||||
|
/* Blue */
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 240px;
|
||||||
|
height: 240px;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
if (typeof XMLHttpRequest === "undefined") {
|
||||||
|
XMLHttpRequest = function () {
|
||||||
|
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) { }
|
||||||
|
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) { }
|
||||||
|
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { }
|
||||||
|
throw new Error("This browser does not support XMLHttpRequest.");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function ge(a) {
|
||||||
|
return document.getElementById(a);
|
||||||
|
}
|
||||||
|
function ce(a) {
|
||||||
|
return document.createElement(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortByKey(array, key) {
|
||||||
|
return array.sort(function (a, b) {
|
||||||
|
var x = a[key]; var y = b[key];
|
||||||
|
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var QueuedRequester = function () {
|
||||||
|
this.queue = [];
|
||||||
|
this.running = false;
|
||||||
|
this.xmlhttp = null;
|
||||||
|
}
|
||||||
|
QueuedRequester.prototype = {
|
||||||
|
_request: function (req) {
|
||||||
|
this.running = true;
|
||||||
|
if (!req instanceof Object) return;
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
function ajaxCb(x, d) {
|
||||||
|
return function () {
|
||||||
|
if (x.readyState == 4) {
|
||||||
|
ge("loader").style.display = "none";
|
||||||
|
d.callback(x.status, x.responseText);
|
||||||
|
if (that.queue.length === 0) that.running = false;
|
||||||
|
if (that.running) that._request(that.queue.shift());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ge("loader").style.display = "block";
|
||||||
|
|
||||||
|
var p = "";
|
||||||
|
if (req.params instanceof FormData) {
|
||||||
|
p = req.params;
|
||||||
|
} else if (req.params instanceof Object) {
|
||||||
|
for (var key in req.params) {
|
||||||
|
if (p === "")
|
||||||
|
p += (req.method === "GET") ? "?" : "";
|
||||||
|
else
|
||||||
|
p += "&";
|
||||||
|
p += encodeURIComponent(key) + "=" + encodeURIComponent(req.params[key]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xmlhttp = new XMLHttpRequest();
|
||||||
|
this.xmlhttp.onreadystatechange = ajaxCb(this.xmlhttp, req);
|
||||||
|
if (req.method === "GET") {
|
||||||
|
this.xmlhttp.open(req.method, req.url + p, true);
|
||||||
|
this.xmlhttp.send();
|
||||||
|
} else {
|
||||||
|
this.xmlhttp.open(req.method, req.url, true);
|
||||||
|
if (p instanceof String)
|
||||||
|
this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
this.xmlhttp.send(p);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stop: function () {
|
||||||
|
if (this.running) this.running = false;
|
||||||
|
if (this.xmlhttp && this.xmlhttp.readyState < 4) {
|
||||||
|
this.xmlhttp.abort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
add: function (method, url, params, callback) {
|
||||||
|
this.queue.push({ url: url, method: method, params: params, callback: callback });
|
||||||
|
if (!this.running) {
|
||||||
|
this._request(this.queue.shift());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var requests = new QueuedRequester();
|
||||||
|
|
||||||
|
function createFileUploader(element, tree, editor) {
|
||||||
|
var xmlHttp;
|
||||||
|
|
||||||
|
var refresh = ce("button");
|
||||||
|
refresh.innerHTML = 'Refresh List';
|
||||||
|
ge(element).appendChild(refresh);
|
||||||
|
|
||||||
|
var input = ce("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.multiple = false;
|
||||||
|
input.name = "data";
|
||||||
|
input.id = "upload-select";
|
||||||
|
ge(element).appendChild(input);
|
||||||
|
|
||||||
|
var path = ce("input");
|
||||||
|
path.id = "upload-path";
|
||||||
|
path.type = "text";
|
||||||
|
path.name = "path";
|
||||||
|
path.defaultValue = "/";
|
||||||
|
ge(element).appendChild(path);
|
||||||
|
|
||||||
|
var button = ce("button");
|
||||||
|
button.innerHTML = 'Upload';
|
||||||
|
ge(element).appendChild(button);
|
||||||
|
|
||||||
|
var mkfile = ce("button");
|
||||||
|
mkfile.innerHTML = 'Create';
|
||||||
|
ge(element).appendChild(mkfile);
|
||||||
|
|
||||||
|
var filename = ce("input");
|
||||||
|
filename.id = "editor-filename";
|
||||||
|
filename.type = "text";
|
||||||
|
filename.disabled = true;
|
||||||
|
filename.size = 20;
|
||||||
|
ge(element).appendChild(filename);
|
||||||
|
|
||||||
|
var savefile = ce("button");
|
||||||
|
savefile.innerHTML = ' Save ';
|
||||||
|
ge(element).appendChild(savefile);
|
||||||
|
|
||||||
|
function httpPostProcessRequest(status, responseText) {
|
||||||
|
if (status != 200)
|
||||||
|
alert("ERROR[" + status + "]: " + responseText);
|
||||||
|
else
|
||||||
|
tree.refreshPath(path.value);
|
||||||
|
}
|
||||||
|
function createPath(p) {
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", p);
|
||||||
|
requests.add("PUT", "/edit", formData, httpPostProcessRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkfile.onclick = function (e) {
|
||||||
|
createPath(path.value);
|
||||||
|
editor.loadUrl(path.value);
|
||||||
|
path.value = "/";
|
||||||
|
};
|
||||||
|
|
||||||
|
savefile.onclick = function (e) {
|
||||||
|
editor.execCommand('saveCommand');
|
||||||
|
};
|
||||||
|
|
||||||
|
refresh.onclick = function (e) {
|
||||||
|
tree.refreshPath(path.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
button.onclick = function (e) {
|
||||||
|
if (input.files.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", input.files[0], path.value);
|
||||||
|
requests.add("POST", "/edit", formData, httpPostProcessRequest);
|
||||||
|
var uploadPath = ge("upload-path");
|
||||||
|
uploadPath.value = "/";
|
||||||
|
var uploadSelect = ge("upload-select");
|
||||||
|
uploadSelect.value = "";
|
||||||
|
};
|
||||||
|
input.onchange = function (e) {
|
||||||
|
if (input.files.length === 0) return;
|
||||||
|
var filename = input.files[0].name;
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||||
|
if (typeof name !== undefined) {
|
||||||
|
filename = name;
|
||||||
|
}
|
||||||
|
path.value = "/" + filename + "." + ext;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTree(element, editor) {
|
||||||
|
var preview = ge("preview");
|
||||||
|
var treeRoot = ce("div");
|
||||||
|
treeRoot.className = "tvu";
|
||||||
|
ge(element).appendChild(treeRoot);
|
||||||
|
|
||||||
|
function loadDownload(path) {
|
||||||
|
ge('download-frame').src = "/edit?download=" + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPreview(path) {
|
||||||
|
var edfname = ge("editor-filename");
|
||||||
|
edfname.value = path;
|
||||||
|
ge("editor").style.display = "none";
|
||||||
|
preview.style.display = "block";
|
||||||
|
preview.innerHTML = '<img src="/edit?edit=' + path + '&_cb=' + Date.now() + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillFileMenu(el, path) {
|
||||||
|
var list = ce("ul");
|
||||||
|
el.appendChild(list);
|
||||||
|
var action = ce("li");
|
||||||
|
list.appendChild(action);
|
||||||
|
if (isImageFile(path)) {
|
||||||
|
action.innerHTML = "<span>Preview</span>";
|
||||||
|
action.onclick = function (e) {
|
||||||
|
loadPreview(path);
|
||||||
|
if (document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
} else if (isTextFile(path)) {
|
||||||
|
action.innerHTML = "<span>Edit</span>";
|
||||||
|
action.onclick = function (e) {
|
||||||
|
editor.loadUrl(path);
|
||||||
|
if (document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var download = ce("li");
|
||||||
|
list.appendChild(download);
|
||||||
|
download.innerHTML = "<span>Download</span>";
|
||||||
|
download.onclick = function (e) {
|
||||||
|
loadDownload(path);
|
||||||
|
if (document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
var delFile = ce("li");
|
||||||
|
list.appendChild(delFile);
|
||||||
|
delFile.innerHTML = "<span>Delete</span>";
|
||||||
|
delFile.onclick = function (e) {
|
||||||
|
httpDelete(path);
|
||||||
|
if (document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function showContextMenu(event, path, isfile) {
|
||||||
|
var divContext = ce("div");
|
||||||
|
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||||
|
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||||
|
var left = event.clientX + scrollLeft;
|
||||||
|
var top = event.clientY + scrollTop;
|
||||||
|
divContext.className = 'cm';
|
||||||
|
divContext.style.display = 'block';
|
||||||
|
divContext.style.left = left + 'px';
|
||||||
|
divContext.style.top = top + 'px';
|
||||||
|
fillFileMenu(divContext, path);
|
||||||
|
document.body.appendChild(divContext);
|
||||||
|
var width = divContext.offsetWidth;
|
||||||
|
var height = divContext.offsetHeight;
|
||||||
|
divContext.onmouseout = function (e) {
|
||||||
|
if (e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)) {
|
||||||
|
if (document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(divContext);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTreeLeaf(path, name, size) {
|
||||||
|
var leaf = ce("li");
|
||||||
|
leaf.id = name;
|
||||||
|
var label = ce("span");
|
||||||
|
label.innerHTML = name;
|
||||||
|
leaf.appendChild(label);
|
||||||
|
leaf.onclick = function (e) {
|
||||||
|
if (isTextFile(leaf.id.toLowerCase())) {
|
||||||
|
editor.loadUrl(leaf.id);
|
||||||
|
} else if (isImageFile(leaf.id.toLowerCase())) {
|
||||||
|
loadPreview(leaf.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
leaf.oncontextmenu = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
showContextMenu(e, leaf.id, true);
|
||||||
|
};
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addList(parent, path, items) {
|
||||||
|
sortByKey(items, 'name');
|
||||||
|
var list = ce("ul");
|
||||||
|
parent.appendChild(list);
|
||||||
|
var ll = items.length;
|
||||||
|
for (var i = 0; i < ll; i++) {
|
||||||
|
if (items[i].type === "file")
|
||||||
|
list.appendChild(createTreeLeaf(path, items[i].name, items[i].size));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTextFile(path) {
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if (typeof ext !== undefined) {
|
||||||
|
switch (ext) {
|
||||||
|
case "cnv":
|
||||||
|
case "txt":
|
||||||
|
case "htm":
|
||||||
|
case "html":
|
||||||
|
case "js":
|
||||||
|
case "css":
|
||||||
|
case "xml":
|
||||||
|
case "json":
|
||||||
|
case "conf":
|
||||||
|
case "ini":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isImageFile(path) {
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||||
|
if (typeof ext !== undefined) {
|
||||||
|
switch (ext) {
|
||||||
|
case "png":
|
||||||
|
case "jpg":
|
||||||
|
case "jpeg":
|
||||||
|
case "gif":
|
||||||
|
case "bmp":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshPath = function (path) {
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
};
|
||||||
|
|
||||||
|
function delCb(path) {
|
||||||
|
return function (status, responseText) {
|
||||||
|
if (status != 200) {
|
||||||
|
alert("ERROR[" + status + "]: " + responseText);
|
||||||
|
} else {
|
||||||
|
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpDelete(filename) {
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("path", filename);
|
||||||
|
requests.add("DELETE", "/edit", formData, delCb(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCb(parent, path) {
|
||||||
|
return function (status, responseText) {
|
||||||
|
if (status == 200)
|
||||||
|
addList(parent, path, JSON.parse(responseText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpGet(parent, path) {
|
||||||
|
requests.add("GET", "/edit", { list: path }, getCb(parent, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
httpGet(treeRoot, "/");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditor(element, file, lang, theme, type) {
|
||||||
|
function getLangFromFilename(filename) {
|
||||||
|
var lang = "plain";
|
||||||
|
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||||
|
if (typeof ext !== undefined) {
|
||||||
|
switch (ext) {
|
||||||
|
case "cnv": lang = "plain"; break;
|
||||||
|
case "txt": lang = "plain"; break;
|
||||||
|
case "hex": lang = "plain"; break;
|
||||||
|
case "conf": lang = "plain"; break;
|
||||||
|
case "htm": lang = "html"; break;
|
||||||
|
case "js": lang = "javascript"; break;
|
||||||
|
case "css":
|
||||||
|
case "scss":
|
||||||
|
case "php":
|
||||||
|
case "html":
|
||||||
|
case "json":
|
||||||
|
case "xml":
|
||||||
|
case "ini": lang = ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof file === "undefined") file = "/index.html";
|
||||||
|
|
||||||
|
if (typeof lang === "undefined") {
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof theme === "undefined") theme = "textmate";
|
||||||
|
|
||||||
|
if (typeof type === "undefined") {
|
||||||
|
type = "text/" + lang;
|
||||||
|
if (lang === "c_cpp") type = "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
var editor = ace.edit(element);
|
||||||
|
function httpPostProcessRequest(status, responseText) {
|
||||||
|
if (status != 200) alert("ERROR[" + status + "]: " + responseText);
|
||||||
|
}
|
||||||
|
function httpPost(filename, data, type) {
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append("data", new Blob([data], { type: type }), filename);
|
||||||
|
requests.add("POST", "/edit", formData, httpPostProcessRequest);
|
||||||
|
}
|
||||||
|
function httpGetProcessRequest(status, responseText) {
|
||||||
|
ge("preview").style.display = "none";
|
||||||
|
ge("editor").style.display = "block";
|
||||||
|
if (status == 200)
|
||||||
|
editor.setValue(responseText);
|
||||||
|
else
|
||||||
|
editor.setValue("");
|
||||||
|
editor.clearSelection();
|
||||||
|
}
|
||||||
|
function httpGet(theUrl) {
|
||||||
|
requests.add("GET", "/edit", { edit: theUrl }, httpGetProcessRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lang !== "plain") editor.getSession().setMode("ace/mode/" + lang);
|
||||||
|
editor.setTheme("ace/theme/" + theme);
|
||||||
|
editor.$blockScrolling = Infinity;
|
||||||
|
editor.getSession().setUseSoftTabs(true);
|
||||||
|
editor.getSession().setTabSize(2);
|
||||||
|
editor.setHighlightActiveLine(true);
|
||||||
|
editor.setShowPrintMargin(false);
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'saveCommand',
|
||||||
|
bindKey: { win: 'Ctrl-S', mac: 'Command-S' },
|
||||||
|
exec: function (editor) {
|
||||||
|
httpPost(file, editor.getValue() + "", type);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'undoCommand',
|
||||||
|
bindKey: { win: 'Ctrl-Z', mac: 'Command-Z' },
|
||||||
|
exec: function (editor) {
|
||||||
|
editor.getSession().getUndoManager().undo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.commands.addCommand({
|
||||||
|
name: 'redoCommand',
|
||||||
|
bindKey: { win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z' },
|
||||||
|
exec: function (editor) {
|
||||||
|
editor.getSession().getUndoManager().redo(false);
|
||||||
|
},
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
editor.loadUrl = function (filename) {
|
||||||
|
var edfname = ge("editor-filename");
|
||||||
|
edfname.value = filename;
|
||||||
|
file = filename;
|
||||||
|
lang = getLangFromFilename(file);
|
||||||
|
type = "text/" + lang;
|
||||||
|
if (lang !== "plain") editor.getSession().setMode("ace/mode/" + lang);
|
||||||
|
httpGet(file);
|
||||||
|
};
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
function onBodyLoad() {
|
||||||
|
var vars = {};
|
||||||
|
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { vars[key] = value; });
|
||||||
|
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||||
|
var tree = createTree("tree", editor);
|
||||||
|
createFileUploader("uploader", tree, editor);
|
||||||
|
if (typeof vars.file === "undefined") vars.file = "/dev_conf.txt";
|
||||||
|
editor.loadUrl(vars.file);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script id='ace' src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js" type="text/javascript"
|
||||||
|
charset="utf-8"></script>
|
||||||
|
<script>
|
||||||
|
if (typeof ace.edit == "undefined") {
|
||||||
|
var script = document.createElement('script');
|
||||||
|
script.src = "/ace.js";
|
||||||
|
script.async = false;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="onBodyLoad();">
|
||||||
|
<div id="loader" class="loader"></div>
|
||||||
|
<div id="uploader"></div>
|
||||||
|
<div id="tree"></div>
|
||||||
|
<div id="editor"></div>
|
||||||
|
<div id="preview" style="display:none;"></div>
|
||||||
|
<iframe id=download-frame style='display:none;'></iframe>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
BIN
data/favicon.ico
Normal file
BIN
data/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icon.jpeg
Normal file
BIN
data/icon.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
data/index.htm.gz
Normal file
BIN
data/index.htm.gz
Normal file
Binary file not shown.
69
data/index.json
Normal file
69
data/index.json
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.live.json",
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"title": "Главная",
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"class": "alert alert-light",
|
||||||
|
"title": "<center><img src='/icon.jpeg' alt='IoT Manager'></center>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Конфигурация устройства",
|
||||||
|
"action": "/?set.device",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Список других устройств в сети",
|
||||||
|
"action": "/?set.udp",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Конфигурация WIFI",
|
||||||
|
"action": "/?set.wifi",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Конфигурация MQTT",
|
||||||
|
"action": "/?set.mqtt",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Конфигурация push",
|
||||||
|
"action": "/?set.push",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Утилиты",
|
||||||
|
"action": "/?set.utilities",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Скачать приложение IoT Manager для android",
|
||||||
|
"action": "https://play.google.com/store/apps/details?id=ru.esp8266.iotmanager",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Скачать приложение IoT Manager для iphone",
|
||||||
|
"action": "https://apps.apple.com/ru/app/iot-manager/id1155934877",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1
data/items/analog-adc.txt
Normal file
1
data/items/analog-adc.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
analog-adc;id;anydata;Сенсоры;Аналоговый;order;pin-adc;map[1,1024,1,1024];c[1]
|
||||||
1
data/items/button-in.txt
Normal file
1
data/items/button-in.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
button-in;id;toggle;Кнопки;Освещение;order;pin;db[20]
|
||||||
1
data/items/button-out-i.txt
Normal file
1
data/items/button-out-i.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
button-out;id;toggle;Кнопки;Освещение;order;pin;inv[1];st[1]
|
||||||
1
data/items/button-out-np.txt
Normal file
1
data/items/button-out-np.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
button-out;id;toggle;Кнопки;Освещение;order;st[0]
|
||||||
1
data/items/button-out-p.txt
Normal file
1
data/items/button-out-p.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
button-out;id;toggle;Кнопки;Освещение;order;pin;st[0]
|
||||||
1
data/items/input-digit.txt
Normal file
1
data/items/input-digit.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
input-digit;id;inputDigit;Ввод;Введите#цифру;order;st[60]
|
||||||
1
data/items/input-time.txt
Normal file
1
data/items/input-time.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
input-time;id;inputTime;Ввод;Введите#время;order;st[10-00-00]
|
||||||
1
data/items/output-text.txt
Normal file
1
data/items/output-text.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
output-text;id;anydata;Вывод;Сигнализация;order;st[Обнаружено#движение]
|
||||||
1
data/items/pwm-out.txt
Normal file
1
data/items/pwm-out.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pwm-out;id;range;Ползунки;Яркость;order;pin;st[500]
|
||||||
5
data/items/signs.json
Normal file
5
data/items/signs.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"more":">",
|
||||||
|
"less":"<",
|
||||||
|
"eq":"="
|
||||||
|
}
|
||||||
BIN
data/js/build.chart.js.gz
Normal file
BIN
data/js/build.chart.js.gz
Normal file
Binary file not shown.
BIN
data/js/function.js.gz
Normal file
BIN
data/js/function.js.gz
Normal file
Binary file not shown.
39
data/lang/lang.ru.json
Normal file
39
data/lang/lang.ru.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"SetDevConf": "Конфигурация устройства",
|
||||||
|
"SetDevPreset": "Выберите из списка подходящий пресет кофигурации",
|
||||||
|
|
||||||
|
"ButSave":"Сохранить",
|
||||||
|
"ButMainPage":"Главная",
|
||||||
|
|
||||||
|
|
||||||
|
"SetUDPList": "Список других устройств в сети:",
|
||||||
|
"SetUDPWarn1": "После нажатия на кнопку <b>переформировать список устройств</b> ждите примерно минуту, а затем обновите страницу и список появится вновь",
|
||||||
|
|
||||||
|
"SetUDPUpdateList":"Переформировать список устройств",
|
||||||
|
"SetUDPUpdatePage":"Обновить страницу",
|
||||||
|
"SetUDPNameOfDev":"Имя этого устройства:",
|
||||||
|
"SetUDPDateExchange":"Включить обмен данными между устройствами",
|
||||||
|
"SetUDPWarn2":"Если обмен данными включен, то устройства будут обмениваться широковещательными пакетами udp для формирования списка устройств и для осуществления посылки настроек mqtt. Данный обмен создает дополнительную нагрузку на wifi сеть.",
|
||||||
|
|
||||||
|
"SetWiFiNameOfDev":"Имя устройства:",
|
||||||
|
"SetWiFiRouterConnect":"Подключение к WiFi роутеру:",
|
||||||
|
"SetWiFiAccessPoint":"Точка доступа:",
|
||||||
|
"SetWiFiWeb":"Логин и пароль web interface:",
|
||||||
|
"SetWiFiTimeZone":"Временная зона:",
|
||||||
|
"SetWiFiNTP":"Сервер NTP:",
|
||||||
|
"SetWiFiWarn1":"Имя устройства должно состоять из английских букв и иметь длинну от 6 до 12 символов",
|
||||||
|
"SetWiFiWarn2":"После того как вы введете логин пароль от вашего wifi роутера необходимо нажать кнопку сохранить, а затем обязательно нажать кнопку <b>перезагрузить устройство</b> внизу этой страницы",
|
||||||
|
"SetWiFiWarn3":"Устройство постоянно сканирует сеть на наличие wifi. Если роутер отключен, то устройство автоматически перейдет в режим точки доступа. Когда wifi появится устройство автоматически подключится к роутеру снова, и выключит точку доступа",
|
||||||
|
"SetWiFiWarn4":"После изменения поля <b>NTP сервер</b> необходимо перезагрузить устройство",
|
||||||
|
"SetWiFiWarn5":"Светодиод статуса подключения показывает четыре состояния подключения: <br><b>1. мигает редко</b> - идет подключение к wifi <br><b>2. мигает часто</b> - идет подключение к серверу mqtt <br><b>3. горит постоянно</b> - модуль в режиме точки доступа, <br><b>4. не горит</b> - модуль подключен к wifi и к mqtt. <br>Светодиод подключен к gpio2. Если галочка стоит - то использовать этот пин нельзя",
|
||||||
|
|
||||||
|
"SetMQTTServerName":"Имя сервера:",
|
||||||
|
"SetMQTTPort":"Номер порта:",
|
||||||
|
"SetMQTTPrefix":"Префикс:",
|
||||||
|
"SetMQTTUserName":"Имя пользователя:",
|
||||||
|
"SetMQTTPassword":"Пароль:",
|
||||||
|
|
||||||
|
"SetMQTTSendSettings":"Отправить настройки MQTT с этого устройства на все остальные",
|
||||||
|
"SetMQTTWarn1":"Обратите внимание что поле префикс может состоять только из одного слова и одного разделителя: <b>/prefix</b>, вариант вида: <b>/prefix1/prefix2</b> работать не будет. После изменения поля prefix необходимо перезагрузить устройство",
|
||||||
|
"SetMQTTWarn2":"Прежде чем нажимать на кнопку <b>Отправить настройки MQTT</b> сохрание их, если Вы их меняли. Настройки получат и перезапишут все устройства в локальной сети"
|
||||||
|
}
|
||||||
1
data/s.conf.csv
Normal file
1
data/s.conf.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Тип элемента;Id;Виджет;Имя вкладки;Имя виджета;Позиция виджета
|
||||||
|
1
data/s.scen.txt
Normal file
1
data/s.scen.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
//
|
||||||
143
data/set.device.json
Normal file
143
data/set.device.json
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/config.option.json",
|
||||||
|
"/config.live.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"class": "col-sm-offset-1 col-sm-10",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Device ID: {{chipID}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "IP address: {{ip}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Time: {{time}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Uptime: {{uptime}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Build version: {{firmware_version}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "LittleFS version: 2.4.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dropdown",
|
||||||
|
"name": "help-url",
|
||||||
|
"class": "btn btn-default",
|
||||||
|
"style": "display:inline",
|
||||||
|
"title": {
|
||||||
|
"#": "Выберите элемент из списка<span class=\"caret\"></span>",
|
||||||
|
"/set?addItem=button-out-p": "1.Кнопка управляющая пином",
|
||||||
|
"/set?addItem=button-out-np": "2.Кнопка не привязанная к пину",
|
||||||
|
"/set?addItem=pwm-out": "3.Широтно импульсная модуляция(pwm)",
|
||||||
|
"/set?addItem=button-in": "4.Физическая кнопка",
|
||||||
|
"/set?addItem=input-digit": "5.Окно ввода цифровых значений",
|
||||||
|
"/set?addItem=input-time": "6.Окно ввода времени",
|
||||||
|
"/set?addItem=output-text": "7.Окно вывода любого текста, предупреждения, цифры",
|
||||||
|
"/set?addItem=analog-adc": "8.Аналоговый сенсор"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "csv",
|
||||||
|
"title": [
|
||||||
|
"html",
|
||||||
|
"text",
|
||||||
|
"text",
|
||||||
|
"text",
|
||||||
|
"text",
|
||||||
|
"text"
|
||||||
|
],
|
||||||
|
"state": "s.conf.csv",
|
||||||
|
"style": "width:100%;",
|
||||||
|
"action": "/set?saveItems",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Удалить все",
|
||||||
|
"action": "/set?delAllItems",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h2",
|
||||||
|
"title": "Сценарии"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "checkbox",
|
||||||
|
"name": "scen",
|
||||||
|
"title": "Включить сценарии",
|
||||||
|
"action": "/set?scen=[[scen]]",
|
||||||
|
"state": "{{scen}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"state": "s.scen.txt",
|
||||||
|
"style": "width:100%;height:350px",
|
||||||
|
"title": "Сохранить",
|
||||||
|
"action": "/set?sceninit",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Инструкция к системе автоматизации",
|
||||||
|
"action": "https://github.com/IoTManagerProject/IoTManager/wiki",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Очистить логи сенсоров",
|
||||||
|
"action": "/set?cleanlog",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"name": "my-block",
|
||||||
|
"style": "position:fixed;top:50%;left:50%;width:400px;margin-left:-200px;text-align:center;",
|
||||||
|
"class": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "Обновить прошивку устройства",
|
||||||
|
"action": "/check",
|
||||||
|
"response": "[[my-block]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
143
data/set.deviceold.json
Normal file
143
data/set.deviceold.json
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/config.option.json",
|
||||||
|
"/config.live.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"class": "col-sm-offset-1 col-sm-10",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Device ID: {{chipID}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "IP address: {{ip}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Time: {{time}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Uptime: {{uptime}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "Build version: {{firmware_version}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "LittleFS version: 2.3.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dropdown",
|
||||||
|
"name": "help-url",
|
||||||
|
"class": "btn btn-default",
|
||||||
|
"style": "display:inline",
|
||||||
|
"title": {
|
||||||
|
"#": "{{SetDevPreset}}<span class=\"caret\"></span>",
|
||||||
|
"/set?preset=001": "1.Вкл. выкл. локального реле",
|
||||||
|
"/set?preset=002": "2.Вкл. выкл. локального реле в определенное время",
|
||||||
|
"/set?preset=003": "3.Вкл. выкл. локального реле на определенный период времени",
|
||||||
|
"/set?preset=004": "4.Вкл. выкл. нескольких локальных реле кнопкой в приложении",
|
||||||
|
"/set?preset=005": "5.Вкл. выкл. локального реле физической кнопкой и кнопкой в приложении параллельно (для выключателя света)",
|
||||||
|
"/set?preset=006": "6.Вкл. выкл. нескольких удаленных реле кнопкой в приложении (нужно указать Device ID)",
|
||||||
|
"/set?preset=007": "7.Вкл. выкл. нескольких удаленных реле физической кнопкой (нужно указать Device ID)",
|
||||||
|
"/set?preset=008": "8.Широтно импульсная модуляция",
|
||||||
|
"/set?preset=009": "9.Сенсор DHT11 (темп, влажность) и логгирование",
|
||||||
|
"/set?preset=010": "10.Сенсор DHT22, DHT33, DHT44, AM2302, RHT03 (темп, влажность) и логгирование",
|
||||||
|
"/set?preset=011": "11.Аналоговый сенсор и логгирование",
|
||||||
|
"/set?preset=012": "12.Cенсор bmp280 (темп, давление) и логгирование",
|
||||||
|
"/set?preset=013": "13.Cенсор bme280 (темп, давление, влажность, высота) и логгирование",
|
||||||
|
"/set?preset=014": "14.Сенсор DS18B20 (темп) и логгирование",
|
||||||
|
"/set?preset=015": "15.Термостат на DS18B20 с переключением в ручной режим и логгированием",
|
||||||
|
"/set?preset=016": "16.Котроль уровня в баке (датчик расстояния) на сенсорах: JSN-SR04T, HC-SR04, HY-SRF05 и логгирование",
|
||||||
|
"/set?preset=017": "17.Датчик движения включающий свет",
|
||||||
|
"/set?preset=018": "18.Охранный датчик движения",
|
||||||
|
"/set?preset=019": "19.Система управления шаговыми двигателями на основе драйвера A4988 (открытие закрытие штор)",
|
||||||
|
"/set?preset=020": "20.Система управления сервоприводами",
|
||||||
|
"/set?preset=021": "21.Модуль uart (serial). Двухстороняя связь с устройством через uart. Получение данных и отправка команд",
|
||||||
|
"/set?preset=100": "22.Настройки по умолчанию"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h2",
|
||||||
|
"title": "{{SetDevConf}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"state": "dev_conf.txt",
|
||||||
|
"style": "width:100%;height:350px",
|
||||||
|
"title": "Сохранить",
|
||||||
|
"action": "/set?devinit",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "h2",
|
||||||
|
"title": "Сценарии"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "checkbox",
|
||||||
|
"name": "scen",
|
||||||
|
"title": "Включить сценарии",
|
||||||
|
"action": "/set?scen=[[scen]]",
|
||||||
|
"state": "{{scen}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"state": "dev_scen.txt",
|
||||||
|
"style": "width:100%;height:350px",
|
||||||
|
"title": "Сохранить",
|
||||||
|
"action": "/set?sceninit",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Инструкция к системе автоматизации",
|
||||||
|
"action": "https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/wiki/Instruction",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Очистить логи сенсоров",
|
||||||
|
"action": "/set?cleanlog",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"name": "my-block",
|
||||||
|
"style": "position:fixed;top:50%;left:50%;width:400px;margin-left:-200px;text-align:center;",
|
||||||
|
"class": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "Обновить прошивку устройства",
|
||||||
|
"action": "/check",
|
||||||
|
"response": "[[my-block]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
133
data/set.mqtt.json
Normal file
133
data/set.mqtt.json
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{SetMQTTServerName}}",
|
||||||
|
"style": "width:60%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "mqttServer-arg",
|
||||||
|
"state": "{{mqttServer}}",
|
||||||
|
"style": "width:40%;float:right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{SetMQTTPort}}",
|
||||||
|
"style": "width:60%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "mqttPort-arg",
|
||||||
|
"state": "{{mqttPort}}",
|
||||||
|
"style": "width:40%;float:right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{SetMQTTPrefix}}",
|
||||||
|
"style": "width:60%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "mqttPrefix-arg",
|
||||||
|
"state": "{{mqttPrefix}}",
|
||||||
|
"style": "width:40%;float:right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{SetMQTTUserName}}",
|
||||||
|
"style": "width:60%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "mqttUser-arg",
|
||||||
|
"state": "{{mqttUser}}",
|
||||||
|
"style": "width:40%;float:right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{SetMQTTPassword}}",
|
||||||
|
"style": "width:60%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "mqttPass-arg",
|
||||||
|
"state": "{{mqttPass}}",
|
||||||
|
"style": "width:40%;float:right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"name": "my-block",
|
||||||
|
"style": "position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;",
|
||||||
|
"class": "hidden"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"action": "set?mqttServer=[[mqttServer-arg]]&mqttPort=[[mqttPort-arg]]&mqttPrefix=[[mqttPrefix-arg]]&mqttUser=[[mqttUser-arg]]&mqttPass=[[mqttPass-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"title": "{{SetMQTTSendSettings}}",
|
||||||
|
"action": "set?mqttsend",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"title": "Проверить соединение с MQTT",
|
||||||
|
"action": "set?mqttcheck",
|
||||||
|
"response": "[[my-block]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetMQTTWarn1}}</p></font></div>"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetMQTTWarn2}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"style": "width:100%;float:left;",
|
||||||
|
"title": "Перезагрузить устройство",
|
||||||
|
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
|
||||||
|
"class": "btn btn-block btn-danger"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
51
data/set.push.json
Normal file
51
data/set.push.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"style": "width:60%;float:left;",
|
||||||
|
"title": "Device id:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "push-arg",
|
||||||
|
"style": "width:40%;float:right",
|
||||||
|
"state": "{{pushingboxid}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "set?pushingboxid=[[push-arg]]",
|
||||||
|
"class": "btn btn-block btn-default",
|
||||||
|
"style": "width:100%;display:inline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Перезагрузить устройство",
|
||||||
|
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}",
|
||||||
|
"class": "btn btn-block btn-danger"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
96
data/set.udp.json
Normal file
96
data/set.udp.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"title": "Главная",
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetUDPList}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "csv",
|
||||||
|
"title": [
|
||||||
|
"html",
|
||||||
|
"html",
|
||||||
|
"html"
|
||||||
|
],
|
||||||
|
"state": "dev.csv",
|
||||||
|
"style": "width:100%;",
|
||||||
|
"class": "nan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{SetUDPUpdateList}}",
|
||||||
|
"action": "/set?updatelist",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{SetUDPUpdatePage}}",
|
||||||
|
"action": "/set?updatepage",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetUDPWarn1}}</p></font></div>",
|
||||||
|
"style": "width:100%;float:left;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetUDPNameOfDev}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "{{SetUDPNameOfDev}}",
|
||||||
|
"name": "devname-arg",
|
||||||
|
"state": "{{name}}",
|
||||||
|
"pattern": "[A-Za-z0-9]{6,12}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "/set?devname=[[devname-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "checkbox",
|
||||||
|
"name": "udponoff",
|
||||||
|
"title": "{{SetUDPDateExchange}}",
|
||||||
|
"action": "/set?udponoff=[[udponoff]]",
|
||||||
|
"state": "{{udponoff}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetUDPWarn2}}</p></font></div>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
39
data/set.utilities.json
Normal file
39
data/set.utilities.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.live.json",
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"title": "Главная",
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "Сканирование шины i2c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h4",
|
||||||
|
"title": "{{i2c}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Сканировать",
|
||||||
|
"action": "/set?i2c",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
185
data/set.wifi.json
Normal file
185
data/set.wifi.json
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
"/config.setup.json",
|
||||||
|
"/lang/lang.ru.json"
|
||||||
|
],
|
||||||
|
"title": "Конфигурация",
|
||||||
|
"class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "h5",
|
||||||
|
"title": "{{name}}",
|
||||||
|
"class": "alert-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "{{ButMainPage}}",
|
||||||
|
"action": "/",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetWiFiNameOfDev}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "{{SetWiFiNameOfDev}}",
|
||||||
|
"name": "devname-arg",
|
||||||
|
"state": "{{name}}",
|
||||||
|
"pattern": "[A-Za-z0-9]{6,12}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "set?devname=[[devname-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetWiFiWarn1}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetWiFiRouterConnect}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "routerssid-arg",
|
||||||
|
"state": "{{routerssid}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "password",
|
||||||
|
"title": "",
|
||||||
|
"name": "routerpass-arg",
|
||||||
|
"state": "{{routerpass}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"class": "btn btn-block btn-default",
|
||||||
|
"action": "set?routerssid=[[routerssid-arg]]&routerpass=[[routerpass-arg]]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetWiFiWarn2}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "checkbox",
|
||||||
|
"name": "blink",
|
||||||
|
"title": "Включить светодиод статуса подключения",
|
||||||
|
"action": "/set?blink=[[blink]]",
|
||||||
|
"state": "{{blink}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetWiFiWarn5}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetWiFiAccessPoint}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "apssid-arg",
|
||||||
|
"state": "{{apssid}}",
|
||||||
|
"pattern": ".{1,20}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "password",
|
||||||
|
"title": "",
|
||||||
|
"name": "appass-arg",
|
||||||
|
"state": "{{appass}}",
|
||||||
|
"pattern": ".{8,20}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "set?apssid=[[apssid-arg]]&appass=[[appass-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetWiFiWarn3}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetWiFiWeb}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "Логин",
|
||||||
|
"name": "weblogin-arg",
|
||||||
|
"state": "{{weblogin}}",
|
||||||
|
"pattern": ".{1,20}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "password",
|
||||||
|
"title": "Пароль",
|
||||||
|
"name": "webpass-arg",
|
||||||
|
"state": "{{webpass}}",
|
||||||
|
"pattern": ".{1,20}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "set?weblogin=[[weblogin-arg]]&webpass=[[webpass-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"title": "{{SetWiFiTimeZone}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "timezone-arg",
|
||||||
|
"state": "{{timezone}}",
|
||||||
|
"pattern": ".{1,20}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input",
|
||||||
|
"title": "",
|
||||||
|
"name": "ntp-arg",
|
||||||
|
"state": "{{ntp}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"title": "{{ButSave}}",
|
||||||
|
"action": "set?timezone=[[timezone-arg]]&ntp=[[ntp-arg]]",
|
||||||
|
"class": "btn btn-block btn-default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"title": "<div style='margin-top:10px;margin-bottom:10px;'><font color='black'><p style='border: 1px solid #DCDCDC; border-radius: 3px; background-color: #F5F5F5; padding: 10px;'>{{SetWiFiWarn4}}</p></font></div>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"title": "Перезагрузить устройство",
|
||||||
|
"action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/set?device=ok');}",
|
||||||
|
"class": "btn btn-block btn-danger"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
6
data/widgets/alarm.json
Normal file
6
data/widgets/alarm.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"widget": "anydata",
|
||||||
|
"icon": "body",
|
||||||
|
"color": "red",
|
||||||
|
"descrColor": "red"
|
||||||
|
}
|
||||||
5
data/widgets/anydata.json
Normal file
5
data/widgets/anydata.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"widget": "anydata",
|
||||||
|
"after": "",
|
||||||
|
"icon": ""
|
||||||
|
}
|
||||||
5
data/widgets/chart.json
Normal file
5
data/widgets/chart.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"widget": "chart",
|
||||||
|
"series": "Temperature, °C",
|
||||||
|
"dateFormat": "HH:mm"
|
||||||
|
}
|
||||||
7
data/widgets/fillgauge.json
Normal file
7
data/widgets/fillgauge.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"widget": "fillgauge",
|
||||||
|
"circleColor": "#00FFFF",
|
||||||
|
"textColor": "#FFFFFF",
|
||||||
|
"waveTextColor": "#000000",
|
||||||
|
"waveColor": "#00FFFF"
|
||||||
|
}
|
||||||
6
data/widgets/inputDate.json
Normal file
6
data/widgets/inputDate.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"size" : "small",
|
||||||
|
"color" : "orange",
|
||||||
|
"type" : "date"
|
||||||
|
}
|
||||||
5
data/widgets/inputDigit.json
Normal file
5
data/widgets/inputDigit.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"color" : "blue",
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
6
data/widgets/inputText.json
Normal file
6
data/widgets/inputText.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"size" : "small",
|
||||||
|
"color" : "orange",
|
||||||
|
"type" : "text"
|
||||||
|
}
|
||||||
5
data/widgets/inputTime.json
Normal file
5
data/widgets/inputTime.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"widget" : "input",
|
||||||
|
"color" : "blue",
|
||||||
|
"type" : "time"
|
||||||
|
}
|
||||||
12
data/widgets/progress-line.json
Normal file
12
data/widgets/progress-line.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"widget": "progress-line",
|
||||||
|
"icon": "sunny",
|
||||||
|
"descrColor": "",
|
||||||
|
"color": "",
|
||||||
|
"max": "100",
|
||||||
|
"background": "",
|
||||||
|
"stroke": "10",
|
||||||
|
"disabled": "",
|
||||||
|
"before": "",
|
||||||
|
"after": ""
|
||||||
|
}
|
||||||
11
data/widgets/progress-round.json
Normal file
11
data/widgets/progress-round.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"widget": "progress-round",
|
||||||
|
"descrColor": "",
|
||||||
|
"max": "100",
|
||||||
|
"stroke": "20",
|
||||||
|
"color": "#45ccce",
|
||||||
|
"background": "#777",
|
||||||
|
"before": "",
|
||||||
|
"semicircle": "1",
|
||||||
|
"after": ""
|
||||||
|
}
|
||||||
9
data/widgets/range.json
Normal file
9
data/widgets/range.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"widget" : "range",
|
||||||
|
"descrColor": "red",
|
||||||
|
"after" : "%",
|
||||||
|
"k" : 0.0977,
|
||||||
|
"min" : 0,
|
||||||
|
"max" : 100,
|
||||||
|
"debounce": 500
|
||||||
|
}
|
||||||
7
data/widgets/select.json
Normal file
7
data/widgets/select.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"widget" : "select",
|
||||||
|
"size" : "small",
|
||||||
|
"fill" : "outline",
|
||||||
|
"options" : "["Zero item", "First item", "Second item"]",
|
||||||
|
"status" : 2
|
||||||
|
}
|
||||||
5
data/widgets/toggle.json
Normal file
5
data/widgets/toggle.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"widget": "toggle",
|
||||||
|
"icon": "",
|
||||||
|
"iconOff": ""
|
||||||
|
}
|
||||||
566
doc/1.txt
Normal file
566
doc/1.txt
Normal file
@@ -0,0 +1,566 @@
|
|||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
- Объединение различных по типу и назначению устройств: управление, получение данных, и настройка параметров - всё в одном приложении
|
||||||
|
|
||||||
|
- Взаимодействие с устройствами осуществляется через "облачный" сервис с использованием протокола mqtt, позволит контролировать их из любой точки Мира (при наличии доступа в Интернет)
|
||||||
|
|
||||||
|
- Поддержка нескольких профилей и их переключение "на лету", дает возможность объединить устройства в группы
|
||||||
|
|
||||||
|
|
||||||
|
Настройка (после "прошивки") производится через веб-интерфейс, чтобы получить к нему доступ необходимо соединиться с WiFi AP устройства и набрать в адресной строке браузера http://192.168.4.1.
|
||||||
|
Далее выбрать типовой шаблон автоматизации, произвести настройку под свои требования и задачи.
|
||||||
|
Основные разделы интерфейса: конфигурация и сценарии.
|
||||||
|
В окне конфигурации задаются "объекты", "элементы управления" устройства (dashboard) - им устройство будет представлено в приложении компаньоне проекта. В окне сценариев задаются реакции на события и изменения в параметрах работы системы.
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
## Команды, назначение и применение
|
||||||
|
|
||||||
|
Команды служат для настройки и управления устройством и его взаимодействия
|
||||||
|
|
||||||
|
**`buttonSet 1 1`** Изменит состояние "кнопки" №1, установит его в значение 1
|
||||||
|
|
||||||
|
**`pinSet 13 0`** Установит GPIO 13 состояние 0
|
||||||
|
|
||||||
|
**`pinChange 13`** Состояние GPIO 13 будет изменено на противоположное
|
||||||
|
|
||||||
|
**`pwmSet 1 500`** Настройка pwm №1 будет использовано значение 500
|
||||||
|
|
||||||
|
**`timeSet 1 08-00-00`** Установит для элемента ввода времени - inputTime значение 08:00:00
|
||||||
|
|
||||||
|
**`digitSet 1 56`** Элемент №1 (для цифровых параметров) отобразит число 56
|
||||||
|
|
||||||
|
**`stepperSet 1 100 1`** Шаговый двигатель №1 - вращение 100 "шагов" по часовой стрелке (для движения в обратную сторону используются отрицательные значения параметра)
|
||||||
|
|
||||||
|
**`servoSet 1 180`** Сервопривод №1 принять положение 180°
|
||||||
|
|
||||||
|
**`timerStart 1 60 sec`** Установить для таймера №1 обратный отсчёт в 60 секунд
|
||||||
|
|
||||||
|
**`timerStop 1`** Остановить таймер №1
|
||||||
|
|
||||||
|
**`textSet 1 Привет`** Установить для элемента текстовое поле №1 - "привет"
|
||||||
|
|
||||||
|
**`push Внимание Протечка`** Отправить push-уведомление с темой "внимание" и содержанием "протечка"
|
||||||
|
|
||||||
|
**`firmwareUpdate`** Обновить прошивку устройства "по воздуху"
|
||||||
|
|
||||||
|
**`firmwareVersion Версия прошивки Системные 1`** Узнать версию прошивки устройстве
|
||||||
|
|
||||||
|
## Сценарии
|
||||||
|
|
||||||
|
Элементарный блок в сценарии состоит из набора команд и триггера - условия для их выполнения
|
||||||
|
|
||||||
|
**temp > 60**
|
||||||
|
digitSet 1 60
|
||||||
|
stepperSet 1 100 1
|
||||||
|
textSet 1 Перегрев
|
||||||
|
**end**
|
||||||
|
|
||||||
|
Условие: когда температура превысит 60°
|
||||||
|
Запустит: команда шаговому двигателю, в приложение отправить сообщение и цифровое значение температуры.
|
||||||
|
|
||||||
|
В сценарии может быть несколько блоков, при необходимости из приложения есть возможность "выключать" часть из них.
|
||||||
|
Неактивные блоки сценария будут проигнорированы.
|
||||||
|
|
||||||
|
Для взаимодействия устройств между собой предусмотрены команды mqtt и http
|
||||||
|
|
||||||
|
**temp > 60**
|
||||||
|
mqtt 154348-134 digitSet_1_56
|
||||||
|
mqtt 154348-136 stepperSet _1_100_1
|
||||||
|
http 192.168.1.10 textSet_1_Перегрев
|
||||||
|
**end**
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 1.1 Объект "кнопка"
|
||||||
|
|
||||||
|
(эти строки мы пишем в "конфигурации устройства")
|
||||||
|
|
||||||
|
### a) кнопка управляющая выходом (пином). Пины нумеруются по системе нумирации gpio для esp контроллеров.
|
||||||
|
|
||||||
|
`button 1 13 кухня освещение 0 1`
|
||||||
|
|
||||||
|
**"button"** это объект создающий кнопку в приложении
|
||||||
|
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
||||||
|
**"13"** это номер пина которым будет управлять данная кнопка
|
||||||
|
**"кухня"** это название кнопки в приложении
|
||||||
|
**"освещение"** это название вкладки в приложении на которой появится данная кнопка
|
||||||
|
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
||||||
|
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
|
||||||
|
### б) виртуальная кнопка - кнопка реакцию на которую можно задать в сценариях:
|
||||||
|
|
||||||
|
`button 1 na запустить таймеры 0 1`
|
||||||
|
|
||||||
|
**"button"** это объект создающий кнопку в приложении
|
||||||
|
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
||||||
|
**"na"** абривиатура not available означающая что эта кнопка виртуальная и что пин не установлен
|
||||||
|
**"запустить"** это название кнопки в приложении
|
||||||
|
**"таймеры"** это название вкладки в приложении на которой появится данная кнопка
|
||||||
|
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
||||||
|
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
### в) кнопка включающая и выключающая все сценарии:
|
||||||
|
|
||||||
|
`button 1 scenario запустить таймеры 0 1`
|
||||||
|
|
||||||
|
**"button"** это объект создающий кнопку в приложении
|
||||||
|
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
||||||
|
**"scenario"** слово означающее что эта кнопка для управления сценариями
|
||||||
|
**"запустить"** это название кнопки в приложении
|
||||||
|
**"таймеры"** это название вкладки в приложении на которой появится данная кнопка
|
||||||
|
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
||||||
|
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
|
||||||
|
### г) кнопка включающая выключающая определенные блоки сценариев:
|
||||||
|
|
||||||
|
`button 1 line1,line3, Включить#отправку#push Оповещение 0 1`
|
||||||
|
|
||||||
|
**"button"** это объект создающий кнопку в приложении
|
||||||
|
**"1"** это номер этой кнопки (необходимый для ее аутентификации)
|
||||||
|
**"line1,line3,"** это блоки сценариев нумирация сверху вниз. Блоком считается выражение от начала до слова end
|
||||||
|
**"Включить#отправку#push"** это название кнопки в приложении
|
||||||
|
**"Оповещение"** это название вкладки в приложении на которой появится данная кнопка
|
||||||
|
**"0"** это начальное состояние кнопки при старте модуля (выкд 0, вкл 1)
|
||||||
|
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 1.2 Команды управления объектом "кнопка"
|
||||||
|
|
||||||
|
(эти строки мы пишем в "сценариях")
|
||||||
|
|
||||||
|
### а) Команда включения выключения кнопки по ее номеру
|
||||||
|
|
||||||
|
`buttonSet 1 1`
|
||||||
|
|
||||||
|
**"buttonSet"** команда управления объектом button
|
||||||
|
**"1"** номер кнопки которой будем управлять
|
||||||
|
**"1"** состояние включено, 0 - выключено
|
||||||
|
|
||||||
|
### б) Команда изменения состояния кнопки на противоположное
|
||||||
|
|
||||||
|
`buttonChange 1`
|
||||||
|
|
||||||
|
**"buttonChange"** команда управления объектом button
|
||||||
|
**"1"** номер кнопки которой будем управлять
|
||||||
|
|
||||||
|
## 1.3 Вызов событий объектом "кнопока"
|
||||||
|
|
||||||
|
(эти строки мы пишем в "сценариях")
|
||||||
|
|
||||||
|
объект button может быть равен либо 0 либо 1
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`button2 = 0`
|
||||||
|
|
||||||
|
Пример использования:
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`buttonSet 2 1`
|
||||||
|
`buttonSet 3 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 2.1 Объект "физическая кнопка"
|
||||||
|
|
||||||
|
`switch 1 0 10`
|
||||||
|
|
||||||
|
**switch** это объект создающий физическую кнопку
|
||||||
|
**1** номер кнопки
|
||||||
|
**0** пин кнопки (при подключении необходим подтягивающий резистор)
|
||||||
|
**10** задержка для избавления от дребезга с мили секундах
|
||||||
|
|
||||||
|
## 2.2 Вызов событий объектом "физическая кнопка"
|
||||||
|
|
||||||
|
`switch1` может быть равна нулю или единицы, ноль - событие отбрасывания кнопки, единица - событие нажатия
|
||||||
|
|
||||||
|
`switch1 = 1`
|
||||||
|
`buttonChange 1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 3.1 Объект "широтноимпульсная модуляция"
|
||||||
|
|
||||||
|
`pwm 1 12 яркость освещение 1023 1`
|
||||||
|
|
||||||
|
**"pwm"** это объект создающий управление шим в приложении в виде ползунка
|
||||||
|
**"1"** это номер этого объекта
|
||||||
|
**"12"** это номер пина на котором будет генерироваться шим заданной в приложении величены
|
||||||
|
**"Яркость"** это название кнопки в приложении
|
||||||
|
**"Оповещение"** это название вкладки в приложении на которой появится данная кнопка
|
||||||
|
**"1023"** это начальное значение шим сигнала и ползунка (изменяется от 0 до 1023)
|
||||||
|
**"1"** это уникальный номер и номер сортировки данной кнопки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 3.2 Команда управления объектом "широтноимпульсная модуляция"
|
||||||
|
|
||||||
|
`pwmSet 1 500`
|
||||||
|
|
||||||
|
**"pwmSet"** команда управления объектом
|
||||||
|
**"1"** номер объекта, которым будем управлять
|
||||||
|
**"500"** значение которое установится после выполнения команды (от 0 до 1023)
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 4.1 Объект "окно ввода времени"
|
||||||
|
|
||||||
|
`inputTime time1 Во#сколько#включить? Таймеры 20-30-00 1`
|
||||||
|
|
||||||
|
**inputTime** это объект создающий окно ввода в приложении
|
||||||
|
**time1** переменная в которую будет записано время введенное в окно
|
||||||
|
**Во#сколько#включить?** это название окна в приложении
|
||||||
|
**Таймеры** это название вкладки в приложении
|
||||||
|
**20-30-00** начальное значение времени после загрузки устройства
|
||||||
|
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 4.2 Управление объектом "окно ввода времени"
|
||||||
|
|
||||||
|
`timeSet 1 08-00-00`
|
||||||
|
|
||||||
|
**"timeSet"** команда управления объектом
|
||||||
|
**"1"** номер объекта, которым будем управлять в данном случае окном ввода с `time1`
|
||||||
|
**"08-00-00"** время которое хотим установить
|
||||||
|
|
||||||
|
В окно ввода можно вводить время в приложении но если необходимо изменить время автоматически
|
||||||
|
по какому нибудь событию то можно использовать команду выше - **timeSet**.
|
||||||
|
|
||||||
|
## 4.3 Вызов событий объектом "окно ввода времени"
|
||||||
|
|
||||||
|
`timenow = time1`
|
||||||
|
`buttonSet 1 1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
`timenow` всегда хранит в себе текущее время, и поэтому исходя из данного сценария кнопка номер 1 включится в то время которое будет введено в окно ввода `time1`
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 5.1 Объект "окно ввода цифры"
|
||||||
|
|
||||||
|
`inputDigit digit1 Через#сколько#секунд#выключить? Таймеры 5 2`
|
||||||
|
|
||||||
|
**inputDigit** это объект создающий окно ввода в приложении
|
||||||
|
**digit1** переменная в которую будет записана цифра, введенная в окно
|
||||||
|
**Через#сколько#секунд#выключить?** это название окна в приложении
|
||||||
|
**Таймеры** это название вкладки в приложении
|
||||||
|
**5** цифра по умолчанию, после загрузки модуля
|
||||||
|
**2** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 5.2 Управление объектом "окно ввода цифры":
|
||||||
|
|
||||||
|
`digitSet 1 56`
|
||||||
|
|
||||||
|
**"digitSet"** команда управления объектом
|
||||||
|
**"1"** номер объекта, которым будем управлять в данном случае окном ввода с `digit1`
|
||||||
|
**"56"** цифра которую хотим установить
|
||||||
|
|
||||||
|
В окно ввода можно вводить цифры в приложении, но если необходимо изменить цифру автоматически
|
||||||
|
по какому нибудь событию, то можно использовать команду выше - **digitSet**.
|
||||||
|
|
||||||
|
## 5.3 Вызов событий объектом "окно ввода цифры"
|
||||||
|
|
||||||
|
`dallas > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`timerStart 1 digit1 sec`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 6.1 Объект "dallas" (сенсор температуры ds18b20)
|
||||||
|
|
||||||
|
`dallas temp1 2 123456 Водонагреватель,#t°C Термостат any-data 1`
|
||||||
|
|
||||||
|
**dallas** это объект чтения датчика температуры
|
||||||
|
**2** пин датчика температуры
|
||||||
|
**Водонагреватель,#t°C** это название виджета в приложении
|
||||||
|
**Датчики** название вкладки в приложении
|
||||||
|
**any-data** или **progress-round** или **progress-line** три разных варианта виджета отображения
|
||||||
|
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 6.2 Вызов событий объектом "dallas"
|
||||||
|
|
||||||
|
В сценариях dallas можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`dallas > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`dallas > 60`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 7.1 Объект "analog" (аналоговый вход контроллера)
|
||||||
|
|
||||||
|
`analog adc 0 Аналоговый#вход,#% Датчики progress-round 310 620 1 100 1`
|
||||||
|
|
||||||
|
**analog** это объект чтения аналогового входа
|
||||||
|
**adc** это переменная
|
||||||
|
**0** пин аналогового входа (для esp8266 всегда 0, для esp32 пока что не доделал читаться будет всегда пин 34)
|
||||||
|
**Аналоговый#вход,#%** это название виджета в приложении
|
||||||
|
**Датчики** название вкладки в приложении
|
||||||
|
**any-data** или **progress-round** или **progress-line** три разных варианта виджета отображения
|
||||||
|
**310** начальная величина читаемого диапазона
|
||||||
|
**620** конечная величина читаемого диапазона
|
||||||
|
**1** начальная величина выводимого диапазона
|
||||||
|
**100** конечная величина выводимого диапазона
|
||||||
|
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 7.2 Вызов событий объектом "analog"
|
||||||
|
|
||||||
|
В сценариях analog можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`analog > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`analog > 50`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 8.1 Объект "level" (ультразвуковой дальномер JSN-SR04T, HC-SR04, HY-SRF05)
|
||||||
|
|
||||||
|
`level Вода#в#баке,#% Датчики any-data 125 20 1`
|
||||||
|
|
||||||
|
**level** это объект чтения датчика расстояния
|
||||||
|
**Вода#в#баке** это название виджета в приложении
|
||||||
|
**Датчики** название вкладки в приложении
|
||||||
|
**any-data** или **progress-round** или **progress-line** три разных варианта отображения виджета
|
||||||
|
**125** расстояние от датчика до дна бака в сантиметрах
|
||||||
|
**20** расстояние от датчика до поверхности воды, когда бак полный, в сантиметрах
|
||||||
|
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
Подключать дальномер нужно:
|
||||||
|
|
||||||
|
| | trig | echo |
|
||||||
|
| :-: | :-: | :-: |
|
||||||
|
| wemos | D5 | D6 |
|
||||||
|
| esp | 14 | 12 |
|
||||||
|
|
||||||
|
## 8.2 Вызов событий объектом "level"
|
||||||
|
|
||||||
|
В сценариях level можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`level > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`level > 95`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 9.1 Объект "dht" (Сенсоры DHT11, DHT22, DHT33, DHT44, AM2302, RHT03)
|
||||||
|
|
||||||
|
dhtT DHT11 2 Температура#DHT,#t°C Датчики any-data 1
|
||||||
|
dhtH DHT11 2 Влажность#DHT,#% Датчики any-data 2
|
||||||
|
dhtComfort Степень#комфорта: Датчики 3
|
||||||
|
dhtPerception Восприятие: Датчики 4
|
||||||
|
dhtDewpoint Точка#росы: Датчики 5
|
||||||
|
|
||||||
|
**dhtT** или **dhtH** температура или влажность
|
||||||
|
**DHT11** или **DHT22** чтение DHT11 или DHT22, DHT33, DHT44, AM2302, RHT03 соответственно
|
||||||
|
**2** пин датчика
|
||||||
|
**Температура#DHT,#t°C** это название виджета в приложении
|
||||||
|
**Датчики** название вкладки в приложении
|
||||||
|
**any-data** или **progress-round** или **progress-line** три разных варианта отображения виджета
|
||||||
|
**1** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
## 9.2 Вызов событий объектом "dhtT" или "dhtH"
|
||||||
|
|
||||||
|
В сценариях "dhtT" или "dhtH" можно сравнивать с переменной окна ввода `digit1` (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`dhtT > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
`dhtH > digit1`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Или можно сравнивать с постоянной цифрой (>,<,>=,<=,=):
|
||||||
|
|
||||||
|
`dhtT > 50`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
`dhtH < 40`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 10.1 Объект "stepper" (Драйвер шагового двигателя A4988)
|
||||||
|
|
||||||
|
stepper 1 12 4
|
||||||
|
stepper 2 13 5
|
||||||
|
|
||||||
|
**stepper** объект создающий шаговый двигатель
|
||||||
|
**1** номер шаговика
|
||||||
|
**12** номер пина количества шагов
|
||||||
|
**4** номер пина направления
|
||||||
|
|
||||||
|
## 10.2 управление объектом "stepper"
|
||||||
|
|
||||||
|
`stepperSet 1 200 1`
|
||||||
|
|
||||||
|
**stepperSet** команда управления шаговым двигателем
|
||||||
|
**1** номер шагового двигателя (их может быть не более двух)
|
||||||
|
**200** количество шагов (обратное направление отрицательное значение параметра)
|
||||||
|
**1** интервал между шагами (мс)
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`stepperSet 1 200 1`
|
||||||
|
`end`
|
||||||
|
`button1 = 0`
|
||||||
|
`stepperSet 1 -200 1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 11.1 Объект "обратный таймер"
|
||||||
|
|
||||||
|
Прежде чем читать этот раздел запустите пресет №3 на устройстве.
|
||||||
|
Нажав на кнопку "Выберите во что вы хотите превратить esp"
|
||||||
|
|
||||||
|
Можно использовать цифры из окон ввода:
|
||||||
|
|
||||||
|
`timerStart 1 digit1 sec`
|
||||||
|
|
||||||
|
Можно писать цифры прям в объект:
|
||||||
|
|
||||||
|
`timerStart 1 10 sec`
|
||||||
|
|
||||||
|
Можно установить часы минуты или секунды:
|
||||||
|
|
||||||
|
`timerStart 1 10 sec`
|
||||||
|
`timerStart 1 10 min`
|
||||||
|
`timerStart 1 10 hours`
|
||||||
|
|
||||||
|
Используем это объект в сценариях вот так:
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`timerStart 1 digit1 sec`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Смысл в том что при нажатии на кнопку один запуститься обратный отчет, на величину digit1 секунд. Если напишем например:
|
||||||
|
|
||||||
|
`dallas < 60`
|
||||||
|
`timerStart 1 digit1 sec`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
то такой же отчет запустится когда значение температуры вырастит больше 60 градусов. Таким образом обратный отчет можно запустить реакцией на любое событие. Итак теперь обратный отчет запущен, обратный таймер уменьшается, и нам надо назначить действие на тот момент когда он обнулится. Для этого я придумал выражение: `timer1 = 0`
|
||||||
|
|
||||||
|
Используем его и в общем получаем вот такой сценарий:
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`timerStart 1 digit1 sec`
|
||||||
|
`end`
|
||||||
|
`timer1 = 0`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Когда таймер закончит отсчёт, кнопка станет "неактивной". Используйте преет №3, как пример подобного сценария
|
||||||
|
Например:
|
||||||
|
|
||||||
|
`dallas < 60`
|
||||||
|
`buttonSet 1 0`
|
||||||
|
`buttonSet 2 0`
|
||||||
|
`pwmSet 1 1023`
|
||||||
|
`mqtt 2653450020 buttonChange_1`
|
||||||
|
`mqtt 2653450020 pinSet_13_1`
|
||||||
|
`http 192.168.1.32 pinSet_14_1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Вот что может произойти на разных устройствах по одному событию повышения температуры...
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 12 Журнал (лог) данных
|
||||||
|
|
||||||
|
|
||||||
|
`logging analog 1 100 slow Аналоговый#вход Датчики 7`
|
||||||
|
|
||||||
|
**logging** объект для логирования
|
||||||
|
**analog** или **dhtT** или **dhtH** какой сенсор будем логировать, можно указать любой
|
||||||
|
**1** период между точками в минутах
|
||||||
|
**100** количество точек (старые точки будут удаляться по мере добавления новых)
|
||||||
|
**slow** или **fast** метод выгрузки графика в приложение, slow - выгружает график по одной точке (меньше расходуется оперативка, лучше использовать для esp8266), fast - выгрузка графика сразу (больше расход оперативки, подходит для esp32)
|
||||||
|
**Аналоговый#вход** название графика в приложении
|
||||||
|
**Датчики** название вкладки в приложении
|
||||||
|
**7** это уникальный номер и номер сортировки. Этот номер должен быть уникален для каждого объекта
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
## 13 Взаимодействие устройств между собой
|
||||||
|
|
||||||
|
Устройства могут между собой обмениваться командами. Команды можно отправлять по http или по mqtt.
|
||||||
|
По событию на одном устройстве можно вызвать действие на другом. Например на esp01 стоит датчик температуры, реле стоит на esp02.
|
||||||
|
|
||||||
|
Настройки esp01:
|
||||||
|
|
||||||
|
`dhtT temp 2 dht11 Температура#DHT,#t°C Датчики any-data 1`
|
||||||
|
|
||||||
|
`temp < 40`
|
||||||
|
`http 192.168.10.25 buttonSet_1_1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
Настройки esp02:
|
||||||
|
|
||||||
|
`button 1 13 Включить#реле Реле 0 1`
|
||||||
|
|
||||||
|
И теперь когда температура датчика на esp01 станет меньше 40 градусов то на esp02 будет отправлена команда на включение кнопки: buttonSet_1_1
|
||||||
|
|
||||||
|
Если вы хотите отправить команду через mqtt то сценарий будет выглядеть следующим образом:
|
||||||
|
|
||||||
|
`temp < 40`
|
||||||
|
`mqtt 12343442-12413131 buttonSet_1_1`
|
||||||
|
`end`
|
||||||
|
|
||||||
|
где `12343442-12413131` id esp02 той на которую отправляем команду. Id можно взять в веб интерфейсе на странице конфигурация устройства. Или в списке устройств в сети.
|
||||||
|
|
||||||
|
Теперь рассмотрим вариант внешнего управления esp с помощью get запросов.
|
||||||
|
|
||||||
|
`http://192.168.88.239/cmd?command=buttonSet%201%201`
|
||||||
|
|
||||||
|
Разберем эту строку. Сама команда в ней выглядит вот так: buttonSet%201%201. `%20` заменяют пробел.
|
||||||
|
|
||||||
|
То есть что бы составить get запрос на изменение например pwm нужно:
|
||||||
|
|
||||||
|
Взять команду `pwmSet 1 500`
|
||||||
|
Заменить в ней пробелы на `%20` получится так: `pwmSet%201%20500`
|
||||||
|
И добавить ее в конец строки `http://192.168.88.239/cmd?command=` где указывается ip адрес устройства
|
||||||
|
|
||||||
|
В итоге получится http://192.168.88.239/cmd?command=pwmSet%201%20500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
85
doc/2.txt
Normal file
85
doc/2.txt
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# В этой инструкции будет описано как с esp отправлять email и push
|
||||||
|
|
||||||
|
# Часть 1. Привязать email и pushbullet к сайту pushingbox
|
||||||
|
|
||||||
|
### 1. Необходимо перейти на сайт: [pushingbox](https://www.pushingbox.com/)
|
||||||
|
### 2. Войти с помощью google
|
||||||
|

|
||||||
|
### 3. Перейти в мои сервисы и добавить новый сервис
|
||||||
|

|
||||||
|
### 4. Нас интересуют два сервиса email и pushbullet
|
||||||
|

|
||||||
|
### 5. Выбираем сначало сервис для отправки email. В окно `Name of your email configuration` - вводим слово "email". В окно `Email address` - вводим ваш email адрес. жмем submit
|
||||||
|

|
||||||
|
manager_modules_firmware/blob/master/push_instruction/Screenshot_6.png)
|
||||||
|
### 6.1 Привязываем pushbullet. Переходим на сайт [pushbullet.com](https://www.pushbullet.com/)
|
||||||
|
### 6.2 Входим с гуглом или фейсбуком
|
||||||
|
### 6.3 Идем в настройки
|
||||||
|

|
||||||
|
### 6.4 Создаем токен
|
||||||
|

|
||||||
|
### 6.5 Идем опять в сервисы и теперь выбираем сервис pushbullet [pushingbox.com/services](https://www.pushingbox.com/services.php) нажимаем add service
|
||||||
|
### Берем токен, и вставляем его в окно Access token.
|
||||||
|
### Окно Device token (optional) оставляем пустым.
|
||||||
|
### В окно Name of your Pushbullet configuration пишем слово "push".
|
||||||
|

|
||||||
|
|
||||||
|
### 7. Теперь наш email и pushbullet привязаны к pushingbox. Далее можно скачать приложение pushbullet на телефон и войти с гуглом или фейсбуком сответственно с пунктом 6.3 этой инструкции
|
||||||
|

|
||||||
|
|
||||||
|
# Часть 2. Создание сценариев отправки email
|
||||||
|
|
||||||
|
### 8.1. Сценарий для отправки email. Заходим в My Scenarios:
|
||||||
|

|
||||||
|
|
||||||
|
### 8.2 Пишем слово email (это имя сценария отправки email) жмем add:
|
||||||
|

|
||||||
|
### 8.3 Нажимаем add an action
|
||||||
|

|
||||||
|
### 8.4 Выбираем наш email который мы зарегестрировали ранее и нажимаем Add an action with this service
|
||||||
|

|
||||||
|
### 8.5 Делаем все как на скриншоте и жмем submit
|
||||||
|

|
||||||
|
### 8.6 Возвращаемся на мои сценарии
|
||||||
|

|
||||||
|
### 8.7 Вставляем токен в веб интерфейс esp
|
||||||
|

|
||||||
|
|
||||||
|
# Часть 3. Создание сценариев отправки push
|
||||||
|
|
||||||
|
### 9.1. Сценарий для отправки push. Заходим в My Scenarios:
|
||||||
|

|
||||||
|
|
||||||
|
### 9.2 Пишем слово push (это имя сценария отправки email) жмем add:
|
||||||
|

|
||||||
|
### 9.3 Нажимаем add an action
|
||||||
|

|
||||||
|
### 9.4 Выбираем наш pushbullet который мы зарегестрировали ранее и нажимаем Add an action with this service
|
||||||
|

|
||||||
|
### 9.5 Делаем все как на скриншоте и жмем submit
|
||||||
|

|
||||||
|
### 9.6 Возвращаемся на мои сценарии
|
||||||
|

|
||||||
|
### 9.7 Вставляем токен в веб интерфейс esp
|
||||||
|

|
||||||
|
|
||||||
|
# Часть 4. Итог
|
||||||
|
|
||||||
|
При создании такой конфигурации как на картинке:
|
||||||
|
|
||||||
|
`button 1 na Отправить#push Push 0 1`
|
||||||
|
|
||||||
|
|
||||||
|
`button1 = 1`
|
||||||
|
`push внимание кнопка#нажата`
|
||||||
|
`end`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Если мы введем токен для email то будут приходить email
|
||||||
|

|
||||||
|
|
||||||
|
Если для push то будут приходить push в pushbullet
|
||||||
|

|
||||||
|
|
||||||
|
Способ описанный в данной инструкции более сложный в настройке но зато очень надежный.
|
||||||
32
doc/3.txt
Normal file
32
doc/3.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
### 1. Скачать архив из [релизов](https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/releases) или из закрепленного сообщения группы телеграм с последней версией прошивки
|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### 2. Для ESP8266 c 4 и больше мб памяти (все сделать как на скриншотах)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
### 2. Для ESP8266 c 1 мб памяти (все сделать как на скриншотах)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
***
|
||||||
|

|
||||||
|
|
||||||
|
### 2. Для ESP32 (все сделать как на скриншотах)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
3
doc/conf/c001.txt
Normal file
3
doc/conf/c001.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
button 1 5 Включить#реле Реле 0 1
|
||||||
|
|
||||||
|
//это простая кнопка номер 1 управляющая пином 5 имеющая начальное состояние 0
|
||||||
6
doc/conf/c002.txt
Normal file
6
doc/conf/c002.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
inputTime time1 Во#сколько#включить? Таймеры 20-30-00 1
|
||||||
|
inputTime time2 Во#сколько#выключить? Таймеры 20-35-00 2
|
||||||
|
button 1 5 Кнопка#(по#таймеру) Таймеры 0 3
|
||||||
|
|
||||||
|
//время в приложение необходимо вводить в строгом формате: ЧЧ-ММ-СС
|
||||||
|
//можно создавать любое количество таймеров, копируя строку inputTime...
|
||||||
4
doc/conf/c003.txt
Normal file
4
doc/conf/c003.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
button 1 5 Вкл#на#время Таймеры 0 1
|
||||||
|
inputDigit digit1 Через#сколько#секунд#выключить? Таймеры 5 2
|
||||||
|
|
||||||
|
//в сценариях можно поменять на sec, min или hours если нужны другие размерности времени
|
||||||
3
doc/conf/c004.txt
Normal file
3
doc/conf/c004.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
button 1 na Включить#все Освещение 0 1
|
||||||
|
|
||||||
|
//при нажатии на эту кнопку пины номер 5 и 13 поведут себя как установленно в сценариях
|
||||||
4
doc/conf/c005.txt
Normal file
4
doc/conf/c005.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
button 1 13 Включить#реле Реле 0 1
|
||||||
|
switch 1 0 10
|
||||||
|
|
||||||
|
//можно управлять реле на пине 13 кнопкой на пине 0 или кнопкой в приложении
|
||||||
6
doc/conf/c006.txt
Normal file
6
doc/conf/c006.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
button 1 5 Включить#все Реле 0 1
|
||||||
|
|
||||||
|
|
||||||
|
//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет
|
||||||
|
//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID
|
||||||
|
//того esp, кнопка на этом девайсе будет выключать другие устройства по воздуху
|
||||||
6
doc/conf/c007.txt
Normal file
6
doc/conf/c007.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
switch 1 0 10
|
||||||
|
|
||||||
|
//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет
|
||||||
|
//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID
|
||||||
|
//того esp, к данному модулю нужно подключить кнопку к пину 0 и тогда
|
||||||
|
//один девайс будет управлять другим по воздуху
|
||||||
6
doc/conf/c008.txt
Normal file
6
doc/conf/c008.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
pwm 1 3 Яркость#коредор: Реле 1023 1
|
||||||
|
pwm 2 4 Яркость#ванная: Реле 510 2
|
||||||
|
|
||||||
|
//в приложении появятся ползунки, соответствующее значение pwm
|
||||||
|
//будет установленно на пинах 3 и 4
|
||||||
|
//1023 и 510 это начальные значения после загрузки модуля
|
||||||
7
doc/conf/c009.txt
Normal file
7
doc/conf/c009.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
dhtT t 2 dht11 Температура#DHT,#t°C Датчики anydata 1
|
||||||
|
dhtH h 2 dht11 Влажность#DHT,#t°C Датчики anydata 2
|
||||||
|
dhtComfort Степень#комфорта: Датчики 3
|
||||||
|
dhtPerception Восприятие: Датчики 4
|
||||||
|
dhtDewpoint Точка#росы: Датчики 5
|
||||||
|
logging t 1 50 Температура Датчики 6
|
||||||
|
logging h 1 50 Влажность Датчики 7
|
||||||
7
doc/conf/c010.txt
Normal file
7
doc/conf/c010.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
dhtT t 2 dht22 Температура#DHT,#t°C Датчики anydata 1
|
||||||
|
dhtH h 2 dht22 Влажность#DHT,#t°C Датчики anydata 2
|
||||||
|
dhtComfort Степень#комфорта: Датчики 3
|
||||||
|
dhtPerception Восприятие: Датчики 4
|
||||||
|
dhtDewpoint Точка#росы: Датчики 5
|
||||||
|
logging t 1 50 Температура Датчики 6
|
||||||
|
logging h 1 50 Влажность Датчики 7
|
||||||
8
doc/conf/c011.txt
Normal file
8
doc/conf/c011.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
analog adc 0 Аналоговый#вход,#% Датчики progress-round 310 620 1 100 1
|
||||||
|
logging adc 5 100 Аналоговый#вход Датчики 2
|
||||||
|
|
||||||
|
//если датчик углекислого газа выдает напряжение от 1 вольта до 2 вольт, то значит
|
||||||
|
//значение чтения аналогового входа будут примерно равным
|
||||||
|
//при 1 вольте - 310, а при 2 вольтах - 620 (считаем по пропорции)
|
||||||
|
//данная строка переведет диапазон 310-620 в диапазон 1-100 и отобразит в приложении
|
||||||
|
//варианты отображения: anydata, progress-round, progress-line, fillgauge
|
||||||
6
doc/conf/c012.txt
Normal file
6
doc/conf/c012.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
bmp280T temp1 0x76 Температура#bmp280 Датчики anydata 1
|
||||||
|
bmp280P press1 0x76 Давление#bmp280 Датчики anydata 2
|
||||||
|
logging temp1 1 100 Температура Датчики 3
|
||||||
|
logging press1 1 100 Давление Датчики 4
|
||||||
|
|
||||||
|
//Чтение и логгирование датчика bmp280. Датчик подключается к шине i2c (esp8266 - gpio 5, 4)
|
||||||
9
doc/conf/c013.txt
Normal file
9
doc/conf/c013.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
bme280T temp1 0x76 Температура#bmp280 Датчики anydata 1
|
||||||
|
bme280P pres1 0x76 Давление#bmp280 Датчики anydata 2
|
||||||
|
bme280H hum1 0x76 Влажность#bmp280 Датчики anydata 3
|
||||||
|
bme280A altit1 0x76 Высота#bmp280 Датчики anydata 4
|
||||||
|
logging temp1 1 100 Температура Датчики 5
|
||||||
|
logging press1 1 100 Давление Датчики 6
|
||||||
|
logging hum1 1 100 Влажность Датчики 7
|
||||||
|
|
||||||
|
//Чтение и логгирование датчика bme280. Датчик подключается к шине i2c (esp8266 - gpio 5, 4)
|
||||||
7
doc/conf/c014.txt
Normal file
7
doc/conf/c014.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
dallas temp1 2 1 Температура Датчики anydata 1
|
||||||
|
dallas temp2 2 2 Температура Датчики anydata 2
|
||||||
|
logging temp1 1 100 Температура Датчики 3
|
||||||
|
logging temp2 1 100 Температура Датчики 4
|
||||||
|
|
||||||
|
//2 - номер пина датчика
|
||||||
|
//варианты отображения: anydata, progress-round, progress-line, fillgauge
|
||||||
12
doc/conf/c015.txt
Normal file
12
doc/conf/c015.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
dallas 2 Водонагреватель,#t°C Термостат anydata 1
|
||||||
|
logging dallas 5 100 Температура Термостат 2
|
||||||
|
inputDigit digit1 При#скольки#выключить? Термостат 40 3
|
||||||
|
inputDigit digit2 При#скольки#включить? Термостат 20 4
|
||||||
|
button 1 5 Нагреватель Термостат 0 5
|
||||||
|
button 2 line1,line2, Автоматический#режим Термостат 1 6
|
||||||
|
|
||||||
|
//2 - номер пина датчика
|
||||||
|
//5 - номер пина реле
|
||||||
|
//это термостат который будет держать температуру между двумя
|
||||||
|
//установленными в приложении значениями, так же можно выключить
|
||||||
|
//автоматический режим, и тогда нагреватель будет управляться в ручную
|
||||||
12
doc/conf/c016.txt
Normal file
12
doc/conf/c016.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
levelPr p 14 12 Уровень#в#баке,#% Датчики fillgauge 125 25 1
|
||||||
|
ultrasonicCm cm 14 12 Дистанция,#см Датчики anydata 2
|
||||||
|
inputDigit digit1 При#скольки#выключить? Датчики 95 3
|
||||||
|
inputDigit digit2 При#скольки#включить? Датчики 10 4
|
||||||
|
button 1 5 Насос Датчики 0 5
|
||||||
|
logging p 1 100 Вода#в#баке Датчики 6
|
||||||
|
|
||||||
|
//125 - это расстояние от датчика до дна бака в сантиметрах
|
||||||
|
//25 - это расстояние от датчика до поверхности воды когда бак полный в сантиметрах
|
||||||
|
//distancePr - эта строка выводит процент заполнения бака
|
||||||
|
//distanceCm - эта строка выводит расстояние в сантиметрах
|
||||||
|
//варианты отображения: anydata, progress-round, progress-line, fillgauge
|
||||||
11
doc/conf/c017.txt
Normal file
11
doc/conf/c017.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
button 1 5 Прихожая Освещение 0 1
|
||||||
|
inputDigit digit1 Задержка#выключения Освещение 30 2
|
||||||
|
switch 1 0 10
|
||||||
|
|
||||||
|
//0 - номер пина датчика движения
|
||||||
|
//5 - номер пина реле
|
||||||
|
//при срабатывании датчика движения включится реле и обратный таймер на 30 сек
|
||||||
|
//если движение не будет обнаружено повтороно в течении 30 секунд - свет выключится
|
||||||
|
//если движение повторится в течении 30 секунд то таймер продлится опять на 30 сек
|
||||||
|
//свет выключится только в том случае если в комнате все замрет на 30 сек
|
||||||
|
//задержку выключения можно будет настраивать в приложении
|
||||||
12
doc/conf/c018.txt
Normal file
12
doc/conf/c018.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
switch 1 0 20
|
||||||
|
text 1 Вход: Охрана 1
|
||||||
|
textSet 1 не#обнаружено-time
|
||||||
|
button 1 na Сбросить Охрана 0 2
|
||||||
|
button 2 line3, Включить#push Охрана 1 3
|
||||||
|
|
||||||
|
//0 - номер пина датчика
|
||||||
|
//при срабатывании датчика движения устройство пошлет пуш и в приложении будет
|
||||||
|
//написано в текстовом поле, что движение было обнаружено
|
||||||
|
//так же будет зафиксирован момент времени срабатывания датчика
|
||||||
|
//в приложении можно отключать отправку пуш сообщений на тот случай если дома хозяин
|
||||||
|
//перевести датчик снова в режим ожидания движения можно нажав кнопку сброса в приложении
|
||||||
17
doc/conf/c019.txt
Normal file
17
doc/conf/c019.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
stepper 1 12 4
|
||||||
|
stepper 2 13 5
|
||||||
|
button 1 na Открыть#штору#1 Шторы 0 1
|
||||||
|
button 2 na Открыть#штору#2 Шторы 0 2
|
||||||
|
|
||||||
|
//для подключения необходим драйвер шагового двигателя A4988
|
||||||
|
|
||||||
|
//stepper 1 12 4 шаговый двигатель с параметрами: 1 - номер шагового двигателя,
|
||||||
|
//12 - номер пина количества шагов, 4 - номер пина направления
|
||||||
|
|
||||||
|
//stepper 2 13 5 шаговый двигатель с параметрами: 2 - номер шагового двигателя,
|
||||||
|
//13 - номер пина количества шагов, 5 - номер пина направления
|
||||||
|
|
||||||
|
//stepperSet 1 200 5 - прокрутить шаговик номер 1 на 200 шагов по часовой стрелке
|
||||||
|
//с задержкой между шагами 5 милисекунд (чем меньше задержка тем больше скорость)
|
||||||
|
//если поставить -200 то будет вращаться против часовой стрелки
|
||||||
|
//можно подключить не более двух шаговиков
|
||||||
17
doc/conf/c020.txt
Normal file
17
doc/conf/c020.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
servo 1 12 50 Мой#сервопривод Сервоприводы 0 100 0 180 1
|
||||||
|
servo 2 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2
|
||||||
|
button 1 na Открыть1 Сервоприводы 0 3
|
||||||
|
button 2 na Открыть2 Сервоприводы 0 4
|
||||||
|
|
||||||
|
//Можно создавать не более двух сервоприводов на одном устройстве.
|
||||||
|
//1 - номер привода
|
||||||
|
//12 - номер пина
|
||||||
|
//50 - начальное значение в процентах
|
||||||
|
|
||||||
|
//0 - 100 диапазон ползунка
|
||||||
|
//0 - 180 диапазон угла
|
||||||
|
|
||||||
|
//Представим ситуацию когда есть некая заслонка и при угле в 30 градусов она закрыта,
|
||||||
|
//а при угле в 90 градусов открыта. В этом случае необходимо написать
|
||||||
|
//0 100 30 90 и тогда поставив ползунок в 0 % серва встанет в положение 30 градусов,
|
||||||
|
//а если поставить ползунок в 100 % серва встанет в положение 90 градусов.
|
||||||
7
doc/conf/c021.txt
Normal file
7
doc/conf/c021.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
serialBegin 9600 12 13
|
||||||
|
button 1 na Управляется#из#arduino Serial 0 1
|
||||||
|
button 2 na Отправить#в#arduino Serial 0 2
|
||||||
|
text 1 Текст#из#arduino Serial 3
|
||||||
|
|
||||||
|
//12 13 это пины uart к которым вы можете подключить arduino. Скетч для arduino выложен в группу.
|
||||||
|
//команда serialWrite ard-on отправит в arduino текст ard-on
|
||||||
12
doc/conf/c100.txt
Normal file
12
doc/conf/c100.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
button 1 na Включить#все Реле 0 1
|
||||||
|
button 2 13 Прихожая Реле 0 2
|
||||||
|
button 3 14 Кухня Реле 0 3
|
||||||
|
pwm 1 3 Яркость#коредор: Реле 1023 4
|
||||||
|
pwm 2 4 Яркость#ванная: Реле 510 5
|
||||||
|
analog adc 0 Аналоговый#вход Датчики fillgauge 1 1023 1 1023 6
|
||||||
|
logging adc 1 100 Аналоговый#вход Датчики 7
|
||||||
|
|
||||||
|
//Это демо конфигурация. В ней показано как связать кнопки c помощью сценариев
|
||||||
|
//Кнопка номер 1 связана с кнопкой 2, 3 и с pwm 2
|
||||||
|
//Так же продемонстрированна система логгирования данных строкой logging
|
||||||
|
//1 - это интервал между точками в минутах, 100 это количество точек
|
||||||
1
doc/conf/s001.txt
Normal file
1
doc/conf/s001.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
6
doc/conf/s002.txt
Normal file
6
doc/conf/s002.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
timenow = time1
|
||||||
|
buttonSet 1 1
|
||||||
|
end
|
||||||
|
timenow = time2
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
6
doc/conf/s003.txt
Normal file
6
doc/conf/s003.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
button1 = 1
|
||||||
|
timerStart 1 digit1 sec
|
||||||
|
end
|
||||||
|
timer1 = 0
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
8
doc/conf/s004.txt
Normal file
8
doc/conf/s004.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
button1 = 1
|
||||||
|
pinSet 5 1
|
||||||
|
pinSet 13 0
|
||||||
|
end
|
||||||
|
button1 = 0
|
||||||
|
pinSet 5 0
|
||||||
|
pinSet 13 1
|
||||||
|
end
|
||||||
3
doc/conf/s005.txt
Normal file
3
doc/conf/s005.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
switch1 = 1
|
||||||
|
buttonChange 1
|
||||||
|
end
|
||||||
8
doc/conf/s006.txt
Normal file
8
doc/conf/s006.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
button1 = 1
|
||||||
|
mqtt 3233662-1589485 buttonSet_1_1
|
||||||
|
mqtt 2233662-1589486 buttonSet_1_1
|
||||||
|
end
|
||||||
|
button1 = 0
|
||||||
|
mqtt 3233662-1589485 buttonSet_1_0
|
||||||
|
mqtt 2233662-1589486 buttonSet_1_0
|
||||||
|
end
|
||||||
4
doc/conf/s007.txt
Normal file
4
doc/conf/s007.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
switch1 = 1
|
||||||
|
mqtt 3233662-1589485 buttonChange_1
|
||||||
|
mqtt 2233662-1589486 buttonChange_1
|
||||||
|
end
|
||||||
1
doc/conf/s008.txt
Normal file
1
doc/conf/s008.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s009.txt
Normal file
1
doc/conf/s009.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s010.txt
Normal file
1
doc/conf/s010.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s011.txt
Normal file
1
doc/conf/s011.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s012.txt
Normal file
1
doc/conf/s012.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s013.txt
Normal file
1
doc/conf/s013.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
doc/conf/s014.txt
Normal file
1
doc/conf/s014.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
6
doc/conf/s015.txt
Normal file
6
doc/conf/s015.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
dallas > digit1
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
|
dallas < digit2
|
||||||
|
buttonSet 1 1
|
||||||
|
end
|
||||||
6
doc/conf/s016.txt
Normal file
6
doc/conf/s016.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
p > digit1
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
|
p < digit2
|
||||||
|
buttonSet 1 1
|
||||||
|
end
|
||||||
7
doc/conf/s017.txt
Normal file
7
doc/conf/s017.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
switch1 = 1
|
||||||
|
timerStart 1 digit1 sec
|
||||||
|
buttonSet 1 1
|
||||||
|
end
|
||||||
|
timer1 = 0
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
10
doc/conf/s018.txt
Normal file
10
doc/conf/s018.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
switch1 = 1
|
||||||
|
textSet 1 обнаружено#движение-time
|
||||||
|
end
|
||||||
|
button1 = 1
|
||||||
|
textSet 1 не#обнаружено-time
|
||||||
|
buttonSet 1 0
|
||||||
|
end
|
||||||
|
switch1 = 1
|
||||||
|
push Внимание обнаружено#движение!
|
||||||
|
end
|
||||||
12
doc/conf/s019.txt
Normal file
12
doc/conf/s019.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
button1 = 1
|
||||||
|
stepperSet 1 200 1
|
||||||
|
end
|
||||||
|
button1 = 0
|
||||||
|
stepperSet 1 -200 1
|
||||||
|
end
|
||||||
|
button2 = 1
|
||||||
|
stepperSet 2 200 1
|
||||||
|
end
|
||||||
|
button2 = 0
|
||||||
|
stepperSet 2 -200 1
|
||||||
|
end
|
||||||
12
doc/conf/s020.txt
Normal file
12
doc/conf/s020.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
button1 = 1
|
||||||
|
servoSet 1 100
|
||||||
|
end
|
||||||
|
button1 = 0
|
||||||
|
servoSet 1 0
|
||||||
|
end
|
||||||
|
button2 = 1
|
||||||
|
servoSet 2 100
|
||||||
|
end
|
||||||
|
button2 = 0
|
||||||
|
servoSet 2 0
|
||||||
|
end
|
||||||
6
doc/conf/s021.txt
Normal file
6
doc/conf/s021.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
button2 = 1
|
||||||
|
serialWrite ard-11-1
|
||||||
|
end
|
||||||
|
button2 = 0
|
||||||
|
serialWrite ard-11-0
|
||||||
|
end
|
||||||
13
doc/conf/s100.txt
Normal file
13
doc/conf/s100.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
button1 = 1
|
||||||
|
buttonSet 2 1
|
||||||
|
buttonSet 3 1
|
||||||
|
pwmSet 2 1024
|
||||||
|
end
|
||||||
|
button1 = 0
|
||||||
|
buttonSet 2 0
|
||||||
|
buttonSet 3 0
|
||||||
|
pwmSet 2 0
|
||||||
|
end
|
||||||
|
adc > 50
|
||||||
|
buttonSet 2 1
|
||||||
|
end
|
||||||
BIN
doc/orders.xlsm
Normal file
BIN
doc/orders.xlsm
Normal file
Binary file not shown.
BIN
doc/pictures/001 iot manager.jpeg
Normal file
BIN
doc/pictures/001 iot manager.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
doc/pictures/002 iot manager.jpeg
Normal file
BIN
doc/pictures/002 iot manager.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
doc/pictures/003 iot manager.jpeg
Normal file
BIN
doc/pictures/003 iot manager.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
doc/pictures/007 iot manager.jpg
Normal file
BIN
doc/pictures/007 iot manager.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 381 KiB |
56
include/Bus/BusScanner.h
Normal file
56
include/Bus/BusScanner.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
class BusScanner {
|
||||||
|
public:
|
||||||
|
BusScanner(const char* tag, String& out, size_t tries) : _found{0},
|
||||||
|
_tries{tries},
|
||||||
|
_out{&out} {
|
||||||
|
_tag = new char(strlen(tag) + 1);
|
||||||
|
strcpy(_tag, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan() {
|
||||||
|
init();
|
||||||
|
bool res;
|
||||||
|
do {
|
||||||
|
res = syncScan();
|
||||||
|
} while (!res && --_tries);
|
||||||
|
|
||||||
|
if (!_found) {
|
||||||
|
addResult("не найдено");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* tag() {
|
||||||
|
return _tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void init(){};
|
||||||
|
|
||||||
|
virtual boolean syncScan() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void addResult(const String& str) {
|
||||||
|
_out->concat(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addResult(uint8_t addr, boolean last = true) {
|
||||||
|
_found++;
|
||||||
|
String str = "0x";
|
||||||
|
if (addr < 16) {
|
||||||
|
str += "0";
|
||||||
|
}
|
||||||
|
str += String(addr, HEX);
|
||||||
|
str += !last ? ", " : ", ";
|
||||||
|
addResult(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* _tag;
|
||||||
|
size_t _found;
|
||||||
|
size_t _tries;
|
||||||
|
String* _out;
|
||||||
|
};
|
||||||
18
include/Bus/BusScannerFactory.h
Normal file
18
include/Bus/BusScannerFactory.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Bus/BusScanner.h"
|
||||||
|
#include "Bus/I2CScanner.h"
|
||||||
|
#include "Consts.h"
|
||||||
|
#include "Utils/JsonUtils.h"
|
||||||
|
|
||||||
|
class BusScannerFactory {
|
||||||
|
public:
|
||||||
|
static BusScanner* get(String& config, BusScanner_t type, String& str) {
|
||||||
|
switch (type) {
|
||||||
|
case BS_I2C:
|
||||||
|
return new I2CScanner(str);
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
12
include/Bus/I2CScanner.h
Normal file
12
include/Bus/I2CScanner.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Bus/BusScanner.h"
|
||||||
|
|
||||||
|
class I2CScanner : public BusScanner {
|
||||||
|
public:
|
||||||
|
I2CScanner(String& out);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void init() override;
|
||||||
|
virtual boolean syncScan() override;
|
||||||
|
};
|
||||||
26
include/Class/CallBackTest.h
Normal file
26
include/Class/CallBackTest.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
// Декларируем тип - сигнатуру метода , который мы готовы принять в данном случае это
|
||||||
|
// должен быть метод без результата и без параметров.
|
||||||
|
// Новый тип мы называем AsynсActionCb - хотя можешь назвать вообще как нравиться а что значит callBack
|
||||||
|
|
||||||
|
typedef std::function<void()> AsyncActionCb; //метод без результата и параметров
|
||||||
|
typedef std::function<bool(const String)> AsyncParamActionCb; //метод без результата и параметров
|
||||||
|
|
||||||
|
class CallBackTest {
|
||||||
|
private:
|
||||||
|
long count;
|
||||||
|
AsyncActionCb _cb;
|
||||||
|
AsyncParamActionCb _pcb;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
CallBackTest();
|
||||||
|
void loop();
|
||||||
|
void setCallback(AsyncActionCb cb);
|
||||||
|
void setCallback(AsyncParamActionCb pcb);
|
||||||
|
};
|
||||||
|
//extern CallBackTest* CB;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user