diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index d4104b2e..64838bd1 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -31,11 +31,11 @@ jobs:
- out: dustinwatts
env: "freetouchdeck_4MB -e freetouchdeck_8MB -e esp32-touchdown"
- out: elecrow
- env: "esp32-terminal-rgb_16MB -e esp32-terminal-spi_16MB -e elecrow-s3-8048c070_4MB"
+ env: "esp32-terminal-rgb_16MB -e esp32-terminal-spi_16MB -e elecrow-s3-8048c050_4MB -e elecrow-s3-8048c070_4MB"
- out: globalsecurity
env: gs-t3e_16MB
- out: guition
- env: esp32-s3-4848s040_16MB
+ env: esp32-s3-4848s040_16MB -e guition-jc4827w543c_4MB
- out: lanbon
env: lanbon_l8
- out: lilygo-ttgo
diff --git a/data/edit.htm b/data/edit.htm
index 4143e51c..c0a35dc2 100644
--- a/data/edit.htm
+++ b/data/edit.htm
@@ -1 +1 @@
-
openHASP File Editor- New File
- Upload Files
- Edit
- Preview
- Download
- Delete
\ No newline at end of file
+openHASP File Editor- New File
- Upload Files
- Edit
- Preview
- Download
- Delete
\ No newline at end of file
diff --git a/data/es_ES.json b/data/es_ES.json
index fa1292a2..7df5c933 100644
--- a/data/es_ES.json
+++ b/data/es_ES.json
@@ -86,13 +86,13 @@
"ssid": "SSID"
},
"wg": {
- "title": "WireGuard Settings",
- "btn": "WireGuard Settings",
- "vpnip": "VPN IP",
- "privkey": "Private Key",
- "host": "Remote IP",
- "port": "Remote Port",
- "pubkey": "Remote Public Key"
+ "title": "Ajustes de WireGuard",
+ "btn": "Ajustes de WireGuard",
+ "vpnip": "IP VPN",
+ "privkey": "Clave Privada",
+ "host": "IP Remota",
+ "port": "Puerto Remoto",
+ "pubkey": "Clave Pública Remota"
},
"mqtt": {
"title": "Ajustes MQTT",
diff --git a/data/fr_FR.json b/data/fr_FR.json
index 7247c2f6..aacaead0 100644
--- a/data/fr_FR.json
+++ b/data/fr_FR.json
@@ -86,13 +86,13 @@
"ssid": "SSID"
},
"wg": {
- "title": "WireGuard Settings",
- "btn": "WireGuard Settings",
- "vpnip": "VPN IP",
- "privkey": "Private Key",
- "host": "Remote IP",
- "port": "Remote Port",
- "pubkey": "Remote Public Key"
+ "title": "Paramètres WireGuard",
+ "btn": "Paramètres WireGuard",
+ "vpnip": "IP du VPN",
+ "privkey": "Clé Privée",
+ "host": "Adresse IP distante",
+ "port": "Port Distant",
+ "pubkey": "Clé publique distante"
},
"mqtt": {
"title": "Paramètres MQTT",
diff --git a/data/script.js b/data/script.js
index 5e9dc496..afd735c2 100644
--- a/data/script.js
+++ b/data/script.js
@@ -1 +1 @@
-var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.8")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='
',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`\n ${e}\n
`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))}));
\ No newline at end of file
+var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.4")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='
',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`\n ${e}\n
`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))}));
\ No newline at end of file
diff --git a/include/lv_conf_v7.h b/include/lv_conf_v7.h
index 764be7bd..606203cc 100644
--- a/include/lv_conf_v7.h
+++ b/include/lv_conf_v7.h
@@ -211,7 +211,7 @@ typedef void* lv_group_user_data_t;
#define LV_USE_FILESYSTEM 1
#if LV_USE_FILESYSTEM
/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/
-typedef void* lv_fs_drv_user_data_t;
+typedef const char* lv_fs_drv_user_data_t;
/*File system interface*/
#ifndef LV_USE_FS_IF
@@ -229,7 +229,7 @@ typedef void* lv_fs_drv_user_data_t;
//# define LV_FS_IF_SPIFFS '\0' // no internal esp Flash
#endif
#endif /*LV_USE_FS_IF*/
-#if HASP_TARGET_ARDUINO
+#if HASP_TARGET_ARDUINO && !defined(LV_FS_PC_PATH)
#define LV_FS_PC_PATH "/littlefs"
#endif
diff --git a/lib/lv_fs_if/lv_fs_if.c b/lib/lv_fs_if/lv_fs_if.c
index 472edcf2..45c94def 100644
--- a/lib/lv_fs_if/lv_fs_if.c
+++ b/lib/lv_fs_if/lv_fs_if.c
@@ -14,6 +14,13 @@
/*********************
* DEFINES
*********************/
+#ifndef LV_FS_PC_PATH
+#ifndef WIN32
+#define LV_FS_PC_PATH "./" /*Project root*/
+#else
+#define LV_FS_PC_PATH ".\\" /*Project root*/
+#endif
+#endif /*LV_FS_PATH*/
/**********************
* TYPEDEFS
@@ -26,8 +33,8 @@
void lv_fs_if_fatfs_init(void);
#endif
-#if LV_FS_IF_PC != '\0'
-void lv_fs_if_pc_init(void);
+#if LV_FS_IF_PC != '\0' || LV_FS_IF_SD != '\0'
+void lv_fs_if_pc_init(char letter, const char* path);
#endif
/**********************
@@ -48,13 +55,16 @@ void lv_fs_if_pc_init(void);
void lv_fs_if_init(void)
{
#if LV_FS_IF_FATFS != '\0'
- lv_fs_if_fatfs_init();
+ lv_fs_if_fatfs_init();
#endif
#if LV_FS_IF_PC != '\0'
- lv_fs_if_pc_init();
+ lv_fs_if_pc_init(LV_FS_IF_PC, LV_FS_PC_PATH);
#endif
+#if LV_FS_IF_SD != '\0'
+ lv_fs_if_pc_init(LV_FS_IF_SD, LV_FS_SD_PATH);
+#endif
}
/**********************
diff --git a/lib/lv_fs_if/lv_fs_pc.c b/lib/lv_fs_if/lv_fs_pc.c
index 02aa1a41..cca7afbd 100644
--- a/lib/lv_fs_if/lv_fs_pc.c
+++ b/lib/lv_fs_if/lv_fs_pc.c
@@ -19,17 +19,6 @@
#include
#endif
-/*********************
- * DEFINES
- *********************/
-#ifndef LV_FS_PC_PATH
-#ifndef WIN32
-#define LV_FS_PC_PATH "./" /*Projet root*/
-#else
-#define LV_FS_PC_PATH ".\\" /*Projet root*/
-#endif
-#endif /*LV_FS_PATH*/
-
/**********************
* TYPEDEFS
**********************/
@@ -77,7 +66,7 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t* drv, void* dir_p);
/**
* Register a driver for the File system interface
*/
-void lv_fs_if_pc_init(void)
+void lv_fs_if_pc_init(char letter, const char* path)
{
/*---------------------------------------------------
* Register the file system interface in LittlevGL
@@ -89,7 +78,7 @@ void lv_fs_if_pc_init(void)
/*Set up fields...*/
fs_drv.file_size = sizeof(file_t);
- fs_drv.letter = LV_FS_IF_PC;
+ fs_drv.letter = letter;
fs_drv.open_cb = fs_open;
fs_drv.close_cb = fs_close;
fs_drv.read_cb = fs_read;
@@ -107,6 +96,8 @@ void lv_fs_if_pc_init(void)
fs_drv.dir_open_cb = fs_dir_open;
fs_drv.dir_read_cb = fs_dir_read;
+ fs_drv.user_data = path;
+
lv_fs_drv_register(&fs_drv);
// char cur_path[512] = "";
@@ -145,10 +136,10 @@ static lv_fs_res_t fs_open(lv_fs_drv_t* drv, void* file_p, const char* path, lv_
#ifndef WIN32
char buf[256];
- sprintf(buf, LV_FS_PC_PATH "/%s", path);
+ sprintf(buf, "%s/%s", drv->user_data, path);
#else
char buf[256];
- sprintf(buf, LV_FS_PC_PATH "\\%s", path);
+ sprintf(buf, "%s\\%s", drv->user_data, path);
#endif
LV_LOG_USER(buf);
@@ -255,6 +246,7 @@ static lv_fs_res_t fs_size(lv_fs_drv_t* drv, void* file_p, uint32_t* size_p)
return LV_FS_RES_OK;
}
+
/**
* Give the position of the read write pointer
* @param drv pointer to a driver where this function belongs
@@ -318,8 +310,8 @@ static lv_fs_res_t fs_rename(lv_fs_drv_t* drv, const char* oldname, const char*
static char new[512];
static char old[512];
- sprintf(old, LV_FS_PC_PATH "/%s", oldname);
- sprintf(new, LV_FS_PC_PATH "/%s", newname);
+ sprintf(old, "%s/%s", drv->user_data, oldname);
+ sprintf(new, "%s/%s", drv->user_data, newname);
int r = rename(old, new);
@@ -365,7 +357,7 @@ static lv_fs_res_t fs_dir_open(lv_fs_drv_t* drv, void* dir_p, const char* path)
#ifndef WIN32
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
- sprintf(buf, LV_FS_PC_PATH "/%s", path);
+ sprintf(buf, "%s/%s", drv->user_data, path);
if((d = opendir(buf)) == NULL) {
return LV_FS_RES_FS_ERR;
} else {
@@ -380,7 +372,7 @@ static lv_fs_res_t fs_dir_open(lv_fs_drv_t* drv, void* dir_p, const char* path)
/*Make the path relative to the current directory (the projects root folder)*/
char buf[256];
- sprintf(buf, LV_FS_PC_PATH "\\%s\\*", path);
+ sprintf(buf, "%s\\%s\\*", drv->user_data, path);
strcpy(next_fn, "");
d = FindFirstFile(buf, &fdata);
diff --git a/platformio.ini b/platformio.ini
index 444439fc..a003dc93 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -112,7 +112,7 @@ lib_deps =
[arduinogfx]
lib_deps =
- moononournation/GFX Library for Arduino@1.4.0 ; Update needs modification of custom PCA class
+ moononournation/GFX Library for Arduino@1.4.7 ; Update needs modification of custom PCA class
;git+https://github.com/moononournation/Arduino_GFX.git
[tft_espi]
diff --git a/platformio_override-template.ini b/platformio_override-template.ini
index 69a865c2..c3791ae8 100644
--- a/platformio_override-template.ini
+++ b/platformio_override-template.ini
@@ -78,6 +78,7 @@ extra_default_envs =
; wt-86-32-3zw1
; yeacreate-nscreen32
; wz2432r028
+ ; ws_esp32_s3_touch_lcd_4p3
;endregion
;region -- Define your local COM ports for each environment ---
diff --git a/src/custom/my_custom_fan_template.cpp b/src/custom/my_custom_fan_template.cpp
index b7bed86d..a8775242 100644
--- a/src/custom/my_custom_fan_template.cpp
+++ b/src/custom/my_custom_fan_template.cpp
@@ -98,4 +98,8 @@ void custom_topic_payload(const char* topic, const char* payload, uint8_t source
// LOG_VERBOSE(TAG_CUSTOM, "Handled custom message: %s => %s", topic, payload);
}
+void custom_state_subtopic(const char* subtopic, const char* payload){
+ // Not used
+}
+
#endif // HASP_USE_CUSTOM
diff --git a/src/custom/my_custom_template.cpp b/src/custom/my_custom_template.cpp
index b41da916..358bbd0f 100644
--- a/src/custom/my_custom_template.cpp
+++ b/src/custom/my_custom_template.cpp
@@ -53,4 +53,9 @@ void custom_topic_payload(const char* topic, const char* payload, uint8_t source
// Not used
}
+void custom_state_subtopic(const char* subtopic, const char* payload){
+ // Not used
+}
+
+
#endif // HASP_USE_CUSTOM
\ No newline at end of file
diff --git a/src/custom/my_custom_template.h b/src/custom/my_custom_template.h
index 111df88f..3e25c031 100644
--- a/src/custom/my_custom_template.h
+++ b/src/custom/my_custom_template.h
@@ -32,6 +32,11 @@ void custom_get_sensors(JsonDocument& doc);
/* Receive custom topic & payload messages */
void custom_topic_payload(const char* topic, const char* payload, uint8_t source);
+/* Get notified when a state message is sent out */
+/* Can be used to send state changes through other means then MQTT, e.g. Serial2 */
+/* https://github.com/HASwitchPlate/openHASP/issues/611 */
+void custom_state_subtopic(const char* subtopic, const char* payload);
+
#endif // HASP_USE_CUSTOM
#endif // HASP_CUSTOM_H
diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp
index c946120a..ae73d504 100644
--- a/src/drv/tft/tft_driver_arduinogfx.cpp
+++ b/src/drv/tft/tft_driver_arduinogfx.cpp
@@ -85,6 +85,10 @@ void ArduinoGfx::init(int w, int h)
/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
tft = new Arduino_RGB_Display(w, h, rgbpanel, 0 /* rotation */, TFT_AUTO_FLUSH, bus, TFT_RST,
st7701_type1_init_operations, sizeof(st7701_type1_init_operations));
+#elif(TFT_WIDTH == 480) && (TFT_HEIGHT == 272) && defined(NV3041A_DRIVER)
+ Arduino_DataBus* bus = new Arduino_ESP32QSPI(TFT_CS, TFT_SCK, TFT_D0, TFT_D1, TFT_D2, TFT_D3);
+ Arduino_GFX* g = new Arduino_NV3041A(bus, TFT_RST, TFT_ROTATION, TFT_IPS);
+ tft = g;
#elif 1
/* Reset is not implemented in the panel */
if(TFT_RST != GFX_NOT_DEFINED) {
@@ -262,6 +266,116 @@ void IRAM_ATTR ArduinoGfx::flush_pixels(lv_disp_drv_t* disp, const lv_area_t* ar
bool ArduinoGfx::is_driver_pin(uint8_t pin)
{
+ if(false // start condition is always needed
+
+// Use individual checks instead of switch statement, as some case labels could be duplicated
+#ifdef TFT_MOSI
+ || (pin == TFT_MOSI)
+#endif
+#ifdef TFT_MISO
+ || (pin == TFT_MISO)
+#endif
+#ifdef TFT_SCLK
+ || (pin == TFT_SCLK)
+#endif
+#ifdef TFT_CS
+ || (pin == TFT_CS)
+#endif
+#ifdef TFT_DC
+ || (pin == TFT_DC)
+#endif
+#ifdef TFT_DE
+ || (pin == TFT_DE)
+#endif
+#ifdef TFT_PCLK
+ || (pin == TFT_PCLK)
+#endif
+#ifdef TFT_VSYNC
+ || (pin == TFT_VSYNC)
+#endif
+#ifdef TFT_HSYNC
+ || (pin == TFT_HSYNC)
+#endif
+#ifdef TFT_RST
+ || (pin == TFT_RST)
+#endif
+#ifdef TFT_BUSY
+ || (pin == TFT_BUSY)
+#endif
+#ifdef TFT_RD
+ || (pin == TFT_RD)
+#endif
+#ifdef TFT_R0
+ || (pin == TFT_R0)
+#endif
+#ifdef TFT_R1
+ || (pin == TFT_R1)
+#endif
+#ifdef TFT_R2
+ || (pin == TFT_R2)
+#endif
+#ifdef TFT_R3
+ || (pin == TFT_R3)
+#endif
+#ifdef TFT_R4
+ || (pin == TFT_R4)
+#endif
+#ifdef TFT_G0
+ || (pin == TFT_G0)
+#endif
+#ifdef TFT_G1
+ || (pin == TFT_G1)
+#endif
+#ifdef TFT_G2
+ || (pin == TFT_G2)
+#endif
+#ifdef TFT_G3
+ || (pin == TFT_G3)
+#endif
+#ifdef TFT_G4
+ || (pin == TFT_G4)
+#endif
+#ifdef TFT_G5
+ || (pin == TFT_G5)
+#endif
+#ifdef TFT_B0
+ || (pin == TFT_B0)
+#endif
+#ifdef TFT_B1
+ || (pin == TFT_B1)
+#endif
+#ifdef TFT_B2
+ || (pin == TFT_B2)
+#endif
+#ifdef TFT_B3
+ || (pin == TFT_B3)
+#endif
+#ifdef TFT_B4
+ || (pin == TFT_B4)
+#endif
+#ifdef TOUCH_SDA
+ || (pin == TOUCH_SDA)
+#endif
+#ifdef TOUCH_SCL
+ || (pin == TOUCH_SCL)
+#endif
+#ifdef TOUCH_RST
+ || (pin == TOUCH_RST)
+#endif
+#ifdef TOUCH_IRQ
+ || (pin == TOUCH_IRQ)
+#endif
+ ) {
+ return true;
+ }
+
+#ifdef ARDUINO_ARCH_ESP8266
+#ifndef TFT_SPI_OVERLAP
+ if((pin >= 12) && (pin <= 14)) return true; // HSPI
+#endif
+#endif
+
+ return false;
return false;
}
@@ -299,6 +413,8 @@ const char* ArduinoGfx::get_tft_model()
return "R61529";
#elif defined(RM68140_DRIVER)
return "RM68140";
+#elif defined(NV3041A_DRIVER)
+ return "NV3041A";
#else
return "Other";
#endif
@@ -336,6 +452,8 @@ uint32_t ArduinoGfx::get_tft_driver()
return 0x61529;
#elif defined(RM68140_DRIVER)
return 0x68140;
+#elif defined(NV3041A_DRIVER)
+ return 0x3041A;
#else
return 0x0;
#endif
diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp
index a3fd9f29..b8b42eca 100644
--- a/src/hasp/hasp_attribute.cpp
+++ b/src/hasp/hasp_attribute.cpp
@@ -98,7 +98,7 @@ const char** my_map_create(const char* payload)
{
// Reserve memory for JsonDocument
// StaticJsonDocument<1024> map_doc;
- size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 256;
+ size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 1024;
DynamicJsonDocument map_doc(maxsize);
DeserializationError jsonError = deserializeJson(map_doc, payload);
diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp
index 03b0da9d..33cffc77 100644
--- a/src/hasp/hasp_dispatch.cpp
+++ b/src/hasp/hasp_dispatch.cpp
@@ -43,7 +43,7 @@ uint16_t dispatchSecondsToNextTeleperiod = 0;
uint16_t dispatchSecondsToNextSensordata = 0;
uint16_t dispatchSecondsToNextDiscovery = 0;
uint8_t nCommands = 0;
-haspCommand_t commands[28];
+haspCommand_t commands[29];
moodlight_t moodlight = {.brightness = 255};
uint8_t saved_jsonl_page = 0;
@@ -52,7 +52,7 @@ uint8_t saved_jsonl_page = 0;
*/
void dispatch_state_subtopic(const char* subtopic, const char* payload)
{
-#if HASP_USE_MQTT == 0 && HASP_USE_TASMOTA_CLIENT == 0
+#if HASP_USE_MQTT == 0 && defined(HASP_USE_TASMOTA_CLIENT) && HASP_USE_TASMOTA_CLIENT > 0
LOG_TRACE(TAG_MSGR, F("%s => %s"), subtopic, payload);
#else
@@ -74,11 +74,15 @@ void dispatch_state_subtopic(const char* subtopic, const char* payload)
}
#endif
-#if HASP_USE_TASMOTA_CLIENT > 0
+#if defined(HASP_USE_TASMOTA_CLIENT) && HASP_USE_TASMOTA_CLIENT > 0
slave_send_state(subtopic, payload);
#endif
#endif
+
+#if defined(HASP_USE_CUSTOM) && HASP_USE_CUSTOM > 0
+ custom_state_subtopic(subtopic, payload);
+#endif
}
void dispatch_state_eventid(const char* topic, hasp_event_t eventid)
@@ -864,6 +868,46 @@ void dispatch_run_script(const char*, const char* payload, uint8_t source)
#endif
}
+/*
+void dispatch_fs(const char*, const char* payload, uint8_t source)
+{
+ StaticJsonDocument<512> json;
+
+ // Note: Deserialization needs to be (const char *) so the objects WILL be copied
+ // this uses more memory but otherwise the mqtt receive buffer can get overwritten by the send buffer !!
+ DeserializationError jsonError = deserializeJson(json, payload);
+ // json.shrinkToFit();
+
+ if(!jsonError && json.is()) { // Only JsonObject is valid
+ JsonVariant action;
+
+ const char* cmd = json["cmd"].as();
+ const char* src = json["src"].as();
+ const char* dst = json["dst"].as();
+ int res = 0;
+
+ if(String(cmd) == "stat") {
+ res = filesystem_vfs_file_exists(src);
+ }
+ if(String(cmd) == "rm") {
+ res = filesystem_vfs_delete_file(src);
+ }
+ if(String(cmd) == "cp") {
+ res = filesystem_vfs_copy_file(src, dst);
+ }
+ if(String(cmd) == "ls") {
+ filesystem_list_path(src);
+ }
+
+ if(res) {
+ LOG_WARNING(TAG_MSGR, "Succes");
+ } else {
+ LOG_WARNING(TAG_MSGR, "Failed");
+ }
+ }
+}
+*/
+
#if HASP_TARGET_PC
static void shell_command_thread(char* cmdline)
{
@@ -1318,9 +1362,10 @@ void dispatch_get_discovery_data(JsonDocument& doc)
JsonArray relay = doc.createNestedArray(F("power"));
JsonArray led = doc.createNestedArray(F("light"));
JsonArray dimmer = doc.createNestedArray(F("dim"));
+ JsonArray event = doc.createNestedArray(F("event"));
#if HASP_USE_GPIO > 0
- gpio_discovery(input, relay, led, dimmer);
+ gpio_discovery(input, relay, led, dimmer, event);
#endif
}
@@ -1592,6 +1637,7 @@ void dispatchSetup()
dispatch_add_command(PSTR("sensors"), dispatch_send_sensordata);
dispatch_add_command(PSTR("theme"), dispatch_theme);
dispatch_add_command(PSTR("run"), dispatch_run_script);
+ // dispatch_add_command(PSTR("fs"), dispatch_fs);
#if HASP_TARGET_PC
dispatch_add_command(PSTR("shell"), dispatch_shell_execute);
#endif
diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp
index a44a9741..bb29307d 100644
--- a/src/hasp/hasp_parser.cpp
+++ b/src/hasp/hasp_parser.cpp
@@ -197,23 +197,26 @@ bool Parser::is_only_digits(const char* s)
return strlen(s) == digits;
}
-int Parser::format_bytes(size_t filesize, char* buf, size_t len)
+int Parser::format_bytes(uint64_t filesize, char* buf, size_t len)
{
- if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%d " D_FILE_SIZE_BYTES), filesize);
- filesize = filesize * 100;
+ const char* suffix[] = {D_FILE_SIZE_BYTES, D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES,
+ D_FILE_SIZE_TERABYTES};
+ uint32_t factor;
+ uint16_t remainder = 0;
+ uint8_t i = 0;
+ uint8_t last_index = (sizeof(suffix) / sizeof(suffix[0])) - 1;
- filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place
- if(filesize < D_FILE_SIZE_DIVIDER * 100)
- return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_KILOBYTES), filesize / 100,
- filesize % 100);
+ while(filesize >= D_FILE_SIZE_DIVIDER && i < last_index) {
+ i += 1;
+ remainder = filesize % D_FILE_SIZE_DIVIDER;
+ filesize /= D_FILE_SIZE_DIVIDER;
+ }
- filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place
- if(filesize < D_FILE_SIZE_DIVIDER * 100)
- return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_MEGABYTES), filesize / 100,
- filesize % 100);
+ factor = (uint32_t)filesize;
+ if(i == 0) return snprintf_P(buf, len, PSTR("%u %s"), factor, suffix[i]);
- return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_GIGABYTES), filesize / 100,
- filesize % 100);
+ remainder = remainder * 100 / D_FILE_SIZE_DIVIDER;
+ return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u %s"), factor, remainder, suffix[i]);
}
uint8_t Parser::get_action_id(const char* action)
diff --git a/src/hasp/hasp_parser.h b/src/hasp/hasp_parser.h
index d1c44bea..84dcfd1b 100644
--- a/src/hasp/hasp_parser.h
+++ b/src/hasp/hasp_parser.h
@@ -19,7 +19,7 @@ class Parser {
static bool is_true(const char* s);
static bool is_true(JsonVariant json);
static bool is_only_digits(const char* s);
- static int format_bytes(size_t filesize, char* buf, size_t len);
+ static int format_bytes(uint64_t filesize, char* buf, size_t len);
};
#ifndef ARDUINO
diff --git a/src/hasp/hasp_task.cpp b/src/hasp/hasp_task.cpp
index a6d01900..272285d7 100644
--- a/src/hasp/hasp_task.cpp
+++ b/src/hasp/hasp_task.cpp
@@ -24,6 +24,10 @@ void task_every_second_cb(lv_task_t* task)
{
haspEverySecond(); // sleep timer & statusupdate
+#if HASP_MQTT_TELNET > 0
+ mqttEverySecond();
+#endif
+
#if HASP_USE_TELNET > 0
telnetEverySecond();
#endif
diff --git a/src/hasp_filesystem.cpp b/src/hasp_filesystem.cpp
index ac39a344..1f9f4953 100644
--- a/src/hasp_filesystem.cpp
+++ b/src/hasp_filesystem.cpp
@@ -180,7 +180,7 @@ void filesystemList()
#else
if(!HASP_FS.begin(true)) { // default vfs path: /littlefs
#endif
- LOG_ERROR(TAG_FILE, F("Flash file system not mouted."));
+ LOG_ERROR(TAG_FILE, F("Flash file system not mounted."));
} else {
LOG_VERBOSE(TAG_FILE, F("Listing files on the internal flash:"));
diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp
index 13caf317..ebb7870a 100644
--- a/src/hasp_gui.cpp
+++ b/src/hasp_gui.cpp
@@ -341,7 +341,7 @@ void guiSetup()
#endif
gui_hide_pointer(false);
if(mouse_indev != NULL) {
- lv_indev_set_cursor(mouse_indev, cursor); /*Connect the image object to the driver*/
+ lv_indev_set_cursor(mouse_indev, cursor); /*Connect the image object to the driver*/
}
#if HASP_TARGET_ARDUINO
diff --git a/src/lang/da_DK.h b/src/lang/da_DK.h
index 13df8dbc..0ec1b257 100644
--- a/src/lang/da_DK.h
+++ b/src/lang/da_DK.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/lang/de_DE.h b/src/lang/de_DE.h
index efd70477..aa83e7b5 100644
--- a/src/lang/de_DE.h
+++ b/src/lang/de_DE.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "," // decimal comma or point
diff --git a/src/lang/en_US.h b/src/lang/en_US.h
index 13df8dbc..0ec1b257 100644
--- a/src/lang/en_US.h
+++ b/src/lang/en_US.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/lang/es_ES.h b/src/lang/es_ES.h
index 613e47ba..acee2059 100644
--- a/src/lang/es_ES.h
+++ b/src/lang/es_ES.h
@@ -13,7 +13,7 @@
#define D_NO "No" // New
#define D_ERROR_OUT_OF_MEMORY "Memory llena"
-#define D_ERROR_UNKNOWN "Unknown error"
+#define D_ERROR_UNKNOWN "Error desconocido"
#define D_CONFIG_NOT_CHANGED "No hay cambios en la configuración"
#define D_CONFIG_CHANGED "Configuración cambiada"
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB" // new
#define D_FILE_SIZE_MEGABYTES "MiB" // new
#define D_FILE_SIZE_GIGABYTES "GiB" // new
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // new, kibi or kilo bytes
#define D_DECIMAL_POINT "," // new, decimal comma or point
@@ -127,7 +128,7 @@
#define D_HTTP_HTTP_SETTINGS "Ajustes HTTP"
#define D_HTTP_HTTP_SETTINGS "Ajustes FTP"
#define D_HTTP_WIFI_SETTINGS "Ajustes Wifi"
-#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings"
+#define D_HTTP_GUI_SETTINGS "Ajustes WireGuard"
#define D_HTTP_MQTT_SETTINGS "Ajustes MQTT"
#define D_HTTP_GPIO_SETTINGS "Ajustes GPIO"
#define D_HTTP_MDNS_SETTINGS "Ajustes mDNS"
@@ -202,8 +203,8 @@
#define D_INFO_MAC_ADDRESS "Dirección MAC"
#define D_INFO_GATEWAY "Gateway"
#define D_INFO_DNS_SERVER "Servidor DNS"
-#define D_INFO_ENDPOINT_IP "Endpoint IP"
-#define D_INFO_ENDPOINT_PORT "Endpoint Port"
+#define D_INFO_ENDPOINT_IP "IP de punto final"
+#define D_INFO_ENDPOINT_PORT "Puerto de punto final"
#define D_OOBE_MSG "Toque la pantalla para ajustar WiFi o conectarse a un punto de acceso"
#define D_OOBE_SCAN_TO_CONNECT "Scanee para conectar"
@@ -216,8 +217,8 @@
#define D_WIFI_RSSI_WEAK "Débil"
#define D_WIFI_RSSI_BAD "Muy baka"
-#define D_WG_INITIALIZED "Initialized"
-#define D_WG_BAD_CONFIG "Missing or bad configuration"
+#define D_WG_INITIALIZED "Inicializado"
+#define D_WG_BAD_CONFIG "Falta o mala configuración"
#define D_GPIO_SWITCH "Switch"
#define D_GPIO_BUTTON "Botón"
diff --git a/src/lang/fr_FR.h b/src/lang/fr_FR.h
index f84d3995..51183b2f 100644
--- a/src/lang/fr_FR.h
+++ b/src/lang/fr_FR.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "Kio"
#define D_FILE_SIZE_MEGABYTES "Mio"
#define D_FILE_SIZE_GIGABYTES "Gio"
+#define D_FILE_SIZE_TERABYTES "Tio"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "," // decimal comma or point
@@ -127,7 +128,7 @@
#define D_HTTP_HTTP_SETTINGS "Paramètres HTTP"
#define D_HTTP_FTP_SETTINGS "Paramètres FTP"
#define D_HTTP_WIFI_SETTINGS "Paramètres Wifi"
-#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings"
+#define D_HTTP_WIREGUARD_SETTINGS "Paramètres WireGuard"
#define D_HTTP_MQTT_SETTINGS "Paramètres MQTT"
#define D_HTTP_GPIO_SETTINGS "Paramètres GPIO"
#define D_HTTP_MDNS_SETTINGS "Paramètres mDNS"
@@ -202,8 +203,8 @@
#define D_INFO_MAC_ADDRESS "Adresse MAC"
#define D_INFO_GATEWAY "Passerelle"
#define D_INFO_DNS_SERVER "Serveur DNS"
-#define D_INFO_ENDPOINT_IP "Endpoint IP"
-#define D_INFO_ENDPOINT_PORT "Endpoint Port"
+#define D_INFO_ENDPOINT_IP "Adresse IP du point final"
+#define D_INFO_ENDPOINT_IP "Port du point final"
#define D_OOBE_MSG "Touchez l'écran pour configurer le WiFi ou branchez ce point d'accès:"
#define D_OOBE_SCAN_TO_CONNECT "Scanner pour se connecter"
@@ -216,8 +217,8 @@
#define D_WIFI_RSSI_WEAK "Faible"
#define D_WIFI_RSSI_BAD "Très mauvais"
-#define D_WG_INITIALIZED "Initialized"
-#define D_WG_BAD_CONFIG "Missing or bad configuration"
+#define D_WG_INITIALIZED "Initialisé"
+#define D_WG_BAD_CONFIG "Configuration manquante ou incorrecte"
#define D_GPIO_SWITCH "Interrupteur"
#define D_GPIO_BUTTON "Bouton"
diff --git a/src/lang/hu_HU.h b/src/lang/hu_HU.h
index 13df8dbc..0ec1b257 100644
--- a/src/lang/hu_HU.h
+++ b/src/lang/hu_HU.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/lang/nl_NL.h b/src/lang/nl_NL.h
index 92e22846..79afa3d1 100644
--- a/src/lang/nl_NL.h
+++ b/src/lang/nl_NL.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "," // decimal comma or point
diff --git a/src/lang/pt_BR.h b/src/lang/pt_BR.h
index 169e3a8d..54121409 100644
--- a/src/lang/pt_BR.h
+++ b/src/lang/pt_BR.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/lang/pt_PT.h b/src/lang/pt_PT.h
index 265b26f0..757a1e2f 100644
--- a/src/lang/pt_PT.h
+++ b/src/lang/pt_PT.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB" // new
#define D_FILE_SIZE_MEGABYTES "MiB" // new
#define D_FILE_SIZE_GIGABYTES "GiB" // new
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // new, kibi or kilo bytes
#define D_DECIMAL_POINT "." // new, decimal comma or point
@@ -127,7 +128,7 @@
#define D_HTTP_HTTP_SETTINGS "Configurar HTTP"
#define D_HTTP_FTP_SETTINGS "Configurar FTP"
#define D_HTTP_WIFI_SETTINGS "Configurar Wifi"
-#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings"
+#define D_HTTP_WIREGUARD_SETTINGS "Configurar WireGuard"
#define D_HTTP_MQTT_SETTINGS "Configurar MQTT"
#define D_HTTP_GPIO_SETTINGS "Configurar GPIO"
#define D_HTTP_MDNS_SETTINGS "Configurar mDNS"
@@ -216,8 +217,8 @@
#define D_WIFI_RSSI_BAD "Muito baixo"
#define D_WIFI_RSSI_FAIR "Decente"
-#define D_WG_INITIALIZED "Initialized"
-#define D_WG_BAD_CONFIG "Missing or bad configuration"
+#define D_WG_INITIALIZED "Inicializado"
+#define D_WG_BAD_CONFIG "Configuração ausente ou ruim"
#define D_GPIO_SWITCH "Interruptor"
#define D_GPIO_BUTTON "Botão"
diff --git a/src/lang/ro_RO.h b/src/lang/ro_RO.h
index 13df8dbc..0ec1b257 100644
--- a/src/lang/ro_RO.h
+++ b/src/lang/ro_RO.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/lang/zh_CN.h b/src/lang/zh_CN.h
index 13df8dbc..0ec1b257 100644
--- a/src/lang/zh_CN.h
+++ b/src/lang/zh_CN.h
@@ -30,6 +30,7 @@
#define D_FILE_SIZE_KILOBYTES "KiB"
#define D_FILE_SIZE_MEGABYTES "MiB"
#define D_FILE_SIZE_GIGABYTES "GiB"
+#define D_FILE_SIZE_TERABYTES "TiB"
#define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes
#define D_DECIMAL_POINT "." // decimal comma or point
diff --git a/src/main.cpp b/src/main.cpp
index b065909c..c68c2bf4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -210,6 +210,10 @@ IRAM_ATTR void loop()
/* Runs Every Second */
haspEverySecond(); // sleep timer & statusupdate
+#if HASP_USE_MQTT > 0
+ mqttEverySecond();
+#endif
+
#if HASP_USE_FTP > 0
ftpEverySecond();
#endif
diff --git a/src/mqtt/hasp_mqtt.h b/src/mqtt/hasp_mqtt.h
index f5d57196..89ced6c1 100644
--- a/src/mqtt/hasp_mqtt.h
+++ b/src/mqtt/hasp_mqtt.h
@@ -18,6 +18,7 @@ typedef enum {
void mqttSetup();
IRAM_ATTR void mqttLoop();
+void mqttEverySecond();
void mqttEvery5Seconds(bool wifiIsConnected);
void mqttStart();
void mqttStop();
diff --git a/src/mqtt/hasp_mqtt_esp.cpp b/src/mqtt/hasp_mqtt_esp.cpp
index 453d3a33..8864c107 100644
--- a/src/mqtt/hasp_mqtt_esp.cpp
+++ b/src/mqtt/hasp_mqtt_esp.cpp
@@ -71,7 +71,7 @@ bool last_mqtt_state = false;
bool current_mqtt_state = false;
uint16_t mqtt_reconnect_counter = 0;
-void mqtt_run_scripts()
+static inline void mqtt_run_scripts()
{
if(last_mqtt_state != current_mqtt_state) {
// mqtt_message_t data;
@@ -104,8 +104,8 @@ void mqtt_run_scripts()
void mqtt_disconnected()
{
current_mqtt_state = false; // now we are disconnected
- // mqtt_run_scripts();
mqtt_reconnect_counter++;
+ // mqtt_run_scripts(); // must happen in LVGL loop
}
void mqtt_connected()
@@ -115,7 +115,7 @@ void mqtt_connected()
current_mqtt_state = true; // now we are connected
LOG_VERBOSE(TAG_MQTT, F("%s"), current_mqtt_state ? PSTR(D_SERVICE_CONNECTED) : PSTR(D_SERVICE_DISCONNECTED));
}
- // mqtt_run_scripts();
+ // mqtt_run_scripts(); // must happen in LVGL loop
}
int mqttPublish(const char* topic, const char* payload, size_t len, bool retain)
@@ -337,7 +337,7 @@ String mqttGetTopic(Preferences preferences, String subtopic, String key, String
}
*/
-void mqttParseTopic(String *topic, String subtopic, bool add_slash)
+void mqttParseTopic(String* topic, String subtopic, bool add_slash)
{
topic->replace(F("%hostname%"), haspDevice.get_hostname());
@@ -509,10 +509,14 @@ IRAM_ATTR void mqttLoop(void)
}
}
-void mqttEvery5Seconds(bool networkIsConnected)
+void mqttEverySecond()
{
mqtt_run_scripts();
- // if(mqttEnabled && networkIsConnected && !mqttClientConnected) {
+}
+
+void mqttEvery5Seconds(bool networkIsConnected)
+{
+ // if(mqttEnabled && networkIsConnected && !current_mqtt_state) {
// LOG_TRACE(TAG_MQTT, F(D_MQTT_RECONNECTING));
// mqttStart();
// }
@@ -535,7 +539,7 @@ void mqttStart()
nvsOldGroup += preferences.getString(FP_CONFIG_GROUP, MQTT_GROUPNAME);
nvsOldGroup += "/%topic%";
- subtopic = F(MQTT_TOPIC_COMMAND);
+ subtopic = F(MQTT_TOPIC_COMMAND);
mqttNodeCommandTopic = preferences.getString(FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC);
mqttParseTopic(&mqttNodeCommandTopic, subtopic, false);
mqttGroupCommandTopic = preferences.getString(FP_CONFIG_GROUP_TOPIC, nvsOldGroup.c_str());
diff --git a/src/mqtt/hasp_mqtt_paho_async.cpp b/src/mqtt/hasp_mqtt_paho_async.cpp
index 6c4e35f2..28b81d10 100644
--- a/src/mqtt/hasp_mqtt_paho_async.cpp
+++ b/src/mqtt/hasp_mqtt_paho_async.cpp
@@ -3,8 +3,6 @@
/* Multi threaded asynchronous paho client */
-#include
-
#include "hasp_conf.h"
#if HASP_USE_MQTT_ASYNC > 0
@@ -47,7 +45,7 @@ const char FP_CONFIG_GROUP[] PROGMEM = "group";
#include "hasp_mqtt.h" // functions to implement here
#include "hasp/hasp_dispatch.h" // for dispatch_topic_payload
-#include "hasp_debug.h" // for logging
+#include "hasp_debug.h" // for logging
#if !defined(_WIN32)
#include
@@ -438,7 +436,10 @@ void mqttSetup()
mqttLwtTopic += MQTT_TOPIC_LWT;
}
-IRAM_ATTR void mqttLoop(){};
+IRAM_ATTR void mqttLoop() {};
+
+void mqttEverySecond()
+{}
void mqttEvery5Seconds(bool wifiIsConnected)
{
diff --git a/src/mqtt/hasp_mqtt_paho_single.cpp b/src/mqtt/hasp_mqtt_paho_single.cpp
index 653a884f..50044044 100644
--- a/src/mqtt/hasp_mqtt_paho_single.cpp
+++ b/src/mqtt/hasp_mqtt_paho_single.cpp
@@ -391,6 +391,9 @@ IRAM_ATTR void mqttLoop()
if(rc == MQTTCLIENT_SUCCESS && message) mqtt_message_arrived(mqtt_client, topicName, topicLen, message);
};
+void mqttEverySecond()
+{}
+
void mqttEvery5Seconds(bool wifiIsConnected)
{
if(!mqttIsConnected()) {
diff --git a/src/mqtt/hasp_mqtt_pubsubclient.cpp b/src/mqtt/hasp_mqtt_pubsubclient.cpp
index 29e11b2f..9acd5ce8 100644
--- a/src/mqtt/hasp_mqtt_pubsubclient.cpp
+++ b/src/mqtt/hasp_mqtt_pubsubclient.cpp
@@ -14,10 +14,10 @@
#if defined(ARDUINO_ARCH_ESP32)
#include
-#include
+// #include
WiFiClient mqttNetworkClient;
// WiFiClientSecure mqttNetworkClient;
-extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start");
+// extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start");
#elif defined(ARDUINO_ARCH_ESP8266)
#include
#include
diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp
index 0094f80b..693eec7b 100644
--- a/src/sys/gpio/hasp_gpio.cpp
+++ b/src/sys/gpio/hasp_gpio.cpp
@@ -835,7 +835,7 @@ hasp_gpio_config_t gpioGetPinConfig(uint8_t num)
return gpioConfig[num];
}
-void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer)
+void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer, JsonArray& event)
{
char description[20] = "";
@@ -848,6 +848,10 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA
case hasp_gpio_type_t::POWER_RELAY:
relay.add(gpioConfig[i].pin);
break;
+
+ case BUTTON ... TOUCH:
+ event.add(gpioConfig[i].pin);
+ break;
case hasp_gpio_type_t::HASP_DAC:
case hasp_gpio_type_t::LED: // Don't include the moodlight
@@ -857,8 +861,8 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA
dimmer.add(gpioConfig[i].pin);
break;
+ // case BUTTON ... TOUCH:
case SWITCH:
- case BUTTON ... TOUCH:
strcpy_P(description, PSTR("none"));
break;
case BATTERY:
@@ -950,8 +954,8 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA
strcpy_P(description, PSTR("unknown"));
}
- if((gpioConfig[i].type >= hasp_gpio_type_t::SWITCH && gpioConfig[i].type <= hasp_gpio_type_t::WINDOW) ||
- (gpioConfig[i].type >= hasp_gpio_type_t::BUTTON && gpioConfig[i].type <= hasp_gpio_type_t::TOUCH)) {
+ if((gpioConfig[i].type >= hasp_gpio_type_t::SWITCH && gpioConfig[i].type <= hasp_gpio_type_t::WINDOW)) {
+ // || (gpioConfig[i].type >= hasp_gpio_type_t::BUTTON && gpioConfig[i].type <= hasp_gpio_type_t::TOUCH)) {
JsonArray arr = input[description];
if(arr.isNull()) arr = input.createNestedArray(description);
arr.add(gpioConfig[i].pin);
diff --git a/src/sys/gpio/hasp_gpio.h b/src/sys/gpio/hasp_gpio.h
index df093048..105f4460 100644
--- a/src/sys/gpio/hasp_gpio.h
+++ b/src/sys/gpio/hasp_gpio.h
@@ -47,7 +47,7 @@ bool gpio_set_pin_state(uint8_t pin, bool power, int32_t val);
void gpio_set_moodlight(moodlight_t& moodlight);
-void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer);
+void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer, JsonArray& event);
bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc, bool inverted);
bool gpioIsSystemPin(uint8_t gpio);
diff --git a/user_setups/esp32/_esp32.ini b/user_setups/esp32/_esp32.ini
index 780997e5..93079589 100644
--- a/user_setups/esp32/_esp32.ini
+++ b/user_setups/esp32/_esp32.ini
@@ -45,7 +45,7 @@ build_flags =
-D LV_ATTRIBUTE_FAST_MEM=IRAM_ATTR
-D LV_ATTRIBUTE_TASK_HANDLER=IRAM_ATTR
-D LV_USE_FS_IF=1
- ;-D LV_FS_PC_PATH="//littlefs" ; this needs to match the vfs mount pount
+ -D LV_FS_PC_PATH='"/littlefs"' ; this needs to match the vfs mount pount
; -- ArduinoJson build options ----------------------------
-D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments
; -- tft_espi build options ------------------------
diff --git a/user_setups/esp32s2/_esp32s2.ini b/user_setups/esp32s2/_esp32s2.ini
index 0cfc0156..7b042521 100644
--- a/user_setups/esp32s2/_esp32s2.ini
+++ b/user_setups/esp32s2/_esp32s2.ini
@@ -15,7 +15,7 @@ build_flags =
-D LV_ATTRIBUTE_FAST_MEM=
-D LV_ATTRIBUTE_TASK_HANDLER=IRAM_ATTR
-D LV_USE_FS_IF=1
- ;-D LV_FS_PC_PATH="//littlefs" ; this needs to match the vfs mount pount
+ -D LV_FS_PC_PATH='"/littlefs"' ; this needs to match the vfs mount pount
; -- ArduinoJson build options ----------------------------
-D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments
; -- tft_espi build options ------------------------
diff --git a/user_setups/esp32s3/crowpanel-hmi.ini b/user_setups/esp32s3/crowpanel-hmi.ini
index 5a6be7c0..74ebc05c 100644
--- a/user_setups/esp32s3/crowpanel-hmi.ini
+++ b/user_setups/esp32s3/crowpanel-hmi.ini
@@ -81,9 +81,6 @@ extends = elecrow-esp32-s3-tft, flash_4mb
build_flags =
-D HASP_MODEL="Elecrow WZ8048C070"
- -D HASP_LOG_LEVEL=LOG_LEVEL_WARNING
- -D HASP_USE_CAPTIVE_PORTAL=0
- ; -D HASP_USE_CUSTOM=1
${elecrow-esp32-s3-tft.build_flags}
${elecrow-tft-common-pins.build_flags}
@@ -127,9 +124,6 @@ extends = elecrow-esp32-s3-tft, flash_4mb
build_flags =
-D HASP_MODEL="Elecrow WZ8048C050"
- -D HASP_LOG_LEVEL=LOG_LEVEL_WARNING
- -D HASP_USE_CAPTIVE_PORTAL=0
- ; -D HASP_USE_CUSTOM=1
${elecrow-esp32-s3-tft.build_flags}
diff --git a/user_setups/esp32s3/esp32-s3-4848S040.ini b/user_setups/esp32s3/esp32-s3-4848S040.ini
index 95c800ac..27d89050 100644
--- a/user_setups/esp32s3/esp32-s3-4848S040.ini
+++ b/user_setups/esp32s3/esp32-s3-4848S040.ini
@@ -76,6 +76,10 @@ build_flags =
-D I2C_TOUCH_FREQUENCY=400000
-D I2C_TOUCH_ADDRESS=0x5D ; or 0x14
-D I2C_TOUCH_PORT=1
+ ; USB GPIO - Only need to define these so that the pins do not
+ ; show up in the list of available GPIO
+ -D USB_TXD=43
+ -D USB_RXD=44
;endregion
lib_deps =
diff --git a/user_setups/esp32s3/guition-jc4827w543.ini b/user_setups/esp32s3/guition-jc4827w543.ini
new file mode 100644
index 00000000..0d41565c
--- /dev/null
+++ b/user_setups/esp32s3/guition-jc4827w543.ini
@@ -0,0 +1,59 @@
+;***************************************************;
+; Guition ESP32-S3 TFT 4.3" ;
+; - Custom esp32-s3 board ;
+; - nv3041a 480x272 ;
+; - gt911 touch controller ;
+;***************************************************;
+
+[guition-esp32-s3-tft]
+extends = arduino_esp32s3_v2
+board = esp32-s3-devkitc-1
+board_build.arduino.memory_type = qio_opi
+
+build_flags =
+ ${arduino_esp32s3_v2.build_flags}
+ ${esp32s3.ps_ram}
+ ;-D HASP_MODEL="Guition 4.3\""
+
+;region -- ArduinoGFX build options ------------------------
+ -D HASP_USE_ARDUINOGFX
+ -D NV3041A_DRIVER
+ ;endregion
+
+lib_deps =
+ ${arduino_esp32s3_v2.lib_deps}
+ ${arduinogfx.lib_deps}
+ ${goodix.lib_deps}
+
+
+[guition-tft-common-pins]
+build_flags =
+ -D TFT_BCKL=1
+ -D TFT_CS=45
+ -D TFT_SCK=47
+ -D TFT_D0=21
+ -D TFT_D1=48
+ -D TFT_D2=40
+ -D TFT_D3=39
+ -D TFT_RST=GFX_NOT_DEFINED
+ -D TFT_ROTATION=0
+ -D TFT_IPS=true
+ -D TFT_WIDTH=480
+ -D TFT_HEIGHT=272
+
+[env:guition-jc4827w543c_4MB]
+extends = guition-esp32-s3-tft, flash_4mb
+debug_tool = esp-builtin
+debug_build_flags = -Os # optimize for size
+build_flags =
+ -D HASP_MODEL="Guition ESP32-S3 JC4827W543C"
+ ${guition-esp32-s3-tft.build_flags}
+ ${guition-tft-common-pins.build_flags}
+ ; Touch Settings
+ -D TOUCH_DRIVER=0x0911
+ -D TOUCH_SCL=4
+ -D TOUCH_SDA=8
+ -D TOUCH_IRQ=-1
+ -D TOUCH_RST=38
+ -D I2C_TOUCH_FREQUENCY=0
+ -D I2C_TOUCH_ADDRESS=0x5D
diff --git a/user_setups/esp32s3/sensecap-indicator.ini b/user_setups/esp32s3/sensecap-indicator.ini
index ef64e18d..bc721aba 100644
--- a/user_setups/esp32s3/sensecap-indicator.ini
+++ b/user_setups/esp32s3/sensecap-indicator.ini
@@ -83,8 +83,7 @@ build_flags =
lib_deps =
${arduino_esp32s3_v2.lib_deps}
- ${arduinogfx.lib_deps}
- ; ${ft6336.lib_deps}
+ moononournation/GFX Library for Arduino@1.4.0 ; Update needs modification of custom PCA class ; ${ft6336.lib_deps}
; git+https://github.com/RobTillaart/TCA9555.git
diff --git a/user_setups/esp32s3/sunton-esp32-s3-tft.ini b/user_setups/esp32s3/sunton-esp32-s3-tft.ini
index 1da68da7..5c4e9139 100644
--- a/user_setups/esp32s3/sunton-esp32-s3-tft.ini
+++ b/user_setups/esp32s3/sunton-esp32-s3-tft.ini
@@ -142,7 +142,7 @@ build_flags =
-D TFT_VSYNC_PULSE_WIDTH=4 ; Typical VSYNC Pulse Width
-D TFT_VSYNC_BACK_PORCH=8 ; Typical VSYNC Back Porch
-D TFT_PCLK_ACTIVE_NEG=1
- -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency
+ -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency
-D TFT_AUTO_FLUSH=1
; Touch Settings
-D TOUCH_WIDTH=480
@@ -180,7 +180,7 @@ build_flags =
-D TFT_VSYNC_PULSE_WIDTH=4 ; Typical VSYNC Pulse Width
-D TFT_VSYNC_BACK_PORCH=8 ; Typical VSYNC Back Porch
-D TFT_PCLK_ACTIVE_NEG=1
- -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency
+ -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency
-D TFT_AUTO_FLUSH=1
; Touch Settings
-D TOUCH_WIDTH=800
@@ -229,15 +229,15 @@ build_flags =
-D TFT_B4=4
; Panel Settings
-D TFT_HSYNC_POLARITY=0
- -D TFT_HSYNC_FRONT_PORCH=8 ; Maximum HSYNC Front Porch / 8 GOOD
- -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width / 10 GOOD
- -D TFT_HSYNC_BACK_PORCH=43 ; Typical HSYNC Back Porch / 43 GOOD
+ -D TFT_HSYNC_FRONT_PORCH=8 ; Maximum HSYNC Front Porch / 8 GOOD
+ -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width / 10 GOOD
+ -D TFT_HSYNC_BACK_PORCH=43 ; Typical HSYNC Back Porch / 43 GOOD
-D TFT_VSYNC_POLARITY=0
-D TFT_VSYNC_FRONT_PORCH=8 ; Maximum VSYNC Front Porch / 8 GOOD
-D TFT_VSYNC_PULSE_WIDTH=8 ; Typical VSYNC Pulse Width / 8 GOOD
- -D TFT_VSYNC_BACK_PORCH=12 ; Typical VSYNC Back Porch / 12 GOOD
+ -D TFT_VSYNC_BACK_PORCH=12 ; Typical VSYNC Back Porch / 12 GOOD
-D TFT_PCLK_ACTIVE_NEG=1
- -D TFT_PREFER_SPEED=14500000 ; 1/2 of Typical DCLK Frequency / 12000000 GOOD
+ -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency / 12000000 GOOD
-D TFT_AUTO_FLUSH=1
; Touch Settings
-D TOUCH_WIDTH=800
diff --git a/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini b/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini
new file mode 100644
index 00000000..fd766e4a
--- /dev/null
+++ b/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini
@@ -0,0 +1,86 @@
+;***************************************************;
+; Waveshare ESP32-S3-Touch-LCD-4.3 ;
+; - 16-bit RGB TFT ;
+; - GT911 touch controller ;
+;***************************************************;
+
+
+[ws_esp32_s3_touch]
+extends = arduino_esp32s3_v2, flash_8mb
+board = esp32-s3-devkitc-1
+board_build.arduino.memory_type = qio_opi
+
+build_flags =
+ ${arduino_esp32s3_v2.build_flags}
+ ${esp32s3.ps_ram}
+ ;-DARDUINO_USB_CDC_ON_BOOT
+ ;-DUSE_USB_CDC_CONSOLE
+
+;region -- ArduinoGFX build options ------------------------
+ -D HASP_USE_ARDUINOGFX=1
+ -D HASP_LV_USE_SW_ROTATE=1
+;endregion
+
+lib_deps =
+ ${arduino_esp32s3_v2.lib_deps}
+ ${arduinogfx.lib_deps}
+ Arduino_RPi_DPI_RGBPanel_mod
+ ${goodix.lib_deps}
+
+[env:ws_esp32_s3_touch_lcd_4p3]
+extends = ws_esp32_s3_touch
+
+build_flags =
+ -D HASP_MODEL="Waveshare ESP32-S3-Touch-LCD-4.3"
+ ${ws_esp32_s3_touch.build_flags}
+ ; Bus Settings
+ -D LV_VDB_SIZE=76800 ; 10% of full framebuffer
+ -D TFT_WIDTH=800
+ -D TFT_HEIGHT=480
+ -D TFT_DE=5
+ -D TFT_VSYNC=3
+ -D TFT_HSYNC=46
+ -D TFT_PCLK=7
+ -D TFT_B0=14
+ -D TFT_B1=38
+ -D TFT_B2=18
+ -D TFT_B3=17
+ -D TFT_B4=10
+ -D TFT_G0=39
+ -D TFT_G1=0
+ -D TFT_G2=45
+ -D TFT_G3=48
+ -D TFT_G4=47
+ -D TFT_G5=21
+ -D TFT_R0=1
+ -D TFT_R1=2
+ -D TFT_R2=42
+ -D TFT_R3=41
+ -D TFT_R4=40
+ -D TFT_BCKL=6 ; use GPIO06 as backlight PIN
+ ; Panel Settings
+ -D TFT_HSYNC_POLARITY=0
+ -D TFT_HSYNC_FRONT_PORCH=20 ; Maximum HSYNC Front Porch
+ -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width
+ -D TFT_HSYNC_BACK_PORCH=10 ; Typical HSYNC Back Porch
+ -D TFT_VSYNC_POLARITY=0
+ -D TFT_VSYNC_FRONT_PORCH=10 ; Maximum VSYNC Front Porch
+ -D TFT_VSYNC_PULSE_WIDTH=10 ; Typical VSYNC Pulse Width
+ -D TFT_VSYNC_BACK_PORCH=10 ; Typical VSYNC Back Porch
+ -D TFT_PCLK_ACTIVE_NEG=0
+ -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency
+ -D TFT_AUTO_FLUSH=1
+ ; Touch Settings
+ -D TOUCH_WIDTH=800
+ -D TOUCH_HEIGHT=480
+ -D TOUCH_DRIVER=0x911
+ -D TOUCH_SCL=9
+ -D TOUCH_SDA=8
+ -D TOUCH_IRQ=-1
+ -D TOUCH_RST=-1
+ -D I2C_TOUCH_ADDRESS=0x5d ; or 0x5D
+ -D I2C_TOUCH_FREQUENCY=400000
+ -D BACKLIGHT_FREQUENCY=1000 ;adopted frerquency for MP3302DJ-LF-Z (200 to 1000Hz) ->higher is better for sound!
+lib_deps =
+ ${sunton-esp32-s3-tft.lib_deps}
+ ${goodix.lib_deps}