mirror of
https://github.com/s00500/ESPUI.git
synced 2025-07-03 19:50:20 +00:00
Compare commits
2 Commits
1.6.1
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
b7b6b8a3cd | |||
bec4eb1c0f |
284
examples/gui/data/js/controls.js
vendored
284
examples/gui/data/js/controls.js
vendored
@ -1,4 +1,3 @@
|
|||||||
const UI_INITIAL_GUI = 100;
|
|
||||||
const UI_TITEL = 0;
|
const UI_TITEL = 0;
|
||||||
|
|
||||||
const UI_LABEL = 1;
|
const UI_LABEL = 1;
|
||||||
@ -113,37 +112,26 @@ function handleVisibilityChange() {
|
|||||||
function start() {
|
function start() {
|
||||||
document.addEventListener("visibilitychange", handleVisibilityChange, false);
|
document.addEventListener("visibilitychange", handleVisibilityChange, false);
|
||||||
websock = new WebSocket("ws://" + window.location.hostname + "/ws");
|
websock = new WebSocket("ws://" + window.location.hostname + "/ws");
|
||||||
websock.onopen = function (evt) {
|
websock.onopen = function(evt) {
|
||||||
console.log("websock open");
|
console.log("websock open");
|
||||||
$("#conStatus").addClass("color-green");
|
$("#conStatus").addClass("color-green");
|
||||||
$("#conStatus").text("Connected");
|
$("#conStatus").text("Connected");
|
||||||
websockConnected = true;
|
websockConnected = true;
|
||||||
};
|
};
|
||||||
|
websock.onclose = function(evt) {
|
||||||
websock.onclose = function (evt) {
|
|
||||||
console.log("websock close");
|
console.log("websock close");
|
||||||
conStatusError();
|
conStatusError();
|
||||||
};
|
};
|
||||||
|
websock.onerror = function(evt) {
|
||||||
websock.onerror = function (evt) {
|
|
||||||
console.log(evt);
|
console.log(evt);
|
||||||
conStatusError();
|
conStatusError();
|
||||||
};
|
};
|
||||||
|
websock.onmessage = function(evt) {
|
||||||
var handleEvent = function (evt) {
|
console.log(evt);
|
||||||
//console.log(evt);
|
|
||||||
var data = JSON.parse(evt.data);
|
var data = JSON.parse(evt.data);
|
||||||
var e = document.body;
|
var e = document.body;
|
||||||
var center = "";
|
var center = "";
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case UI_INITIAL_GUI:
|
|
||||||
data.controls.forEach(element => {
|
|
||||||
var fauxEvent = {
|
|
||||||
data: JSON.stringify(element)
|
|
||||||
};
|
|
||||||
handleEvent(fauxEvent);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case UI_TITEL:
|
case UI_TITEL:
|
||||||
document.title = data.label;
|
document.title = data.label;
|
||||||
$("#mainHeader").html(data.label);
|
$("#mainHeader").html(data.label);
|
||||||
@ -151,42 +139,42 @@ function start() {
|
|||||||
case UI_LABEL:
|
case UI_LABEL:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='two columns card tcenter " +
|
"<div class='two columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'><h5 id='" +
|
"'><h5 id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>" +
|
"'>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr /><span id='l" +
|
"</h5><hr /><span id='l" +
|
||||||
data.id +
|
data.id +
|
||||||
"' class='label label-wrap'>" +
|
"' class='label label-wrap'>" +
|
||||||
data.value +
|
data.value +
|
||||||
"</span></div>"
|
"</span></div>"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case UI_BUTTON:
|
case UI_BUTTON:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='one columns card tcenter " +
|
"<div class='one columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'><h5>" +
|
"'><h5>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr/><button onmousedown='buttonclick(" +
|
"</h5><hr/><button onmousedown='buttonclick(" +
|
||||||
data.id +
|
data.id +
|
||||||
", true)' onmouseup='buttonclick(" +
|
", true)' onmouseup='buttonclick(" +
|
||||||
data.id +
|
data.id +
|
||||||
", false)' id='" +
|
", false)' id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>" +
|
"'>" +
|
||||||
data.value +
|
data.value +
|
||||||
"</button></div>"
|
"</button></div>"
|
||||||
);
|
);
|
||||||
$("#" + data.id).on({
|
$("#" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
buttonclick(data.id, true);
|
buttonclick(data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#" + data.id).on({
|
$("#" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
buttonclick(data.id, false);
|
buttonclick(data.id, false);
|
||||||
}
|
}
|
||||||
@ -211,16 +199,16 @@ function start() {
|
|||||||
}
|
}
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div id='" +
|
"<div id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"' class='one columns card tcenter " +
|
"' class='one columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'><h5>" +
|
"'><h5>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr/>" +
|
"</h5><hr/>" +
|
||||||
label +
|
label +
|
||||||
input +
|
input +
|
||||||
"</label>" +
|
"</label>" +
|
||||||
"</div>"
|
"</div>"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case UI_CPAD:
|
case UI_CPAD:
|
||||||
@ -232,106 +220,106 @@ function start() {
|
|||||||
", false)' href='#' id='pc" +
|
", false)' href='#' id='pc" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>OK</a>";
|
"'>OK</a>";
|
||||||
//NO BREAK
|
//NO BREAK
|
||||||
case UI_PAD:
|
case UI_PAD:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='two columns card tcenter " +
|
"<div class='two columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'><h5>" +
|
"'><h5>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr/>" +
|
"</h5><hr/>" +
|
||||||
"<nav class='control'>" +
|
"<nav class='control'>" +
|
||||||
"<ul>" +
|
"<ul>" +
|
||||||
"<li><a onmousedown='padclick(FOR, " +
|
"<li><a onmousedown='padclick(FOR, " +
|
||||||
data.id +
|
data.id +
|
||||||
", true)' onmouseup='padclick(FOR, " +
|
", true)' onmouseup='padclick(FOR, " +
|
||||||
data.id +
|
data.id +
|
||||||
", false)' href='#' id='pf" +
|
", false)' href='#' id='pf" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>▲</a></li>" +
|
"'>▲</a></li>" +
|
||||||
"<li><a onmousedown='padclick(RIGHT, " +
|
"<li><a onmousedown='padclick(RIGHT, " +
|
||||||
data.id +
|
data.id +
|
||||||
", true)' onmouseup='padclick(RIGHT, " +
|
", true)' onmouseup='padclick(RIGHT, " +
|
||||||
data.id +
|
data.id +
|
||||||
", false)' href='#' id='pr" +
|
", false)' href='#' id='pr" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>▲</a></li>" +
|
"'>▲</a></li>" +
|
||||||
"<li><a onmousedown='padclick(LEFT, " +
|
"<li><a onmousedown='padclick(LEFT, " +
|
||||||
data.id +
|
data.id +
|
||||||
", true)' onmouseup='padclick(LEFT, " +
|
", true)' onmouseup='padclick(LEFT, " +
|
||||||
data.id +
|
data.id +
|
||||||
", false)' href='#' id='pl" +
|
", false)' href='#' id='pl" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>▲</a></li>" +
|
"'>▲</a></li>" +
|
||||||
"<li><a onmousedown='padclick(BACK, " +
|
"<li><a onmousedown='padclick(BACK, " +
|
||||||
data.id +
|
data.id +
|
||||||
", true)' onmouseup='padclick(BACK, " +
|
", true)' onmouseup='padclick(BACK, " +
|
||||||
data.id +
|
data.id +
|
||||||
", false)' href='#' id='pb" +
|
", false)' href='#' id='pb" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>▲</a></li>" +
|
"'>▲</a></li>" +
|
||||||
"</ul>" +
|
"</ul>" +
|
||||||
center +
|
center +
|
||||||
"</nav>" +
|
"</nav>" +
|
||||||
"</div>"
|
"</div>"
|
||||||
);
|
);
|
||||||
|
|
||||||
$("#pf" + data.id).on({
|
$("#pf" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(FOR, data.id, true);
|
padclick(FOR, data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pf" + data.id).on({
|
$("#pf" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(FOR, data.id, false);
|
padclick(FOR, data.id, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pl" + data.id).on({
|
$("#pl" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(LEFT, data.id, true);
|
padclick(LEFT, data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pl" + data.id).on({
|
$("#pl" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(LEFT, data.id, false);
|
padclick(LEFT, data.id, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pr" + data.id).on({
|
$("#pr" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(RIGHT, data.id, true);
|
padclick(RIGHT, data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pr" + data.id).on({
|
$("#pr" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(RIGHT, data.id, false);
|
padclick(RIGHT, data.id, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pb" + data.id).on({
|
$("#pb" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(BACK, data.id, true);
|
padclick(BACK, data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pb" + data.id).on({
|
$("#pb" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(BACK, data.id, false);
|
padclick(BACK, data.id, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pc" + data.id).on({
|
$("#pc" + data.id).on({
|
||||||
touchstart: function (e) {
|
touchstart: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(CENTER, data.id, true);
|
padclick(CENTER, data.id, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#pc" + data.id).on({
|
$("#pc" + data.id).on({
|
||||||
touchend: function (e) {
|
touchend: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
padclick(CENTER, data.id, false);
|
padclick(CENTER, data.id, false);
|
||||||
}
|
}
|
||||||
@ -348,23 +336,23 @@ function start() {
|
|||||||
case UI_SLIDER:
|
case UI_SLIDER:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='two columns card tcenter card-slider " +
|
"<div class='two columns card tcenter card-slider " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'>" +
|
"'>" +
|
||||||
"<h5 id='" +
|
"<h5 id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>" +
|
"'>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr />" +
|
"</h5><hr />" +
|
||||||
"<div id='sl" +
|
"<div id='sl" +
|
||||||
data.id +
|
data.id +
|
||||||
"' class='rkmd-slider slider-discrete slider-" +
|
"' class='rkmd-slider slider-discrete slider-" +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'>" +
|
"'>" +
|
||||||
"<input type='range' min='0' max='100' value='" +
|
"<input type='range' min='0' max='100' value='" +
|
||||||
data.value +
|
data.value +
|
||||||
"'>" +
|
"'>" +
|
||||||
"</div>" +
|
"</div>" +
|
||||||
"</div>"
|
"</div>"
|
||||||
);
|
);
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<script>" + "rkmd_rangeSlider('#sl" + data.id + "');" + "</script>"
|
"<script>" + "rkmd_rangeSlider('#sl" + data.id + "');" + "</script>"
|
||||||
@ -378,21 +366,21 @@ function start() {
|
|||||||
case UI_NUMBER:
|
case UI_NUMBER:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='two columns card tcenter " +
|
"<div class='two columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'>" +
|
"'>" +
|
||||||
"<h5 id='" +
|
"<h5 id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>" +
|
"'>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr />" +
|
"</h5><hr />" +
|
||||||
"<input style='color:black;' id='num" +
|
"<input style='color:black;' id='num" +
|
||||||
data.id +
|
data.id +
|
||||||
"' type='number' value='" +
|
"' type='number' value='" +
|
||||||
data.value +
|
data.value +
|
||||||
"' onchange='numberchange(" +
|
"' onchange='numberchange(" +
|
||||||
data.id +
|
data.id +
|
||||||
")' />" +
|
")' />" +
|
||||||
"</div>"
|
"</div>"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -403,21 +391,21 @@ function start() {
|
|||||||
case UI_TEXT_INPUT:
|
case UI_TEXT_INPUT:
|
||||||
$("#row").append(
|
$("#row").append(
|
||||||
"<div class='two columns card tcenter " +
|
"<div class='two columns card tcenter " +
|
||||||
colorClass(data.color) +
|
colorClass(data.color) +
|
||||||
"'>" +
|
"'>" +
|
||||||
"<h5 id='" +
|
"<h5 id='" +
|
||||||
data.id +
|
data.id +
|
||||||
"'>" +
|
"'>" +
|
||||||
data.label +
|
data.label +
|
||||||
"</h5><hr />" +
|
"</h5><hr />" +
|
||||||
"<input style='color:black;' id='text" +
|
"<input style='color:black;' id='text" +
|
||||||
data.id +
|
data.id +
|
||||||
"' value='" +
|
"' value='" +
|
||||||
data.value +
|
data.value +
|
||||||
"' onchange='textchange(" +
|
"' onchange='textchange(" +
|
||||||
data.id +
|
data.id +
|
||||||
")' />" +
|
")' />" +
|
||||||
"</div>"
|
"</div>"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -430,8 +418,6 @@ function start() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
websock.onmessage = handleEvent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function numberchange(number) {
|
function numberchange(number) {
|
||||||
|
6
examples/gui/data/js/controls.min.js
vendored
6
examples/gui/data/js/controls.min.js
vendored
@ -1,8 +1,8 @@
|
|||||||
const UI_INITIAL_GUI=100;const UI_TITEL=0;const UI_LABEL=1;const UPDATE_LABEL=6;const UI_BUTTON=2;const UI_SWITCHER=3;const UPDATE_SWITCHER=7;const UI_PAD=4;const UI_CPAD=5;const UI_SLIDER=8;const UPDATE_SLIDER=9;const UI_NUMBER=10;const UPDATE_NUMBER=11;const UI_TEXT_INPUT=12;const UPDATE_TEXT_INPUT=13;const UI_GRAPH=14;const CLEAR_GRAPH=15;const ADD_GRAPH_POINT=16;const FOR=0;const BACK=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_NONE=7;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";break;case C_EMERALD:return"emerald";break;case C_PETERRIVER:return"peterriver";break;case C_WETASPHALT:return"wetasphalt";break;case C_SUNFLOWER:return"sunflower";break;case C_CARROT:return"carrot";break;case C_ALIZARIN:return"alizarin";break;case C_NONE:return"";break;default:return"";}}
|
const UI_TITEL=0;const UI_LABEL=1;const UPDATE_LABEL=6;const UI_BUTTON=2;const UI_SWITCHER=3;const UPDATE_SWITCHER=7;const UI_PAD=4;const UI_CPAD=5;const UI_SLIDER=8;const UPDATE_SLIDER=9;const UI_NUMBER=10;const UPDATE_NUMBER=11;const UI_TEXT_INPUT=12;const UPDATE_TEXT_INPUT=13;const UI_GRAPH=14;const CLEAR_GRAPH=15;const ADD_GRAPH_POINT=16;const FOR=0;const BACK=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_NONE=7;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";break;case C_EMERALD:return"emerald";break;case C_PETERRIVER:return"peterriver";break;case C_WETASPHALT:return"wetasphalt";break;case C_SUNFLOWER:return"sunflower";break;case C_CARROT:return"carrot";break;case C_ALIZARIN:return"alizarin";break;case C_NONE:return"";break;default:return"";}}
|
||||||
var websock;var websockConnected=false;function restart(){$(document).add("*").off();$("#row").html("");websock.close();start();}
|
var websock;var websockConnected=false;function restart(){$(document).add("*").off();$("#row").html("");websock.close();start();}
|
||||||
function conStatusError(){websockConnected=false;$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart});}
|
function conStatusError(){websockConnected=false;$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart});}
|
||||||
function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
|
function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
|
||||||
function start(){document.addEventListener("visibilitychange",handleVisibilityChange,false);websock=new WebSocket("ws://"+window.location.hostname+"/ws");websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log(evt);conStatusError();};var handleEvent=function(evt){var data=JSON.parse(evt.data);var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element)};handleEvent(fauxEvent);});break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:$("#row").append("<div class='two columns card tcenter "+
|
function start(){document.addEventListener("visibilitychange",handleVisibilityChange,false);websock=new WebSocket("ws://"+window.location.hostname+"/ws");websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log(evt);conStatusError();};websock.onmessage=function(evt){console.log(evt);var data=JSON.parse(evt.data);var e=document.body;var center="";switch(data.type){case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:$("#row").append("<div class='two columns card tcenter "+
|
||||||
colorClass(data.color)+
|
colorClass(data.color)+
|
||||||
"'><h5 id='"+
|
"'><h5 id='"+
|
||||||
data.id+
|
data.id+
|
||||||
@ -134,7 +134,7 @@ data.value+
|
|||||||
"' onchange='textchange("+
|
"' onchange='textchange("+
|
||||||
data.id+
|
data.id+
|
||||||
")' />"+
|
")' />"+
|
||||||
"</div>");break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;default:console.error("Unknown type or event");break;}};websock.onmessage=handleEvent;}
|
"</div>");break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;default:console.error("Unknown type or event");break;}};}
|
||||||
function numberchange(number){var val=$("#num"+number).val();websock.send("nvalue:"+val+":"+number);console.log(val);}
|
function numberchange(number){var val=$("#num"+number).val();websock.send("nvalue:"+val+":"+number);console.log(val);}
|
||||||
function textchange(number){var val=$("#text"+number).val();websock.send("tvalue:"+val+":"+number);console.log(val);}
|
function textchange(number){var val=$("#text"+number).val();websock.send("tvalue:"+val+":"+number);console.log(val);}
|
||||||
function buttonclick(number,isdown){if(isdown)websock.send("bdown:"+number);else websock.send("bup:"+number);}
|
function buttonclick(number,isdown){if(isdown)websock.send("bdown:"+number);else websock.send("bup:"+number);}
|
||||||
|
@ -157,19 +157,11 @@ void setup(void) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
.begin loads and serves all files from PROGMEM directly.
|
.begin loads and serves all files from PROGMEM directly.
|
||||||
If you want to serve the files from SPIFFS use ESPUI.beginSPIFFS
|
If you want to serve the files from SPIFFS use .beginSPIFFS
|
||||||
(.prepareFileSystem has to be run in an empty sketch before)
|
(.prepareFileSystem has to be run in an empty sketch before)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dnsServer.start(DNS_PORT, "*", apIP);
|
dnsServer.start(DNS_PORT, "*", apIP);
|
||||||
|
|
||||||
/*
|
|
||||||
* Optionally you can use HTTP BasicAuth. Keep in mind that this is NOT a
|
|
||||||
SECURE way of limiting access.
|
|
||||||
* Anyone who is able to sniff traffic will be able to intercept your password
|
|
||||||
since it is transmitted in cleartext ESPUI.begin("ESPUI Control", "myuser",
|
|
||||||
"mypassword");
|
|
||||||
*/
|
|
||||||
ESPUI.begin("ESPUI Control");
|
ESPUI.begin("ESPUI Control");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
library.json
19
library.json
@ -6,13 +6,16 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/s00500/ESPUI.git"
|
"url": "https://github.com/s00500/ESPUI.git"
|
||||||
},
|
},
|
||||||
"authors": [{
|
"authors": [
|
||||||
"name": "Lukas Bachschwell",
|
{
|
||||||
"email": "lukas@lbsfilm.at",
|
"name": "Lukas Bachschwell",
|
||||||
"url": "https://lbsfilm.at",
|
"email": "lukas@lbsfilm.at",
|
||||||
"maintainer": true
|
"url": "https://lbsfilm.at",
|
||||||
}],
|
"maintainer": true
|
||||||
"dependencies": [{
|
}
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
"name": "ESP Async WebServer",
|
"name": "ESP Async WebServer",
|
||||||
"authors": "Hristo Gochkov",
|
"authors": "Hristo Gochkov",
|
||||||
"frameworks": "arduino"
|
"frameworks": "arduino"
|
||||||
@ -23,7 +26,7 @@
|
|||||||
"frameworks": "arduino"
|
"frameworks": "arduino"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": "1.6.1",
|
"version": "1.6.0",
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"platforms": "*"
|
"platforms": "*"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
name=ESPUI
|
name=ESPUI
|
||||||
version=1.6.1
|
version=1.6.0
|
||||||
author=Lukas Bachschwell
|
author=Lukas Bachschwell
|
||||||
maintainer=Lukas Bachschwell <lukas@lbsfilm.at>
|
maintainer=Lukas Bachschwell <lukas@lbsfilm.at>
|
||||||
sentence=ESP32 and ESP8266 Web Interface Library
|
sentence=ESP32 and ESP8266 Web Interface Library
|
||||||
|
133
src/ESPUI.cpp
133
src/ESPUI.cpp
@ -492,16 +492,6 @@ void ESPUIClass::updateSlider(int id, int nValue, int clientId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPUIClass::updateSlider(String label, int nValue, int clientId) {
|
|
||||||
if (!labelExists(label)) {
|
|
||||||
if (DEBUG_ESPUI)
|
|
||||||
Serial.println("UI ERROR: Element does not " + String(label) +
|
|
||||||
" exist, cannot update!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateSlider(getIdByLabel(label), nValue, clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESPUIClass::updateSwitcher(int id, bool nValue, int clientId) {
|
void ESPUIClass::updateSwitcher(int id, bool nValue, int clientId) {
|
||||||
if (id < cIndex && controls[id]->type == UI_SWITCHER) {
|
if (id < cIndex && controls[id]->type == UI_SWITCHER) {
|
||||||
controls[id]->value = nValue ? 1 : 0;
|
controls[id]->value = nValue ? 1 : 0;
|
||||||
@ -613,48 +603,28 @@ bool ESPUIClass::labelExists(String label) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Convert & Transfer Arduino elements to JSON elements
|
||||||
Convert & Transfer Arduino elements to JSON elements
|
|
||||||
Initially this function used to send the control element data individually.
|
|
||||||
Due to a change in the ESPAsyncWebserver library this had top be changed to be
|
|
||||||
sent as one blob at the beginning. Therefore a new type is used as well
|
|
||||||
*/
|
|
||||||
void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
|
void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
|
||||||
String json;
|
|
||||||
DynamicJsonBuffer jsonBuffer(2000);
|
|
||||||
JsonObject &root = jsonBuffer.createObject();
|
|
||||||
root["type"] = UI_INITIAL_GUI;
|
|
||||||
JsonArray &items = jsonBuffer.createArray();
|
|
||||||
|
|
||||||
for (int i = -1; i < cIndex; i++) {
|
for (int i = -1; i < cIndex; i++) {
|
||||||
JsonObject &item = jsonBuffer.createObject();
|
String json;
|
||||||
|
StaticJsonBuffer<200> jsonBuffer;
|
||||||
|
JsonObject &root = jsonBuffer.createObject();
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
item["type"] = UI_TITEL;
|
root["type"] = UI_TITEL;
|
||||||
item["label"] = String(ui_title);
|
root["label"] = String(ui_title);
|
||||||
} else {
|
} else {
|
||||||
item["type"] = controls[i]->type;
|
root["type"] = controls[i]->type;
|
||||||
item["label"] = String(controls[i]->label);
|
root["label"] = String(controls[i]->label);
|
||||||
item["value"] = String(controls[i]->value);
|
root["value"] = String(controls[i]->value);
|
||||||
item["color"] = String(controls[i]->color);
|
root["color"] = String(controls[i]->color);
|
||||||
item["id"] = String(i);
|
root["id"] = String(i);
|
||||||
}
|
}
|
||||||
items.add(item);
|
root.printTo(json);
|
||||||
|
client->text(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send as one big bunch
|
|
||||||
root["controls"] = items;
|
|
||||||
root.printTo(json);
|
|
||||||
client->text(json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPUIClass::beginSPIFFS(const char *_title) {
|
void ESPUIClass::beginSPIFFS(const char *_title) {
|
||||||
begin(_title, NULL, NULL);
|
|
||||||
basicAuth = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESPUIClass::beginSPIFFS(const char *_title, const char *username,
|
|
||||||
const char *password) {
|
|
||||||
ui_title = _title;
|
ui_title = _title;
|
||||||
server = new AsyncWebServer(80);
|
server = new AsyncWebServer(80);
|
||||||
ws = new AsyncWebSocket("/ws");
|
ws = new AsyncWebSocket("/ws");
|
||||||
@ -676,29 +646,10 @@ void ESPUIClass::beginSPIFFS(const char *_title, const char *username,
|
|||||||
|
|
||||||
ws->onEvent(onWsEvent);
|
ws->onEvent(onWsEvent);
|
||||||
server->addHandler(ws);
|
server->addHandler(ws);
|
||||||
|
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
|
||||||
if (basicAuth && username != NULL && password != NULL) {
|
|
||||||
basicAuthPassword = password;
|
|
||||||
basicAuthUsername = username;
|
|
||||||
basicAuth = true;
|
|
||||||
if (WS_AUTHENTICATION)
|
|
||||||
ws->setAuthentication(this->basicAuthUsername, this->basicAuthPassword);
|
|
||||||
server->serveStatic("/", SPIFFS, "/")
|
|
||||||
.setDefaultFile("index.htm")
|
|
||||||
.setAuthentication(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword);
|
|
||||||
|
|
||||||
} else if (basicAuth) {
|
|
||||||
Serial.println(
|
|
||||||
"Could not enable BasicAuth: Username or password are not set");
|
|
||||||
} else {
|
|
||||||
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heap for general Servertest
|
// Heap for general Servertest
|
||||||
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/plain",
|
request->send(200, "text/plain",
|
||||||
String(ESP.getFreeHeap()) + " In SPIFFSmode");
|
String(ESP.getFreeHeap()) + " In SPIFFSmode");
|
||||||
});
|
});
|
||||||
@ -706,50 +657,26 @@ void ESPUIClass::beginSPIFFS(const char *_title, const char *username,
|
|||||||
server->onNotFound(
|
server->onNotFound(
|
||||||
[](AsyncWebServerRequest *request) { request->send(404); });
|
[](AsyncWebServerRequest *request) { request->send(404); });
|
||||||
|
|
||||||
|
server->on("/zepto.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(
|
||||||
|
200, "application/javascript", JS_ZEPTO_GZIP, sizeof(JS_ZEPTO_GZIP));
|
||||||
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
|
request->send(response);
|
||||||
|
});
|
||||||
|
|
||||||
server->begin();
|
server->begin();
|
||||||
if (DEBUG_ESPUI) Serial.println("UI Initialized");
|
if (DEBUG_ESPUI) Serial.println("UI Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPUIClass::begin(const char *_title) {
|
void ESPUIClass::begin(const char *_title) {
|
||||||
begin(_title, NULL, NULL);
|
|
||||||
basicAuth = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESPUIClass::begin(const char *_title, const char *username,
|
|
||||||
const char *password) {
|
|
||||||
if (basicAuth && username != NULL && password != NULL) {
|
|
||||||
basicAuthPassword = password;
|
|
||||||
basicAuthUsername = username;
|
|
||||||
basicAuth = true;
|
|
||||||
} else if (basicAuth) {
|
|
||||||
Serial.println(
|
|
||||||
"Could not enable BasicAuth: Username or password are not set");
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_title = _title;
|
ui_title = _title;
|
||||||
|
|
||||||
server = new AsyncWebServer(80);
|
server = new AsyncWebServer(80);
|
||||||
ws = new AsyncWebSocket("/ws");
|
ws = new AsyncWebSocket("/ws");
|
||||||
|
|
||||||
ws->onEvent(onWsEvent);
|
ws->onEvent(onWsEvent);
|
||||||
server->addHandler(ws);
|
server->addHandler(ws);
|
||||||
|
|
||||||
if (basicAuth && username != NULL && password != NULL) {
|
|
||||||
basicAuthPassword = password;
|
|
||||||
basicAuthUsername = username;
|
|
||||||
basicAuth = true;
|
|
||||||
if (WS_AUTHENTICATION)
|
|
||||||
ws->setAuthentication(this->basicAuthUsername, this->basicAuthPassword);
|
|
||||||
|
|
||||||
} else if (basicAuth) {
|
|
||||||
Serial.println(
|
|
||||||
"Could not enable BasicAuth: Username or password are not set");
|
|
||||||
}
|
|
||||||
|
|
||||||
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response =
|
AsyncWebServerResponse *response =
|
||||||
request->beginResponse_P(200, "text/html", HTML_INDEX);
|
request->beginResponse_P(200, "text/html", HTML_INDEX);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -758,9 +685,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
// Javascript files
|
// Javascript files
|
||||||
|
|
||||||
server->on("/js/zepto.min.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/js/zepto.min.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(
|
AsyncWebServerResponse *response = request->beginResponse_P(
|
||||||
200, "application/javascript", JS_ZEPTO_GZIP, sizeof(JS_ZEPTO_GZIP));
|
200, "application/javascript", JS_ZEPTO_GZIP, sizeof(JS_ZEPTO_GZIP));
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
@ -768,9 +692,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
});
|
});
|
||||||
|
|
||||||
server->on("/js/controls.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/js/controls.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response =
|
AsyncWebServerResponse *response =
|
||||||
request->beginResponse_P(200, "application/javascript",
|
request->beginResponse_P(200, "application/javascript",
|
||||||
JS_CONTROLS_GZIP, sizeof(JS_CONTROLS_GZIP));
|
JS_CONTROLS_GZIP, sizeof(JS_CONTROLS_GZIP));
|
||||||
@ -779,9 +700,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
});
|
});
|
||||||
|
|
||||||
server->on("/js/slider.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/js/slider.js", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(
|
AsyncWebServerResponse *response = request->beginResponse_P(
|
||||||
200, "application/javascript", JS_SLIDER_GZIP, sizeof(JS_SLIDER_GZIP));
|
200, "application/javascript", JS_SLIDER_GZIP, sizeof(JS_SLIDER_GZIP));
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
@ -791,9 +709,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
// Stylesheets
|
// Stylesheets
|
||||||
|
|
||||||
server->on("/css/style.css", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/css/style.css", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(
|
AsyncWebServerResponse *response = request->beginResponse_P(
|
||||||
200, "text/css", CSS_STYLE_GZIP, sizeof(CSS_STYLE_GZIP));
|
200, "text/css", CSS_STYLE_GZIP, sizeof(CSS_STYLE_GZIP));
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
@ -802,9 +717,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
|
|
||||||
server->on(
|
server->on(
|
||||||
"/css/normalize.css", HTTP_GET, [](AsyncWebServerRequest *request) {
|
"/css/normalize.css", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(
|
AsyncWebServerResponse *response = request->beginResponse_P(
|
||||||
200, "text/css", CSS_NORMALIZE_GZIP, sizeof(CSS_NORMALIZE_GZIP));
|
200, "text/css", CSS_NORMALIZE_GZIP, sizeof(CSS_NORMALIZE_GZIP));
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
@ -813,9 +725,6 @@ void ESPUIClass::begin(const char *_title, const char *username,
|
|||||||
|
|
||||||
// Heap for general Servertest
|
// Heap for general Servertest
|
||||||
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername,
|
|
||||||
ESPUI.basicAuthPassword))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/plain",
|
request->send(200, "text/plain",
|
||||||
String(ESP.getFreeHeap()) + " In Memorymode");
|
String(ESP.getFreeHeap()) + " In Memorymode");
|
||||||
});
|
});
|
||||||
|
11
src/ESPUI.h
11
src/ESPUI.h
@ -2,7 +2,6 @@
|
|||||||
#define ESPUI_h
|
#define ESPUI_h
|
||||||
|
|
||||||
#define DEBUG_ESPUI true
|
#define DEBUG_ESPUI true
|
||||||
#define WS_AUTHENTICATION false
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "ArduinoJson.h"
|
#include "ArduinoJson.h"
|
||||||
@ -41,7 +40,6 @@ typedef struct Control {
|
|||||||
} Control;
|
} Control;
|
||||||
|
|
||||||
// Message Types (and control types)
|
// Message Types (and control types)
|
||||||
#define UI_INITIAL_GUI 100
|
|
||||||
#define UI_TITEL 0
|
#define UI_TITEL 0
|
||||||
|
|
||||||
#define UI_LABEL 1
|
#define UI_LABEL 1
|
||||||
@ -102,12 +100,8 @@ typedef struct Control {
|
|||||||
|
|
||||||
class ESPUIClass {
|
class ESPUIClass {
|
||||||
public:
|
public:
|
||||||
void begin(const char *_title); // Setup servers and page in Memorymode
|
void begin(const char *_title); // Setup servers and page in Memorymode
|
||||||
void begin(const char *_title, const char *username, const char *password);
|
|
||||||
|
|
||||||
void beginSPIFFS(const char *_title); // Setup servers and page in SPIFFSmode
|
void beginSPIFFS(const char *_title); // Setup servers and page in SPIFFSmode
|
||||||
void beginSPIFFS(const char *_title, const char *username,
|
|
||||||
const char *password);
|
|
||||||
|
|
||||||
void prepareFileSystem(); // Initially preps the filesystem and loads a lot
|
void prepareFileSystem(); // Initially preps the filesystem and loads a lot
|
||||||
// of stuff into SPIFFS
|
// of stuff into SPIFFS
|
||||||
@ -165,9 +159,6 @@ class ESPUIClass {
|
|||||||
bool labelExists(String label);
|
bool labelExists(String label);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *basicAuthUsername;
|
|
||||||
const char *basicAuthPassword;
|
|
||||||
bool basicAuth = true;
|
|
||||||
AsyncWebServer *server;
|
AsyncWebServer *server;
|
||||||
AsyncWebSocket *ws;
|
AsyncWebSocket *ws;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,15 +1,42 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from jsmin import jsmin as jsminify
|
### import always available modules
|
||||||
from htmlmin import minify as htmlminify
|
|
||||||
from csscompressor import compress as cssminify
|
|
||||||
import gzip
|
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import argparse
|
import argparse
|
||||||
import re
|
import re
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
|
### import not always installed modules
|
||||||
|
missing = []
|
||||||
|
try:
|
||||||
|
from jsmin import jsmin as jsminify
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
missing.append(e)
|
||||||
|
try:
|
||||||
|
from htmlmin import minify as htmlminify
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
missing.append(e)
|
||||||
|
try:
|
||||||
|
from csscompressor import compress as cssminify
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
missing.append(e)
|
||||||
|
try:
|
||||||
|
import gzip
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
missing.append(e)
|
||||||
|
if len(missing) > 0:
|
||||||
|
# ERROR: at least one module is missing
|
||||||
|
for m in missing:
|
||||||
|
print("Cannot find module '%s'." % m.name)
|
||||||
|
print("Can't find %s required python module%s. Please install %s. If you're not sure how, a web search" % (len(missing), "s" if len(missing) > 1 else "", "them" if len(missing) > 1 else "it"))
|
||||||
|
print("for 'python', your operating system/python distribution and 'install modules' should help.")
|
||||||
|
print("For most people on unix-y systems, this line should work (possibly w/o the '3'):\n pip3 install %s" % " ".join(m.name for m in missing))
|
||||||
|
print("Here's the long documentation: https://packaging.python.org/tutorials/installing-packages/")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
### String template for C header files
|
||||||
TARGET_TEMPLATE = '''const char {constant}[] PROGMEM = R"=====(
|
TARGET_TEMPLATE = '''const char {constant}[] PROGMEM = R"=====(
|
||||||
{minidata}
|
{minidata}
|
||||||
)=====";
|
)=====";
|
||||||
@ -17,7 +44,9 @@ TARGET_TEMPLATE = '''const char {constant}[] PROGMEM = R"=====(
|
|||||||
const uint8_t {constant}_GZIP[{gziplen}] PROGMEM = {{ {gzipdata} }};
|
const uint8_t {constant}_GZIP[{gziplen}] PROGMEM = {{ {gzipdata} }};
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments(args=None):
|
def parse_arguments(args=None):
|
||||||
|
""" Command line argument parser definitions """
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Prepares ESPUI header files by minifying and gzipping HTML, JS and CSS source files.")
|
description="Prepares ESPUI header files by minifying and gzipping HTML, JS and CSS source files.")
|
||||||
parser.add_argument("--auto", "--all", "-a", dest="auto", action="store_true",
|
parser.add_argument("--auto", "--all", "-a", dest="auto", action="store_true",
|
||||||
@ -36,6 +65,20 @@ def parse_arguments(args=None):
|
|||||||
return args
|
return args
|
||||||
|
|
||||||
def get_context(infile, outfile):
|
def get_context(infile, outfile):
|
||||||
|
""" This function creates a 'context object': a dictionary containing all the data needed.
|
||||||
|
Dictionary members:
|
||||||
|
infile: Full path to the input file or directory as given or autodetected
|
||||||
|
indir: Full path to the infile parent.
|
||||||
|
dir: Full path to the input directory tree (indir or parent of indir).
|
||||||
|
name: Filename of infile excluding extension (i.e. filename up until the first dot)
|
||||||
|
type: Lowercase extension of infile; one of: html, js, css.
|
||||||
|
outfile: Full path to the output file or directory as given or autodetected.
|
||||||
|
outdir: Full path to output directory.
|
||||||
|
outfilename: Filename of outfile.
|
||||||
|
minifile: Full path and filename of the intermediary minified file.
|
||||||
|
constant: C header file constant name derived from infile.
|
||||||
|
If infile == minifile, the input file already is minified (contains ".min.")
|
||||||
|
"""
|
||||||
infile = os.path.realpath(infile)
|
infile = os.path.realpath(infile)
|
||||||
dir, name, type = (os.path.basename(os.path.dirname(infile)), os.path.basename(infile).split(os.path.extsep)[0], os.path.basename(infile).split(os.path.extsep)[-1] )
|
dir, name, type = (os.path.basename(os.path.dirname(infile)), os.path.basename(infile).split(os.path.extsep)[0], os.path.basename(infile).split(os.path.extsep)[-1] )
|
||||||
type = type.strip(".").lower()
|
type = type.strip(".").lower()
|
||||||
@ -58,6 +101,11 @@ def get_context(infile, outfile):
|
|||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
def perform_gzip(c):
|
def perform_gzip(c):
|
||||||
|
""" Performs GZIP on c['minidata'].
|
||||||
|
The returned context object will contain additional fields:
|
||||||
|
gzipdata: Comma-separated string of decimal byte values representing gzipped data.
|
||||||
|
gziplen: Count of decimal byte values in gzipdata.
|
||||||
|
"""
|
||||||
compressed = gzip.compress(bytes(c['minidata'], 'utf-8'))
|
compressed = gzip.compress(bytes(c['minidata'], 'utf-8'))
|
||||||
c['gzipdata'] = ','.join([ str(b) for b in compressed ])
|
c['gzipdata'] = ','.join([ str(b) for b in compressed ])
|
||||||
c['gziplen'] = len(compressed)
|
c['gziplen'] = len(compressed)
|
||||||
@ -65,6 +113,9 @@ def perform_gzip(c):
|
|||||||
return c
|
return c
|
||||||
|
|
||||||
def perform_minify(c):
|
def perform_minify(c):
|
||||||
|
""" Performs minification on c['infile'].
|
||||||
|
The returned context object contains the additional field minidata: A string of minified file contents.
|
||||||
|
"""
|
||||||
with open(c['infile']) as infile:
|
with open(c['infile']) as infile:
|
||||||
minifier = {
|
minifier = {
|
||||||
'css': cssminify,
|
'css': cssminify,
|
||||||
@ -73,19 +124,27 @@ def perform_minify(c):
|
|||||||
}.get(c['type']) or htmlminify
|
}.get(c['type']) or htmlminify
|
||||||
print(" Using %s minifier" % c['type'])
|
print(" Using %s minifier" % c['type'])
|
||||||
c['minidata'] = minifier(infile.read())
|
c['minidata'] = minifier(infile.read())
|
||||||
return perform_gzip(c)
|
return c
|
||||||
|
|
||||||
def process_file(infile, outdir, storemini=True):
|
def process_file(infile, outdir, storemini=True):
|
||||||
|
""" Processes one file """
|
||||||
print("Processing file %s" % infile)
|
print("Processing file %s" % infile)
|
||||||
|
# Evaluate file and target context
|
||||||
c = get_context(infile, outdir)
|
c = get_context(infile, outdir)
|
||||||
|
# Minify file data
|
||||||
c = perform_minify(c)
|
c = perform_minify(c)
|
||||||
|
# Gzip minified data
|
||||||
|
c = perform_gzip(c)
|
||||||
|
|
||||||
if storemini:
|
if storemini:
|
||||||
|
# Write intermediary minified file
|
||||||
if c['infile'] == c['minifile']:
|
if c['infile'] == c['minifile']:
|
||||||
print(" Original file is already minified, refusing to overwrite it")
|
print(" Original file is already minified, refusing to overwrite it")
|
||||||
else:
|
else:
|
||||||
print(" Writing minified file %s" % c['minifile'])
|
print(" Writing minified file %s" % c['minifile'])
|
||||||
with open(c['minifile'], 'w+') as minifile:
|
with open(c['minifile'], 'w+') as minifile:
|
||||||
minifile.write(c['minidata'])
|
minifile.write(c['minidata'])
|
||||||
|
# Write minified and gzipped data to C header file
|
||||||
with open(c['outfile'], 'w+') as outfile:
|
with open(c['outfile'], 'w+') as outfile:
|
||||||
print(" Using C constant names %s and %s_GZIP" % (c['constant'], c['constant']))
|
print(" Using C constant names %s and %s_GZIP" % (c['constant'], c['constant']))
|
||||||
print(" Writing C header file %s" % c['outfile'])
|
print(" Writing C header file %s" % c['outfile'])
|
||||||
@ -95,6 +154,10 @@ def filenamefilter(pattern, strings):
|
|||||||
return filter(re.compile(pattern).search, strings)
|
return filter(re.compile(pattern).search, strings)
|
||||||
|
|
||||||
def process_dir(sourcedir, outdir, recursive=True, storemini=True):
|
def process_dir(sourcedir, outdir, recursive=True, storemini=True):
|
||||||
|
""" Processes a directory tree, recursively. Calls process_file on each HTML/CSS/JS file found.
|
||||||
|
Skips intermediary minified files. Standalone minified files (i.e. files containing ".min." that
|
||||||
|
do not have a full version) are processed without minifying again.
|
||||||
|
"""
|
||||||
pattern = r'/*\.(css|js|htm|html)$'
|
pattern = r'/*\.(css|js|htm|html)$'
|
||||||
files = glob(sourcedir + "/**/*", recursive=True)+glob(sourcedir + "/*") if recursive else glob(sourcedir + "/*")
|
files = glob(sourcedir + "/**/*", recursive=True)+glob(sourcedir + "/*") if recursive else glob(sourcedir + "/*")
|
||||||
files = filenamefilter(pattern, files)
|
files = filenamefilter(pattern, files)
|
||||||
@ -105,6 +168,7 @@ def process_dir(sourcedir, outdir, recursive=True, storemini=True):
|
|||||||
process_file(f, outdir, storemini)
|
process_file(f, outdir, storemini)
|
||||||
|
|
||||||
def check_args(args):
|
def check_args(args):
|
||||||
|
""" Checks argumental sanity and exits if the arguments are insane. """
|
||||||
abort = 0
|
abort = 0
|
||||||
if not os.path.exists(args.sources):
|
if not os.path.exists(args.sources):
|
||||||
print("ERROR: Source %s does not exist" % args.sources)
|
print("ERROR: Source %s does not exist" % args.sources)
|
||||||
@ -120,8 +184,12 @@ def check_args(args):
|
|||||||
sys.exit(abort)
|
sys.exit(abort)
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
|
""" main entry point. """
|
||||||
|
# default source if not given: realpath(../examples/gui/data)
|
||||||
args.sources = os.path.realpath(args.sources or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "examples", "gui", "data")))
|
args.sources = os.path.realpath(args.sources or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "examples", "gui", "data")))
|
||||||
|
# default target if not given: realpath(../src)
|
||||||
args.target = os.path.realpath(args.target or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "src")))
|
args.target = os.path.realpath(args.target or os.sep.join((os.path.dirname(os.path.realpath(__file__)), "..", "src")))
|
||||||
|
# check arguments
|
||||||
check_args(args)
|
check_args(args)
|
||||||
if os.path.isfile(args.sources):
|
if os.path.isfile(args.sources):
|
||||||
print("Source %s is a file, will process one file only." % args.sources)
|
print("Source %s is a file, will process one file only." % args.sources)
|
||||||
|
Reference in New Issue
Block a user