mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 07:06:36 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
205dfa0ce2 | ||
|
|
5c7b53b740 | ||
|
|
e7fbaffbab | ||
|
|
c68b582be7 |
129
ESP32_AP-Flasher/data/content_template.json
Normal file
129
ESP32_AP-Flasher/data/content_template.json
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"1": {
|
||||
"0": {
|
||||
"weekday": [ 76, 10, "fonts/calibrib30" ],
|
||||
"month": [ 76, 120, "fonts/calibrib30" ],
|
||||
"day": [ 76, 42, "fonts/calibrib100" ]
|
||||
},
|
||||
"1": {
|
||||
"weekday": [ 148, 10, "fonts/calibrib60" ],
|
||||
"date": [ 148, 73, "fonts/calibrib50" ]
|
||||
},
|
||||
"2": {
|
||||
"weekday": [ 200, 25, "fonts/calibrib60" ],
|
||||
"month": [ 200, 225, "fonts/calibrib60" ],
|
||||
"day": [ 200, 95, "fonts/calibrib150" ]
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"fonts": [ "fonts/calibrib120", "fonts/calibrib80", "fonts/calibrib50", "fonts/calibrib50" ],
|
||||
"xy": [ 76, 83 ]
|
||||
},
|
||||
"1": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120", "fonts/calibrib100" ],
|
||||
"xy": [ 148, 74 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120" ],
|
||||
"xy": [ 200, 148 ]
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"0": {
|
||||
"location": [ 10, 130, 2 ],
|
||||
"wind": [ 140, 10, "fonts/bahnschrift30" ],
|
||||
"temp": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"icon": [ 33, 33, "fonts/weathericons78" ],
|
||||
"dir": [ 100, -2, "fonts/weathericons30" ],
|
||||
"umbrella": [ 115, 110 ]
|
||||
},
|
||||
"1": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"wind": [ 280, 5, "fonts/bahnschrift30" ],
|
||||
"temp": [ 5, 65, "fonts/bahnschrift70" ],
|
||||
"icon": [ 185, 32, "fonts/weathericons70" ],
|
||||
"dir": [ 240, -3, "fonts/weathericons30" ],
|
||||
"umbrella": [ 190, 0 ]
|
||||
},
|
||||
"2": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 290, 83, "fonts/calibrib60" ],
|
||||
"temp": [ 20, 170, "fonts/calibrib150" ],
|
||||
"icon": [ 100, 50, "fonts/weathericons78" ],
|
||||
"dir": [ 220, 50, "fonts/weathericons78" ],
|
||||
"umbrella": [ 330, 10 ]
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"1": {
|
||||
"location": [ 5, 0, 2 ],
|
||||
"column": [ 5, 59 ],
|
||||
"day": [ 30, 18, "fonts/twcondensed20", 41, 108 ],
|
||||
"icon": [ 12, 58, "fonts/weathericons30" ],
|
||||
"wind": [ 17, 25 ],
|
||||
"line": [ 20, 128 ]
|
||||
},
|
||||
"2": {
|
||||
"location": [ 10, 10, "fonts/calibrib30" ],
|
||||
"column": [ 6, 66 ],
|
||||
"day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ],
|
||||
"rain": [ 34, 260 ],
|
||||
"icon": [ 15, 145, "fonts/weathericons30" ],
|
||||
"wind": [ 17, 90 ],
|
||||
"line": [ 50, 300 ]
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"1": {
|
||||
"title": [ 5, 3, "fonts/bahnschrift20" ],
|
||||
"items": 8,
|
||||
"line": [ 5, 34, 13 ],
|
||||
"font": "glasstown_nbp_tf"
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/calibrib30" ],
|
||||
"items": 12,
|
||||
"line": [ 10, 60, 20 ],
|
||||
"font": "7x14_tf"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"0": {
|
||||
"title": [ 10, 3, 2 ],
|
||||
"pos": [ 76, 20 ]
|
||||
},
|
||||
"1": {
|
||||
"title": [ 10, 5, "fonts/bahnschrift20" ],
|
||||
"pos": [ 149, 25 ]
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 200, 30 ]
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"1": {
|
||||
"title": [ 5, 2, "fonts/bahnschrift20" ],
|
||||
"date": [ 290, 2 ],
|
||||
"items": 7,
|
||||
"red": [ 0, 21, 296, 14 ],
|
||||
"line": [ 5, 32, 15, "t0_14b_tf", 50 ]
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"date": [ 390, 10 ],
|
||||
"items": 12,
|
||||
"red": [ 0, 48, 400, 17 ],
|
||||
"line": [ 10, 61, 18, "7x14_tf", 60 ]
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"1": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"title": [ 247, 11, "glasstown_nbp_tf" ],
|
||||
"cols": [ 1, 125, 12 ],
|
||||
"bars": [ 5, 111, 10 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -21,6 +21,16 @@
|
||||
"name": "TimeToLive",
|
||||
"desc": "Amount (minutes) that this image will stay valid. The tag might not respond meanwhile",
|
||||
"type": "int"
|
||||
},
|
||||
{
|
||||
"key": "dither",
|
||||
"name": "Dithering",
|
||||
"desc": "Turn halftone dithering on or off. Turn it on when displaying photos. For texts, you better leave if off",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"0": "off",
|
||||
"1": "on"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -29,10 +29,30 @@
|
||||
<button id="paintbutton"><i>A</i>🖌</button>
|
||||
</p>
|
||||
<div id="customoptions"></div>
|
||||
<p>
|
||||
<input type="button" value="Save" id="cfgsave">
|
||||
<span id="cfgdelete"><img src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw==
|
||||
"></span>
|
||||
<div id="advancedoptions" style="height: 0px;">
|
||||
<p>Advanced options</p>
|
||||
<p>
|
||||
<label for="cfgrotate">Rotate image</label>
|
||||
<select id="cfgrotate">
|
||||
<option value="0">0 degrees</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label for="cfglut">LUT</label>
|
||||
<select id="cfglut">
|
||||
<option value="0">auto</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<button id="cfgrefresh">force refresh</button>
|
||||
<button id="cfgclrpending">clear pending</button>
|
||||
<button id="cfgdelete"><img src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw==
|
||||
"></button>
|
||||
</p>
|
||||
</div>
|
||||
<p id="savebar">
|
||||
<span><input type="button" value="Save" id="cfgsave"></span>
|
||||
<span id="cfgmore" title="advanced options">🞃</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -105,7 +125,7 @@ Latency will be around 40 seconds.">
|
||||
<th>alias</th>
|
||||
<th>tags</th>
|
||||
<th>ch</th>
|
||||
<th>fw ver</th>
|
||||
<th>AP ver</th>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
@@ -137,6 +157,7 @@ Latency will be around 40 seconds.">
|
||||
<div class="actionbox">
|
||||
<div>
|
||||
<div>Currently active tags:</div>
|
||||
<div><span id="runstate"></div>
|
||||
<div><span id="apstatecolor">⬤</span> <span id="apstate">loading</span></div>
|
||||
<div><span id="apconfigbutton">AP config</span></div>
|
||||
<div><a href="/edit" target="littlefs" class="filebutton">edit littleFS</a></div>
|
||||
@@ -159,8 +180,8 @@ Latency will be around 40 seconds.">
|
||||
<div class="nextcheckin"></div>
|
||||
<div class="nextupdate"></div>
|
||||
<div class="corner">
|
||||
<div class="pendingicon">↻</div>
|
||||
<div class="warningicon">⚠</div>
|
||||
<div class="pendingicon" title="A new message is waiting for the tag to pick up">↻</div>
|
||||
<div class="warningicon" title="This tag has not been seen for a long time">⚠</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,6 +142,33 @@ select {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
#advancedoptions {
|
||||
overflow: hidden;
|
||||
transition: height 0.3s ease;
|
||||
}
|
||||
|
||||
#advancedoptions p:first-child {
|
||||
font-weight: 700;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#savebar {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#savebar:first-child {
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
#cfgmore {
|
||||
padding: 2px 5px;
|
||||
font-weight: 700;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#apconfigbox {
|
||||
background-color: #e6f0d3;
|
||||
}
|
||||
@@ -179,10 +206,8 @@ select {
|
||||
}
|
||||
|
||||
#cfgdelete {
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 15px;
|
||||
cursor:pointer;
|
||||
cursor: pointer;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
.closebtn {
|
||||
@@ -245,7 +270,7 @@ select {
|
||||
}
|
||||
|
||||
.tagpending {
|
||||
animation: pending 1s ease infinite;
|
||||
animation: pending 1.5s ease infinite;
|
||||
}
|
||||
|
||||
.currimg {
|
||||
@@ -514,9 +539,9 @@ ul.messages li.new {
|
||||
}
|
||||
|
||||
@keyframes pending {
|
||||
0% { background-color: #d0d0e0;}
|
||||
50% { background-color: #b0b0e0;}
|
||||
100% { background-color: #d0d0e0;}
|
||||
0% { }
|
||||
50% { background-color: #d4d4f5;}
|
||||
100% { }
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
@@ -562,5 +587,10 @@ ul.messages li.new {
|
||||
|
||||
.actionbox>div {
|
||||
gap: 5px;
|
||||
flex-flow: wrap;
|
||||
}
|
||||
|
||||
.actionbox>div:first-child>div:first-child {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ const WAKEUP_REASON_WDT_RESET = 0xFE;
|
||||
const models = ["1.54\" 152x152px", "2.9\" 296x128px", "4.2\" 400x300px"];
|
||||
models[240] = "Segmented tag"
|
||||
models[17] = "2.9\" 296x128px (UC8151)"
|
||||
const displaySizeLookup = { 0: [152, 152], 1: [128, 296], 2: [400, 300] };
|
||||
displaySizeLookup[17] = [128, 296];
|
||||
const displaySizeLookup = { 0: [152, 152, 4], 1: [128, 296, 2], 2: [400, 300, 2] }; // w, h, rotate
|
||||
displaySizeLookup[17] = [128, 296, 2];
|
||||
displaySizeLookup[240] = [0, 0, 0];
|
||||
const colorTable = { 0: [255, 255, 255], 1: [0, 0, 0], 2: [255, 0, 0], 3: [150, 150, 150] };
|
||||
|
||||
const apstate = [
|
||||
@@ -24,6 +25,12 @@ const apstate = [
|
||||
{ state: "failed", color: "red" },
|
||||
{ state: "coming online", color: "yellow" }
|
||||
];
|
||||
const runstate = [
|
||||
{ state: "⏹︎ stopped" },
|
||||
{ state: "⏸pause" },
|
||||
{ state: "" }, // hide running
|
||||
{ state: "⏳︎ init" }
|
||||
];
|
||||
|
||||
const imageQueue = [];
|
||||
let isProcessing = false;
|
||||
@@ -91,6 +98,7 @@ function connect() {
|
||||
if (msg.sys.apstate) {
|
||||
$("#apstatecolor").style.color = apstate[msg.sys.apstate].color;
|
||||
$("#apstate").innerHTML = apstate[msg.sys.apstate].state;
|
||||
$("#runstate").innerHTML = runstate[msg.sys.runstate].state;
|
||||
}
|
||||
servertimediff = (Date.now() / 1000) - msg.sys.currtime;
|
||||
}
|
||||
@@ -208,6 +216,7 @@ function processTags(tagArray) {
|
||||
break;
|
||||
case WAKEUP_REASON_GPIO:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "GPIO wakeup"
|
||||
$('#tag' + tagmac).style.background = "#c8f1bb";
|
||||
break;
|
||||
case WAKEUP_REASON_NFC:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "NFC wakeup"
|
||||
@@ -272,6 +281,7 @@ $('#clearlog').onclick = function () {
|
||||
document.querySelectorAll('.closebtn').forEach(button => {
|
||||
button.addEventListener('click', (event) => {
|
||||
event.target.parentNode.style.display = 'none';
|
||||
$('#advancedoptions').style.height = '0px';
|
||||
});
|
||||
});
|
||||
|
||||
@@ -295,19 +305,29 @@ $('#taglist').addEventListener("click", (event) => {
|
||||
.then(data => {
|
||||
var tagdata = data.tags[0];
|
||||
$('#cfgalias').value = tagdata.alias;
|
||||
$('#cfgmore').style.display = "none";
|
||||
if (populateSelectTag(tagdata.hwType, tagdata.capabilities)) {
|
||||
$('#cfgcontent').parentNode.style.display = "flex";
|
||||
$('#cfgcontent').value = tagdata.contentMode;
|
||||
$('#cfgcontent').dataset.json = tagdata.modecfgjson;
|
||||
contentselected();
|
||||
if (tagdata.contentMode != 12) $('#cfgmore').style.display = 'block';
|
||||
} else {
|
||||
$('#customoptions').innerHTML = "";
|
||||
$('#cfgcontent').parentNode.style.display = "none";
|
||||
}
|
||||
$('#cfgrotate').value = tagdata.rotate;
|
||||
$('#cfglut').value = tagdata.lut;
|
||||
$('#cfgmore').innerHTML = '🞃';
|
||||
$('#configbox').style.display = 'block';
|
||||
})
|
||||
})
|
||||
|
||||
$('#cfgmore').onclick = function () {
|
||||
$('#cfgmore').innerHTML = $('#advancedoptions').style.height == '0px' ? '🞁' : '🞃';
|
||||
$('#advancedoptions').style.height = $('#advancedoptions').style.height == '0px' ? $('#advancedoptions').scrollHeight + 'px' : '0px';
|
||||
};
|
||||
|
||||
$('#cfgsave').onclick = function () {
|
||||
let contentMode = $('#cfgcontent').value;
|
||||
let contentDef = getContentDefById(contentMode);
|
||||
@@ -332,6 +352,9 @@ $('#cfgsave').onclick = function () {
|
||||
formData.append("modecfgjson", String());
|
||||
}
|
||||
|
||||
formData.append("rotate", $('#cfgrotate').value);
|
||||
formData.append("lut", $('#cfglut').value);
|
||||
|
||||
fetch("/save_cfg", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
@@ -340,26 +363,41 @@ $('#cfgsave').onclick = function () {
|
||||
.then(data => showMessage(data))
|
||||
.catch(error => showMessage('Error: ' + error));
|
||||
|
||||
$('#advancedoptions').style.height = '0px';
|
||||
$('#configbox').style.display = 'none';
|
||||
}
|
||||
|
||||
$('#cfgdelete').onclick = function () {
|
||||
function sendCmd(mac, cmd) {
|
||||
let formData = new FormData();
|
||||
formData.append("mac", $('#cfgmac').dataset.mac);
|
||||
fetch("/delete_cfg", {
|
||||
formData.append("mac", mac);
|
||||
formData.append("cmd", cmd);
|
||||
fetch("/tag_cmd", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
var div = $('#tag' + $('#cfgmac').dataset.mac);
|
||||
div.remove();
|
||||
if (cmd == "del") div.remove();
|
||||
showMessage(data);
|
||||
})
|
||||
.catch(error => showMessage('Error: ' + error));
|
||||
$('#advancedoptions').style.height = '0px';
|
||||
$('#configbox').style.display = 'none';
|
||||
}
|
||||
|
||||
$('#cfgdelete').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "del");
|
||||
}
|
||||
|
||||
$('#cfgclrpending').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "clear");
|
||||
}
|
||||
|
||||
$('#cfgrefresh').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "refresh");
|
||||
}
|
||||
|
||||
$('#rebootbutton').onclick = function () {
|
||||
showMessage("rebooting AP....", true);
|
||||
fetch("/reboot", {
|
||||
@@ -459,7 +497,6 @@ function contentselected() {
|
||||
obj = JSON.parse($('#cfgcontent').dataset.json);
|
||||
}
|
||||
$('#paintbutton').style.display = 'none';
|
||||
|
||||
if (contentMode) {
|
||||
let contentDef = getContentDefById(contentMode);
|
||||
if (contentDef) {
|
||||
@@ -487,6 +524,15 @@ function contentselected() {
|
||||
input.type = "text";
|
||||
input.disabled = true;
|
||||
break;
|
||||
case 'select':
|
||||
input = document.createElement("select");
|
||||
for (const key in element.options) {
|
||||
const optionElement = document.createElement("option");
|
||||
optionElement.value = key;
|
||||
optionElement.text = element.options[key];
|
||||
input.appendChild(optionElement);
|
||||
}
|
||||
break;
|
||||
}
|
||||
input.id = 'opt' + element.key;
|
||||
input.title = element.desc;
|
||||
@@ -505,17 +551,46 @@ function populateSelectTag(hwtype, capabilities) {
|
||||
var selectTag = $("#cfgcontent");
|
||||
selectTag.innerHTML = "";
|
||||
var optionsAdded = false;
|
||||
var option;
|
||||
cardconfig.forEach(item => {
|
||||
var capcheck = item.capabilities ?? 0;
|
||||
var hwtypeArray = item.hwtype;
|
||||
if (hwtypeArray.includes(hwtype) && (capabilities & capcheck || capcheck == 0)) {
|
||||
var option = document.createElement("option");
|
||||
option = document.createElement("option");
|
||||
option.value = item.id;
|
||||
option.text = item.name;
|
||||
selectTag.appendChild(option);
|
||||
optionsAdded = true;
|
||||
}
|
||||
});
|
||||
|
||||
var rotateTag = $("#cfgrotate");
|
||||
rotateTag.innerHTML = "";
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (i == 0 || displaySizeLookup[hwtype][2] == 4 || (i == 2 && displaySizeLookup[hwtype][2] == 2)) {
|
||||
option = document.createElement("option");
|
||||
option.value = i;
|
||||
option.text = (i * 90) + " degrees";
|
||||
rotateTag.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
var lutTag = $("#cfglut");
|
||||
lutTag.innerHTML = "";
|
||||
|
||||
option = document.createElement("option");
|
||||
option.value = "0";
|
||||
option.text = "auto";
|
||||
lutTag.appendChild(option);
|
||||
|
||||
if (hwtype != 240) {
|
||||
option = document.createElement("option");
|
||||
option.value = "1";
|
||||
option.text = "Always full refresh";
|
||||
lutTag.appendChild(option);
|
||||
}
|
||||
|
||||
return optionsAdded;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <LittleFS.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#include "U8g2_for_TFT_eSPI.h"
|
||||
#include "makeimage.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
@@ -18,7 +19,7 @@ void contentRunner();
|
||||
void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo);
|
||||
bool updateTagImage(String &filename, uint8_t *dst, uint16_t nextCheckin, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawString(TFT_eSprite &spr, String content, uint16_t posx, uint16_t posy, String font, byte align = 0, uint16_t color = TFT_BLACK);
|
||||
void initSprite(TFT_eSprite &spr, int w, int h);
|
||||
void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams);
|
||||
void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawWeather(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
@@ -35,4 +36,6 @@ int windSpeedToBeaufort(float windSpeed);
|
||||
String windDirectionIcon(int degrees);
|
||||
void getLocation(JsonObject &cfgobj);
|
||||
void prepareNFCReq(uint8_t* dst, const char* url);
|
||||
void prepareLUTreq(uint8_t *dst, String input);
|
||||
void prepareLUTreq(uint8_t *dst, String input);
|
||||
void getTemplate(JsonDocument &json, const char *filePath, uint8_t id, uint8_t hwtype);
|
||||
void setU8G2Font(const String &title, U8g2_for_TFT_eSPI &u8f);
|
||||
|
||||
@@ -8,6 +8,8 @@ struct imgParam {
|
||||
uint8_t dataType;
|
||||
bool dither;
|
||||
bool grayLut = false;
|
||||
uint8_t bpp = 8;
|
||||
uint8_t rotate = 0;
|
||||
|
||||
char segments[12];
|
||||
uint16_t symbols;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
void doLeds();
|
||||
void rampTagPower(uint8_t pin, bool up);
|
||||
//void doLeds();
|
||||
void powerControl(bool powerState, uint8_t* pin, uint8_t pincount);
|
||||
|
||||
14
ESP32_AP-Flasher/include/system.h
Normal file
14
ESP32_AP-Flasher/include/system.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#define WAKEUP_REASON_TIMED 0
|
||||
#define WAKEUP_REASON_BOOT 1
|
||||
#define WAKEUP_REASON_GPIO 2
|
||||
#define WAKEUP_REASON_NFC 3
|
||||
#define WAKEUP_REASON_FIRSTBOOT 0xFC
|
||||
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
|
||||
#define WAKEUP_REASON_WDT_RESET 0xFE
|
||||
|
||||
void init_time();
|
||||
void logLine(char* buffer);
|
||||
void logLine(String text);
|
||||
void logStartUp();
|
||||
@@ -14,11 +14,12 @@
|
||||
#define RUNSTATUS_STOP 0
|
||||
#define RUNSTATUS_PAUSE 1
|
||||
#define RUNSTATUS_RUN 2
|
||||
#define RUNSTATUS_INIT 3
|
||||
|
||||
class tagRecord {
|
||||
public:
|
||||
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), hasCustomLUT(false),
|
||||
filename(""), data(nullptr), len(0) {}
|
||||
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0),
|
||||
dataType(0), filename(""), data(nullptr), len(0) {}
|
||||
|
||||
uint8_t mac[8];
|
||||
String alias;
|
||||
@@ -41,6 +42,10 @@ class tagRecord {
|
||||
bool isExternal;
|
||||
uint16_t pendingIdle;
|
||||
bool hasCustomLUT;
|
||||
uint8_t rotate;
|
||||
uint8_t lut;
|
||||
|
||||
uint8_t dataType;
|
||||
String filename;
|
||||
uint8_t* data;
|
||||
uint32_t len;
|
||||
@@ -58,7 +63,7 @@ struct Config {
|
||||
uint8_t runStatus;
|
||||
};
|
||||
|
||||
extern SemaphoreHandle_t tagDBOwner;
|
||||
// extern SemaphoreHandle_t tagDBOwner;
|
||||
extern Config config;
|
||||
extern std::vector<tagRecord*> tagDB;
|
||||
extern DynamicJsonDocument APconfig;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
class ZBS_interface
|
||||
{
|
||||
public:
|
||||
uint8_t begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t POWER = -1, uint32_t spi_speed = 8000000);
|
||||
uint8_t begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t* POWER = nullptr, uint8_t powerPins = 1, uint32_t spi_speed = 8000000);
|
||||
void setSpeed(uint32_t speed);
|
||||
void set_power(uint8_t state);
|
||||
void enable_debug();
|
||||
@@ -38,7 +38,8 @@ private:
|
||||
uint8_t _MOSI_PIN = -1;
|
||||
uint8_t _MISO_PIN = -1;
|
||||
uint8_t _RESET_PIN = -1;
|
||||
uint8_t _POWER_PIN = -1;
|
||||
uint8_t* _POWER_PIN = nullptr;
|
||||
uint8_t _POWER_PINS = 1;
|
||||
int ZBS_spi_delay = 1;
|
||||
uint8_t spi_ready = 0;
|
||||
uint32_t after_byte_delay = 10;
|
||||
|
||||
@@ -21,6 +21,7 @@ lib_deps =
|
||||
https://github.com/Bodmer/U8g2_for_TFT_eSPI
|
||||
https://github.com/ricmoo/qrcode
|
||||
fastled/FastLED
|
||||
|
||||
platform_packages =
|
||||
board_build.filesystem = littlefs
|
||||
monitor_filters = esp32_exception_decoder
|
||||
@@ -42,18 +43,18 @@ build_flags =
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
;-D DEBUG_VERSION
|
||||
|
||||
-D HAS_RGB_LED
|
||||
-D BOARD_HAS_PSRAM
|
||||
;-D HAS_USB
|
||||
|
||||
-D POWER_NO_SOFT_POWER
|
||||
|
||||
-D FLASHER_AP_SS=11
|
||||
-D FLASHER_AP_CLK=9
|
||||
-D FLASHER_AP_MOSI=10
|
||||
-D FLASHER_AP_MISO=8
|
||||
-D FLASHER_AP_RESET=13
|
||||
-D FLASHER_AP_POWER=-1 ;this board has no soft power control
|
||||
-D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
-D FLASHER_AP_TXD=7
|
||||
-D FLASHER_AP_RXD=6
|
||||
-D FLASHER_AP_TEST=12
|
||||
@@ -89,21 +90,15 @@ build_flags =
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
;-D DEBUG_VERSION
|
||||
|
||||
;-D HAS_RGB_LED
|
||||
-D BOARD_HAS_PSRAM
|
||||
;-D HAS_USB
|
||||
|
||||
|
||||
-D FLASHER_AP_SS=38
|
||||
-D FLASHER_AP_CLK=40
|
||||
-D FLASHER_AP_MOSI=39
|
||||
-D FLASHER_AP_MISO=33
|
||||
-D FLASHER_AP_RESET=37
|
||||
-D FLASHER_AP_POWER=18
|
||||
-D FLASHER_AP_POWER2=21
|
||||
-D FLASHER_AP_POWER3=16
|
||||
-D FLASHER_AP_POWER4=17
|
||||
-D FLASHER_AP_POWER={16,17,18,21}
|
||||
-D FLASHER_AP_TXD=35
|
||||
-D FLASHER_AP_RXD=36
|
||||
-D FLASHER_AP_TEST=34
|
||||
@@ -150,12 +145,15 @@ build_flags =
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
|
||||
-D POWER_RAMPING
|
||||
-D POWER_HIGH_SIDE_DRIVER
|
||||
|
||||
-D FLASHER_AP_SS=4
|
||||
-D FLASHER_AP_CLK=5
|
||||
-D FLASHER_AP_MOSI=7
|
||||
-D FLASHER_AP_MISO=6
|
||||
-D FLASHER_AP_RESET=15
|
||||
-D FLASHER_AP_POWER=0
|
||||
-D FLASHER_AP_POWER={0}
|
||||
-D FLASHER_AP_TXD=16
|
||||
-D FLASHER_AP_RXD=18
|
||||
-D FLASHER_AP_TEST=17
|
||||
@@ -165,7 +163,7 @@ build_flags =
|
||||
-D FLASHER_EXT_MOSI=2
|
||||
-D FLASHER_EXT_MISO=42
|
||||
-D FLASHER_EXT_RESET=1
|
||||
-D FLASHER_EXT_POWER=8
|
||||
-D FLASHER_EXT_POWER={8}
|
||||
-D FLASHER_EXT_TXD=38
|
||||
-D FLASHER_EXT_RXD=39
|
||||
-D FLASHER_EXT_TEST=47
|
||||
@@ -175,6 +173,7 @@ build_flags =
|
||||
-D FLASHER_ALT_MOSI=10
|
||||
-D FLASHER_ALT_MISO=9
|
||||
-D FLASHER_ALT_RESET=11
|
||||
-D FLASHER_ALT_POWER={-1}
|
||||
-D FLASHER_ALT_TXD=12
|
||||
-D FLASHER_ALT_RXD=14
|
||||
-D FLASHER_ALT_TEST=13
|
||||
@@ -211,8 +210,7 @@ build_flags =
|
||||
-D FLASHER_AP_MOSI=23
|
||||
-D FLASHER_AP_MISO=19
|
||||
-D FLASHER_AP_RESET=2
|
||||
-D FLASHER_AP_POWER=13 ;// switching HIGH side; connect to 3V3 of tag
|
||||
-D FLASHER_AP_POWER2=15
|
||||
-D FLASHER_AP_POWER={13,15}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=16
|
||||
@@ -244,8 +242,7 @@ build_flags =
|
||||
-D FLASHER_AP_MOSI=23
|
||||
-D FLASHER_AP_MISO=33
|
||||
-D FLASHER_AP_RESET=27
|
||||
-D FLASHER_AP_POWER=4
|
||||
-D FLASHER_AP_POWER2=4
|
||||
-D FLASHER_AP_POWER={4}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=26
|
||||
-D FLASHER_AP_RXD=25
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,16 @@ void dump(uint8_t *a, uint16_t l) {
|
||||
Serial.printf("\n");
|
||||
}
|
||||
|
||||
int8_t powerPinsAP[] = FLASHER_AP_POWER;
|
||||
int8_t pinsAP[] = {FLASHER_AP_CLK, FLASHER_AP_MISO, FLASHER_AP_MOSI, FLASHER_AP_RESET, FLASHER_AP_RXD, FLASHER_AP_SS, FLASHER_AP_TEST, FLASHER_AP_TXD};
|
||||
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
int8_t powerPinsExt[] = FLASHER_EXT_POWER;
|
||||
int8_t powerPinsAlt[] = FLASHER_ALT_POWER;
|
||||
uint8_t pinsExt[] = {FLASHER_EXT_CLK, FLASHER_EXT_MISO, FLASHER_EXT_MOSI, FLASHER_EXT_RESET, FLASHER_EXT_RXD, FLASHER_EXT_SS, FLASHER_EXT_TEST, FLASHER_EXT_TXD};
|
||||
|
||||
#endif
|
||||
|
||||
class flasher {
|
||||
public:
|
||||
class ZBS_interface *zbs = nullptr;
|
||||
@@ -106,16 +116,17 @@ flasher::~flasher() {
|
||||
|
||||
bool flasher::connectTag(uint8_t port) {
|
||||
bool result;
|
||||
|
||||
switch (port) {
|
||||
case 0:
|
||||
result = zbs->begin(FLASHER_AP_SS, FLASHER_AP_CLK, FLASHER_AP_MOSI, FLASHER_AP_MISO, FLASHER_AP_RESET, FLASHER_AP_POWER, 8000000);
|
||||
result = zbs->begin(FLASHER_AP_SS, FLASHER_AP_CLK, FLASHER_AP_MOSI, FLASHER_AP_MISO, FLASHER_AP_RESET, (uint8_t *)powerPinsAP, sizeof(powerPinsAP), 8000000);
|
||||
break;
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
case 1:
|
||||
result = zbs->begin(FLASHER_EXT_SS, FLASHER_EXT_CLK, FLASHER_EXT_MOSI, FLASHER_EXT_MISO, FLASHER_EXT_RESET, FLASHER_EXT_POWER, 8000000);
|
||||
result = zbs->begin(FLASHER_EXT_SS, FLASHER_EXT_CLK, FLASHER_EXT_MOSI, FLASHER_EXT_MISO, FLASHER_EXT_RESET, (uint8_t *)powerPinsExt, sizeof(powerPinsExt), 8000000);
|
||||
break;
|
||||
case 2:
|
||||
result = zbs->begin(FLASHER_ALT_SS, FLASHER_ALT_CLK, FLASHER_ALT_MOSI, FLASHER_ALT_MISO, FLASHER_ALT_RESET, 255, 8000000);
|
||||
result = zbs->begin(FLASHER_ALT_SS, FLASHER_ALT_CLK, FLASHER_ALT_MOSI, FLASHER_ALT_MISO, FLASHER_ALT_RESET, (uint8_t *)powerPinsAlt, sizeof(powerPinsAlt), 8000000);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -625,6 +636,42 @@ void flashCountDown(uint8_t c) {
|
||||
}
|
||||
}
|
||||
|
||||
void pinTest() {
|
||||
uint8_t *pintest;
|
||||
pintest = (uint8_t *)pinsAP;
|
||||
for (uint8_t c = 0; c < 8; c++) {
|
||||
if (pintest[c] != -1) {
|
||||
pinMode(pintest[c], INPUT_PULLDOWN);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
if (digitalRead(pintest[c])) {
|
||||
Serial.printf("Pin %d failed to become low\n", c);
|
||||
} else {
|
||||
pinMode(pintest[c], INPUT_PULLUP);
|
||||
bool pinChange = false;
|
||||
uint16_t pinTime = 0;
|
||||
for (uint16_t t = 0; t < 65535; t++) {
|
||||
if (digitalRead(pintest[c])) {
|
||||
pinChange = true;
|
||||
pinTime = t;
|
||||
break;
|
||||
}
|
||||
ets_delay_us(1);
|
||||
}
|
||||
if (pinChange) {
|
||||
Serial.printf("Pin %d went high in %d µS\n", pintest[c], pinTime);
|
||||
} else {
|
||||
Serial.printf("Pin %d timeout becoming high\n", pintest[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint8_t c = 0; c < 8; c++) {
|
||||
if (pintest[c] != -1) {
|
||||
pinMode(pintest[c], INPUT_PULLDOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
// perform device flash, save mac, everything
|
||||
bool doTagFlash() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "makeimage.h"
|
||||
#include "serialap.h"
|
||||
#include "settings.h"
|
||||
#include "system.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
#ifdef HAS_USB
|
||||
@@ -19,24 +20,27 @@
|
||||
#include "udp.h"
|
||||
#include "web.h"
|
||||
|
||||
void timeTask(void* parameter) {
|
||||
void pinTest();
|
||||
|
||||
void delayedStart(void* parameter) {
|
||||
vTaskDelay(30000 / portTICK_PERIOD_MS);
|
||||
Serial.println("Resuming content generation");
|
||||
wsLog("resuming content generation");
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
esp_reset_reason_t resetReason = esp_reset_reason();
|
||||
// if (resetReason == ESP_RST_PANIC) config.runStatus = RUNSTATUS_PAUSE;
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void timeTask(void* parameter) {
|
||||
wsSendSysteminfo();
|
||||
while (1) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
tm tm;
|
||||
if (!getLocalTime(&tm)) {
|
||||
Serial.println("Waiting for valid time from NTP-server");
|
||||
} else {
|
||||
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE) {
|
||||
wsSendSysteminfo();
|
||||
}
|
||||
if (now % 300 == 6 && config.runStatus != RUNSTATUS_STOP) saveDB("/current/tagDB.json");
|
||||
|
||||
if (apInfo.state == AP_STATE_ONLINE) contentRunner();
|
||||
}
|
||||
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE || config.runStatus != RUNSTATUS_RUN) wsSendSysteminfo();
|
||||
if (now % 300 == 6 && config.runStatus != RUNSTATUS_STOP) saveDB("/current/tagDB.json");
|
||||
if (apInfo.state == AP_STATE_ONLINE) contentRunner();
|
||||
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +70,7 @@ void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.print(">\n");
|
||||
|
||||
pinTest();
|
||||
#ifdef BOARD_HAS_PSRAM
|
||||
if (!psramInit()) {
|
||||
Serial.printf("This build of the AP expects PSRAM, but we couldn't find/init any. Something is terribly wrong here! System halted.");
|
||||
@@ -124,16 +129,37 @@ void setup() {
|
||||
rgbIdle();
|
||||
#endif
|
||||
loadDB("/current/tagDB.json");
|
||||
tagDBOwner = xSemaphoreCreateMutex();
|
||||
// tagDBOwner = xSemaphoreCreateMutex();
|
||||
xTaskCreate(APTask, "AP Process", 6000, NULL, 2, NULL);
|
||||
xTaskCreate(webSocketSendProcess, "ws", 2000, NULL, configMAX_PRIORITIES - 10, NULL);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
config.runStatus = RUNSTATUS_INIT;
|
||||
|
||||
xTaskCreate(timeTask, "timed tasks", 12000, NULL, 2, NULL);
|
||||
|
||||
init_time();
|
||||
logStartUp();
|
||||
|
||||
esp_reset_reason_t resetReason = esp_reset_reason();
|
||||
if (resetReason == ESP_RST_PANIC) {
|
||||
Serial.println("Panic! Pausing content generation for 30 seconds");
|
||||
config.runStatus = RUNSTATUS_PAUSE;
|
||||
xTaskCreate(delayedStart, "delaystart", 2000, NULL, 2, NULL);
|
||||
} else {
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
// performDeviceFlash();
|
||||
while (1) {
|
||||
// pinTest();
|
||||
while (1) {
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
// pinTest();
|
||||
}
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
if (extTagConnected()) {
|
||||
flashCountDown(3);
|
||||
|
||||
@@ -37,9 +37,10 @@ void jpg2buffer(String filein, String fileout, imgParam &imageParams) {
|
||||
#endif
|
||||
spr.createSprite(w, h);
|
||||
if (spr.getPointer() == nullptr) {
|
||||
//no heap space for 8bpp, fallback to 1bpp
|
||||
wsErr("fallback to 1bpp");
|
||||
wsErr("low on memory. Fallback to 1bpp");
|
||||
spr.setColorDepth(1);
|
||||
spr.setBitmapColor(TFT_WHITE, TFT_BLACK);
|
||||
imageParams.bpp = 1;
|
||||
spr.createSprite(w, h);
|
||||
}
|
||||
if (spr.getPointer() == nullptr) {
|
||||
@@ -79,11 +80,12 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
|
||||
fs::File f_out = LittleFS.open(fileout, "w");
|
||||
|
||||
bool dither = true, rotated = false;
|
||||
bool dither = true;
|
||||
uint8_t rotate = imageParams.rotate;
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
|
||||
if (bufw > bufh && bufw!=400 && bufh!=300) {
|
||||
rotated = true;
|
||||
rotate = (rotate + 3) % 4;
|
||||
bufw = spr.height();
|
||||
bufh = spr.width();
|
||||
}
|
||||
@@ -105,6 +107,7 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
Serial.println("rendering with gray");
|
||||
}
|
||||
int num_colors = palette.size();
|
||||
if (imageParams.bpp == 1) num_colors = 2;
|
||||
Color color;
|
||||
Error *error_bufferold = new Error[bufw + 4];
|
||||
Error *error_buffernew = new Error[bufw + 4];
|
||||
@@ -113,10 +116,19 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
for (uint16_t y = 0; y < bufh; y++) {
|
||||
memset(error_buffernew, 0, bufw * sizeof(Error));
|
||||
for (uint16_t x = 0; x < bufw; x++) {
|
||||
if (rotated) {
|
||||
color = Color(spr.readPixel(bufh - 1 - y, x));
|
||||
} else {
|
||||
color = Color(spr.readPixel(x, y));
|
||||
switch (rotate) {
|
||||
case 0:
|
||||
color = Color(spr.readPixel(x, y));
|
||||
break;
|
||||
case 1:
|
||||
color = Color(spr.readPixel(y, bufw - 1 - x));
|
||||
break;
|
||||
case 2:
|
||||
color = Color(spr.readPixel(bufw - 1 - x, bufh - 1 - y));
|
||||
break;
|
||||
case 3:
|
||||
color = Color(spr.readPixel(bufh - 1 - y, x));
|
||||
break;
|
||||
}
|
||||
|
||||
int best_color_index = 0;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "commstructs.h"
|
||||
#include "serialap.h"
|
||||
#include "settings.h"
|
||||
#include "system.h"
|
||||
#include "tag_db.h"
|
||||
#include "udp.h"
|
||||
#include "web.h"
|
||||
@@ -98,6 +99,7 @@ void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* ds
|
||||
taginfo->len = len;
|
||||
taginfo->expectedNextCheckin = 0;
|
||||
taginfo->filename = String();
|
||||
taginfo->dataType = dataType;
|
||||
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
|
||||
|
||||
struct pendingData pending = {0};
|
||||
@@ -168,11 +170,11 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
|
||||
time_t now;
|
||||
time(&now);
|
||||
time_t last_midnight = now - now % (24 * 60 * 60) + 3 * 3600; // somewhere in the middle of the night
|
||||
if (taginfo->lastfullupdate < last_midnight || taginfo->hwType == SOLUM_29_UC8151) {
|
||||
if (taginfo->lastfullupdate < last_midnight || taginfo->hwType == SOLUM_29_UC8151 || taginfo->lut == 1) {
|
||||
lut = EPD_LUT_DEFAULT; // full update once a day
|
||||
taginfo->lastfullupdate = now;
|
||||
}
|
||||
if (taginfo->hasCustomLUT && taginfo->capabilities & CAPABILITY_SUPPORTS_CUSTOM_LUTS) {
|
||||
if (taginfo->hasCustomLUT && taginfo->capabilities & CAPABILITY_SUPPORTS_CUSTOM_LUTS && taginfo->lut != 1) {
|
||||
Serial.println("using custom LUT");
|
||||
lut = EPD_LUT_OTA;
|
||||
}
|
||||
@@ -190,16 +192,18 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
|
||||
time_t now;
|
||||
time(&now);
|
||||
taginfo->expectedNextCheckin = now + nextCheckin * 60 + 60;
|
||||
clearPending(taginfo);
|
||||
taginfo->filename = *filename;
|
||||
taginfo->len = filesize;
|
||||
clearPending(taginfo);
|
||||
taginfo->dataType = dataType;
|
||||
taginfo->pending = true;
|
||||
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
|
||||
} else {
|
||||
wsLog("firmware upload pending");
|
||||
clearPending(taginfo);
|
||||
taginfo->filename = *filename;
|
||||
taginfo->len = filesize;
|
||||
clearPending(taginfo);
|
||||
taginfo->dataType = dataType;
|
||||
taginfo->pending = true;
|
||||
}
|
||||
|
||||
@@ -272,9 +276,10 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
}
|
||||
|
||||
file.close();
|
||||
clearPending(taginfo);
|
||||
taginfo->filename = filename;
|
||||
taginfo->len = filesize;
|
||||
clearPending(taginfo);
|
||||
taginfo->dataType = pending->availdatainfo.dataType;
|
||||
taginfo->pending = true;
|
||||
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
|
||||
break;
|
||||
@@ -296,6 +301,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
taginfo->data = new uint8_t[len];
|
||||
WiFiClient* stream = http.getStreamPtr();
|
||||
stream->readBytes(taginfo->data, len);
|
||||
taginfo->dataType = pending->availdatainfo.dataType;
|
||||
taginfo->pending = true;
|
||||
taginfo->len = len;
|
||||
}
|
||||
@@ -334,7 +340,7 @@ void processBlockRequest(struct espBlockRequest* br) {
|
||||
// not cached. open file, cache the data
|
||||
fs::File file = LittleFS.open(taginfo->filename);
|
||||
if (!file) {
|
||||
Serial.print("Dunno how this happened... File pending but deleted in the meantime?\n");
|
||||
Serial.print("No current file. Canceling request\n");
|
||||
prepareCancelPending(br->src);
|
||||
return;
|
||||
}
|
||||
@@ -463,6 +469,23 @@ void processDataReq(struct espAvailDataReq* eadr, bool local) {
|
||||
taginfo->lastseen = now;
|
||||
|
||||
if (eadr->adr.lastPacketRSSI != 0) {
|
||||
if (eadr->adr.wakeupReason >= 0xF0) {
|
||||
if (!taginfo->pending) taginfo->nextupdate = 0;
|
||||
memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
|
||||
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
|
||||
|
||||
const char* reason = "";
|
||||
if (eadr->adr.wakeupReason == WAKEUP_REASON_FIRSTBOOT) reason = "Booting";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_NETWORK_SCAN) reason = "Network scan";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_WDT_RESET) reason = "Watchdog reset";
|
||||
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X %s", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0], reason);
|
||||
logLine(buffer);
|
||||
}
|
||||
if (taginfo->batteryMv != eadr->adr.batteryMv) {
|
||||
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X battery went from %.2fV to %.2fV", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0], static_cast<float>(taginfo->batteryMv) / 1000.0, static_cast<float>(eadr->adr.batteryMv) / 1000.0);
|
||||
logLine(buffer);
|
||||
}
|
||||
|
||||
taginfo->LQI = eadr->adr.lastPacketLQI;
|
||||
taginfo->hwType = eadr->adr.hwType;
|
||||
taginfo->RSSI = eadr->adr.lastPacketRSSI;
|
||||
@@ -471,11 +494,6 @@ void processDataReq(struct espAvailDataReq* eadr, bool local) {
|
||||
taginfo->hwType = eadr->adr.hwType;
|
||||
taginfo->wakeupReason = eadr->adr.wakeupReason;
|
||||
taginfo->capabilities = eadr->adr.capabilities;
|
||||
if (eadr->adr.wakeupReason >= 0xF0) {
|
||||
if (!taginfo->pending) taginfo->nextupdate = 0;
|
||||
memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
|
||||
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
if (local) {
|
||||
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X%02X%02X\n\0", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0]);
|
||||
|
||||
@@ -9,50 +9,35 @@
|
||||
#include "soc/soc.h"
|
||||
#endif
|
||||
|
||||
#ifdef SIMPLE_AP
|
||||
void simpleAPPower(bool state) {
|
||||
if (FLASHER_AP_POWER >= 0 && FLASHER_AP_POWER2 >= 0) {
|
||||
pinMode(FLASHER_AP_POWER, INPUT);
|
||||
pinMode(FLASHER_AP_POWER2, INPUT);
|
||||
digitalWrite(FLASHER_AP_POWER, state);
|
||||
digitalWrite(FLASHER_AP_POWER2, state);
|
||||
pinMode(FLASHER_AP_POWER, OUTPUT);
|
||||
pinMode(FLASHER_AP_POWER2, OUTPUT);
|
||||
void simpleAPPower(uint8_t* pin, uint8_t pincount, bool state) {
|
||||
for (uint8_t c = 0; c < pincount; c++) {
|
||||
pinMode(pin[c], INPUT);
|
||||
}
|
||||
for (uint8_t c = 0; c < pincount; c++) {
|
||||
#ifdef POWER_HIGH_SIDE_DRIVER
|
||||
digitalWrite(pin[c], !state);
|
||||
#else
|
||||
digitalWrite(pin[c], state);
|
||||
#endif
|
||||
}
|
||||
for (uint8_t c = 0; c < pincount; c++) {
|
||||
pinMode(pin[c], OUTPUT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENEPAPERLINK_NANO_AP_PCB
|
||||
void simpleAPPower(bool state) {
|
||||
if (FLASHER_AP_POWER >= 0 && FLASHER_AP_POWER2 >= 0 && FLASHER_AP_POWER3 >= 0 && FLASHER_AP_POWER4 >= 0) {
|
||||
pinMode(FLASHER_AP_POWER, INPUT);
|
||||
pinMode(FLASHER_AP_POWER2, INPUT);
|
||||
pinMode(FLASHER_AP_POWER3, INPUT);
|
||||
pinMode(FLASHER_AP_POWER4, INPUT);
|
||||
digitalWrite(FLASHER_AP_POWER, state);
|
||||
digitalWrite(FLASHER_AP_POWER2, state);
|
||||
digitalWrite(FLASHER_AP_POWER3, state);
|
||||
digitalWrite(FLASHER_AP_POWER4, state);
|
||||
pinMode(FLASHER_AP_POWER, OUTPUT);
|
||||
pinMode(FLASHER_AP_POWER2, OUTPUT);
|
||||
pinMode(FLASHER_AP_POWER3, OUTPUT);
|
||||
pinMode(FLASHER_AP_POWER4, OUTPUT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// On the OpenEPaperLink board, there is no in-rush current limiting. The tags that can be connected to the board can have significant capacity, which,
|
||||
// when drained if the board applies power, will cause the 3v3 rail to sag enough to reset the ESP32. This is obviously not great. To prevent this from happening,
|
||||
// we ramp up/down the voltage with PWM. Ramping down really is unnecessary, as the board has a resistor to dump the charge into.
|
||||
void rampTagPower(uint8_t pin, bool up) {
|
||||
void rampTagPower(uint8_t* pin, bool up) {
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
||||
#endif
|
||||
if (up) {
|
||||
ledcSetup(0, 152000, 8); // 141251 okay // 101251 okay
|
||||
ledcWrite(0, 254);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
ledcAttachPin(pin, 0);
|
||||
pinMode(pin, OUTPUT);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 254; c != 0xFF; c--) {
|
||||
ledcWrite(0, c);
|
||||
@@ -62,23 +47,54 @@ void rampTagPower(uint8_t pin, bool up) {
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
}
|
||||
digitalWrite(pin, LOW);
|
||||
ledcDetachPin(pin);
|
||||
digitalWrite(pin, LOW);
|
||||
digitalWrite(pin[0], LOW);
|
||||
ledcDetachPin(pin[0]);
|
||||
digitalWrite(pin[0], LOW);
|
||||
} else {
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, HIGH);
|
||||
ledcSetup(0, 152000, 8); // 141251 okay // 101251 okay
|
||||
ledcWrite(0, 0);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 0; c < 0xFF; c++) {
|
||||
ledcWrite(0, c);
|
||||
if (c > 250) {
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
}
|
||||
digitalWrite(pin[0], HIGH);
|
||||
ledcDetachPin(pin[0]);
|
||||
digitalWrite(pin[0], HIGH);
|
||||
}
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1);
|
||||
#endif
|
||||
#ifdef SIMPLE_AP
|
||||
simpleAPPower(false);
|
||||
delay(500);
|
||||
simpleAPPower(up);
|
||||
}
|
||||
|
||||
void powerControl(bool powerState, uint8_t* pin, uint8_t pincount) {
|
||||
if (pin[0] == -1) return;
|
||||
|
||||
#ifdef POWER_RAMPING
|
||||
if (powerState == true) {
|
||||
#ifdef POWER_HIGH_SIDE_DRIVER
|
||||
rampTagPower(pin, true);
|
||||
#else
|
||||
rampTagPower(pin, false);
|
||||
#endif
|
||||
#ifdef OPENEPAPERLINK_NANO_AP_PCB
|
||||
simpleAPPower(false);
|
||||
} else {
|
||||
pinMode(pin[0], OUTPUT);
|
||||
#ifdef POWER_HIGH_SIDE_DRIVER
|
||||
digitalWrite(pin[0], HIGH);
|
||||
#else
|
||||
digitalWrite(pin[0], LOW);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
simpleAPPower(pin, pincount, false);
|
||||
delay(500);
|
||||
simpleAPPower(up);
|
||||
simpleAPPower(pin, pincount, true);
|
||||
#endif
|
||||
}
|
||||
@@ -110,15 +110,18 @@ bool waitCmdReply() {
|
||||
}
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
int8_t APpowerPins[] = FLASHER_AP_POWER;
|
||||
#define AP_RESET_PIN FLASHER_AP_RESET
|
||||
#define AP_POWER_PIN FLASHER_AP_POWER
|
||||
#endif
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
|
||||
int8_t APpowerPins[] = FLASHER_EXT_POWER;
|
||||
#define AP_RESET_PIN FLASHER_EXT_RESET
|
||||
#define AP_POWER_PIN FLASHER_EXT_POWER
|
||||
#endif
|
||||
#if (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
|
||||
int8_t APpowerPins[] = FLASHER_ALT_POWER;
|
||||
#define AP_RESET_PIN FLASHER_ALT_RESET
|
||||
#define AP_POWER_PIN FLASHER_ALT_POWER
|
||||
#endif
|
||||
@@ -134,9 +137,9 @@ void APTagReset() {
|
||||
pinMode(AP_RESET_PIN, OUTPUT);
|
||||
digitalWrite(AP_RESET_PIN, LOW);
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
rampTagPower(AP_POWER_PIN, false);
|
||||
powerControl(false, (uint8_t*)APpowerPins, sizeof(APpowerPins));
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
rampTagPower(AP_POWER_PIN, true);
|
||||
powerControl(true, (uint8_t*)APpowerPins, sizeof(APpowerPins));
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
digitalWrite(AP_RESET_PIN, HIGH);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
@@ -538,7 +541,7 @@ void ShowAPInfo() {
|
||||
void notifySegmentedFlash() {
|
||||
sendAPSegmentedData(apInfo.mac, (String) "Fl ash", 0x0800, false, true);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
#if (FLASHER_AP_POWER == -1)
|
||||
#ifdef POWER_NO_SOFT_POWER
|
||||
sendAPSegmentedData(apInfo.mac, (String) "If done", 0x0800, false, true);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
sendAPSegmentedData(apInfo.mac, (String) "RE boot", 0x0800, false, true);
|
||||
@@ -547,7 +550,7 @@ void notifySegmentedFlash() {
|
||||
}
|
||||
void checkWaitPowerCycle() {
|
||||
// check if we should wait for a power cycle. If we do, try to inform the user the best we can, and hang.
|
||||
#if (FLASHER_AP_POWER == -1)
|
||||
#ifdef POWER_NO_SOFT_POWER
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_REQUIRED_POWER_CYCLE;
|
||||
// If we have no soft power control, we'll now wait until the device is power-cycled
|
||||
@@ -690,7 +693,7 @@ void APTask(void* parameter) {
|
||||
Serial.println("I wasn't able to connect to a ZBS (AP) tag.\n");
|
||||
Serial.printf("This could be the first time this AP is booted and the AP-tag may be unflashed. We'll try to flash it!\n");
|
||||
Serial.printf("If this tag was previously flashed succesfully but this message still shows up, there's probably something wrong with the serial connections.\n");
|
||||
Serial.printf("The build of this firmware expects an AP tag with RXD/TXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
Serial.printf("The build of this firmware expects an AP tag with TXD/RXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
Serial.println("Performing firmware flash in about 30 seconds!\n");
|
||||
flashCountDown(30);
|
||||
if (doAPFlash()) {
|
||||
@@ -708,10 +711,11 @@ void APTask(void* parameter) {
|
||||
Serial.printf("This generally means that the flasher connections (MISO/MOSI/CLK/RESET/CS) are okay,\n");
|
||||
Serial.printf("but we can't (yet) talk to the AP over serial lines. Verify the pins mentioned above.\n\n");
|
||||
|
||||
if (FLASHER_AP_POWER != -1) {
|
||||
Serial.printf("The firmware you're using expects soft power control over the AP tag; if it can't\n");
|
||||
Serial.printf("power-cycle the AP-tag using GPIO pin %d, this can cause this very same issue.\n", FLASHER_AP_POWER);
|
||||
}
|
||||
#ifndef POWER_NO_SOFT_POWER
|
||||
Serial.printf("The firmware you're using expects soft power control over the AP tag; if it can't\n");
|
||||
Serial.printf("power-cycle the AP-tag using GPIO pin %d, this can cause this very same issue.\n", APpowerPins[0]);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red);
|
||||
#endif
|
||||
@@ -729,17 +733,17 @@ void APTask(void* parameter) {
|
||||
Serial.println("Seems like you're running into some issues with the wiring, or (very small chance) the tag itself");
|
||||
Serial.println("This ESP32-build expects the following pins connected to the ZBS243:");
|
||||
Serial.println("--- ZBS243 based tag ESP32 ---");
|
||||
Serial.printf(" RXD ---------------- %02d\n", FLASHER_AP_RXD);
|
||||
Serial.printf(" TXD ---------------- %02d\n", FLASHER_AP_TXD);
|
||||
Serial.printf(" TXD ---------------- %02d\n", FLASHER_AP_RXD);
|
||||
Serial.printf(" RXD ---------------- %02d\n", FLASHER_AP_TXD);
|
||||
Serial.printf(" CS/SS ---------------- %02d\n", FLASHER_AP_SS);
|
||||
Serial.printf(" MOSI ---------------- %02d\n", FLASHER_AP_MOSI);
|
||||
Serial.printf(" MISO ---------------- %02d\n", FLASHER_AP_MISO);
|
||||
Serial.printf(" CLK ---------------- %02d\n", FLASHER_AP_CLK);
|
||||
Serial.printf(" RSET ---------------- %02d\n", FLASHER_AP_RESET);
|
||||
#if (FLASHER_AP_POWER == -1)
|
||||
#ifdef POWER_NO_SOFT_POWER
|
||||
Serial.printf("Your firmware is configured without soft power control. This means you'll have to manually power-cycle the tag after flashing.\n");
|
||||
#else
|
||||
Serial.printf(" POWER ---------------- %02d\n", FLASHER_AP_POWER);
|
||||
Serial.printf(" POWER ---------------- %02d\n", APpowerPins[0]);
|
||||
#endif
|
||||
Serial.println("Please verify your wiring and try again!");
|
||||
}
|
||||
|
||||
80
ESP32_AP-Flasher/src/system.cpp
Normal file
80
ESP32_AP-Flasher/src/system.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "system.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
|
||||
#include "LittleFS.h"
|
||||
|
||||
void init_time() {
|
||||
struct tm timeinfo;
|
||||
while (true) {
|
||||
if (!getLocalTime(&timeinfo)) {
|
||||
Serial.println("Waiting for valid time from NTP-server");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void logLine(char* buffer) {
|
||||
logLine(String(buffer));
|
||||
}
|
||||
|
||||
void logLine(String text) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
char timeStr[24];
|
||||
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S ", localtime(&now));
|
||||
|
||||
File logFile = LittleFS.open("/log.txt", "a");
|
||||
if (logFile) {
|
||||
logFile.print(timeStr);
|
||||
logFile.println(text);
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void logStartUp() {
|
||||
esp_reset_reason_t resetReason = esp_reset_reason();
|
||||
|
||||
String logEntry = "Reboot. Reason: ";
|
||||
switch (resetReason) {
|
||||
case ESP_RST_POWERON:
|
||||
logEntry += "Power-on";
|
||||
break;
|
||||
case ESP_RST_EXT:
|
||||
logEntry += "External";
|
||||
break;
|
||||
case ESP_RST_SW:
|
||||
logEntry += "Software";
|
||||
break;
|
||||
case ESP_RST_PANIC:
|
||||
logEntry += "Panic";
|
||||
break;
|
||||
case ESP_RST_INT_WDT:
|
||||
logEntry += "Watchdog";
|
||||
break;
|
||||
case ESP_RST_TASK_WDT:
|
||||
logEntry += "Task Watchdog";
|
||||
break;
|
||||
case ESP_RST_WDT:
|
||||
logEntry += "Other Watchdog";
|
||||
break;
|
||||
case ESP_RST_DEEPSLEEP:
|
||||
logEntry += "Deep Sleep";
|
||||
break;
|
||||
case ESP_RST_BROWNOUT:
|
||||
logEntry += "Brownout";
|
||||
break;
|
||||
case ESP_RST_SDIO:
|
||||
logEntry += "SDIO";
|
||||
break;
|
||||
default:
|
||||
logEntry += "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
logLine(logEntry);
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
std::vector<tagRecord*> tagDB;
|
||||
|
||||
Config config;
|
||||
SemaphoreHandle_t tagDBOwner;
|
||||
// SemaphoreHandle_t tagDBOwner;
|
||||
|
||||
tagRecord* tagRecord::findByMAC(uint8_t mac[8]) {
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
@@ -117,6 +117,8 @@ void fillNode(JsonObject &tag, tagRecord* &taginfo) {
|
||||
tag["capabilities"] = taginfo->capabilities;
|
||||
tag["modecfgjson"] = taginfo->modeConfigJson;
|
||||
tag["isexternal"] = taginfo->isExternal;
|
||||
tag["rotate"] = taginfo->rotate;
|
||||
tag["lut"] = taginfo->lut;
|
||||
}
|
||||
|
||||
void saveDB(String filename) {
|
||||
@@ -210,6 +212,8 @@ void loadDB(String filename) {
|
||||
taginfo->capabilities = tag["capabilities"];
|
||||
taginfo->modeConfigJson = tag["modecfgjson"].as<String>();
|
||||
taginfo->isExternal = tag["isexternal"].as<bool>();
|
||||
taginfo->rotate = tag["rotate"] | 0;
|
||||
taginfo->lut = tag["lut"] | 0;
|
||||
}
|
||||
} else {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
@@ -251,6 +255,7 @@ uint8_t getTagCount() {
|
||||
}
|
||||
|
||||
void clearPending(tagRecord* taginfo) {
|
||||
taginfo->filename = String();
|
||||
if (taginfo->data != nullptr) {
|
||||
free(taginfo->data);
|
||||
taginfo->data = nullptr;
|
||||
@@ -260,13 +265,14 @@ void clearPending(tagRecord* taginfo) {
|
||||
|
||||
void initAPconfig() {
|
||||
LittleFS.begin(true);
|
||||
DynamicJsonDocument APconfig(150);
|
||||
DynamicJsonDocument APconfig(500);
|
||||
File configFile = LittleFS.open("/current/apconfig.json", "r");
|
||||
if (configFile) {
|
||||
DeserializationError error = deserializeJson(APconfig, configFile);
|
||||
if (error) {
|
||||
configFile.close();
|
||||
Serial.println("failed to read apconfig.json. Using default config");
|
||||
Serial.println(error.c_str());
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
@@ -280,7 +286,7 @@ void initAPconfig() {
|
||||
|
||||
void saveAPconfig() {
|
||||
fs::File configFile = LittleFS.open("/current/apconfig.json", "w");
|
||||
DynamicJsonDocument APconfig(150);
|
||||
DynamicJsonDocument APconfig(500);
|
||||
APconfig["channel"] = config.channel;
|
||||
APconfig["alias"] = config.alias;
|
||||
APconfig["led"] = config.led;
|
||||
|
||||
@@ -36,6 +36,12 @@ void enterConsoleMode() {
|
||||
xTaskCreate(consoleTask, "consoleTask", 10000, NULL, 2, &consoleTaskHandle);
|
||||
}
|
||||
|
||||
int8_t powerPins[] = FLASHER_AP_POWER;
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
int8_t powerPins2[] = FLASHER_EXT_POWER;
|
||||
int8_t powerPins3[] = FLASHER_ALT_POWER;
|
||||
#endif
|
||||
|
||||
void sendFlasherAnswer(uint8_t answer_cmd, uint8_t* ans_buff, uint8_t len) {
|
||||
uint8_t* answer_buffer = (uint8_t*)calloc(2 + 2 + len + 2, 1);
|
||||
if (answer_buffer == nullptr) return;
|
||||
@@ -259,16 +265,17 @@ void processFlasherCommand(struct flasherCommand* cmd) {
|
||||
spi_speed = 8000000;
|
||||
}
|
||||
curspeed = spi_speed;
|
||||
|
||||
if (cmd->data[0] & 2) {
|
||||
temp_buff[0] = zbs->begin(FLASHER_AP_SS, FLASHER_AP_CLK, FLASHER_AP_MOSI, FLASHER_AP_MISO, FLASHER_AP_RESET, FLASHER_AP_POWER, spi_speed);
|
||||
temp_buff[0] = zbs->begin(FLASHER_AP_SS, FLASHER_AP_CLK, FLASHER_AP_MOSI, FLASHER_AP_MISO, FLASHER_AP_RESET, (uint8_t*)powerPins, spi_speed);
|
||||
} else if (cmd->data[0] & 4) {
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
temp_buff[0] = zbs->begin(FLASHER_ALT_SS, FLASHER_ALT_CLK, FLASHER_ALT_MOSI, FLASHER_ALT_MISO, FLASHER_ALT_RESET, 255, spi_speed);
|
||||
#endif
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
temp_buff[0] = zbs->begin(FLASHER_ALT_SS, FLASHER_ALT_CLK, FLASHER_ALT_MOSI, FLASHER_ALT_MISO, FLASHER_ALT_RESET, (uint8_t*)powerPins3, spi_speed);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
temp_buff[0] = zbs->begin(FLASHER_EXT_SS, FLASHER_EXT_CLK, FLASHER_EXT_MOSI, FLASHER_EXT_MISO, FLASHER_EXT_RESET, FLASHER_EXT_POWER, spi_speed);
|
||||
#endif
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
temp_buff[0] = zbs->begin(FLASHER_EXT_SS, FLASHER_EXT_CLK, FLASHER_EXT_MOSI, FLASHER_EXT_MISO, FLASHER_EXT_RESET, (uint8_t*)powerPins2, spi_speed);
|
||||
#endif
|
||||
}
|
||||
sendFlasherAnswer(cmd->command, temp_buff, 1);
|
||||
break;
|
||||
|
||||
@@ -319,6 +319,12 @@ void init_web() {
|
||||
taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value();
|
||||
taginfo->contentMode = atoi(request->getParam("contentmode", true)->value().c_str());
|
||||
taginfo->nextupdate = 0;
|
||||
if (request->hasParam("rotate", true)) {
|
||||
taginfo->rotate = atoi(request->getParam("rotate", true)->value().c_str());
|
||||
}
|
||||
if (request->hasParam("lut", true)) {
|
||||
taginfo->lut = atoi(request->getParam("lut", true)->value().c_str());
|
||||
}
|
||||
// memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
|
||||
// memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
|
||||
wsSendTaginfo(mac, SYNC_USERCFG);
|
||||
@@ -332,20 +338,33 @@ void init_web() {
|
||||
request->send(200, "text/plain", "Ok, saved");
|
||||
});
|
||||
|
||||
server.on("/delete_cfg", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
if (request->hasParam("mac", true)) {
|
||||
String dst = request->getParam("mac", true)->value();
|
||||
server.on("/tag_cmd", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
if (request->hasParam("mac", true) && request->hasParam("cmd", true)) {
|
||||
uint8_t mac[8];
|
||||
if (hex2mac(dst, mac)) {
|
||||
wsSendTaginfo(mac, SYNC_DELETE);
|
||||
if (deleteRecord(mac)) {
|
||||
request->send(200, "text/plain", "Ok, deleted");
|
||||
if (hex2mac(request->getParam("mac", true)->value(), mac)) {
|
||||
tagRecord *taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(mac);
|
||||
if (taginfo != nullptr) {
|
||||
const char *cmdValue = request->getParam("cmd", true)->value().c_str();
|
||||
if (strcmp(cmdValue, "del") == 0) {
|
||||
wsSendTaginfo(mac, SYNC_DELETE);
|
||||
deleteRecord(mac);
|
||||
}
|
||||
if (strcmp(cmdValue, "clear") == 0) {
|
||||
clearPending(taginfo);
|
||||
memcpy(taginfo->md5pending, taginfo->md5, sizeof(taginfo->md5pending));
|
||||
wsSendTaginfo(mac, SYNC_TAGSTATUS);
|
||||
}
|
||||
if (strcmp(cmdValue, "refresh") == 0) {
|
||||
updateContent(mac);
|
||||
}
|
||||
request->send(200, "text/plain", "Ok, done");
|
||||
} else {
|
||||
request->send(200, "text/plain", "Error while saving: mac not found");
|
||||
request->send(200, "text/plain", "Error: mac not found");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
request->send(500, "text/plain", "no mac");
|
||||
request->send(500, "text/plain", "param error");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "powermgt.h"
|
||||
|
||||
uint8_t ZBS_interface::begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t POWER, uint32_t spi_speed) {
|
||||
uint8_t ZBS_interface::begin(uint8_t SS, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t RESET, uint8_t* POWER, uint8_t powerPins, uint32_t spi_speed) {
|
||||
_SS_PIN = SS;
|
||||
_CLK_PIN = CLK;
|
||||
_MOSI_PIN = MOSI;
|
||||
@@ -49,9 +49,7 @@ ZBS_interface::~ZBS_interface() {
|
||||
if(spi)delete spi;
|
||||
}
|
||||
void ZBS_interface::set_power(uint8_t state) {
|
||||
if (_POWER_PIN != 255) {
|
||||
rampTagPower(_POWER_PIN, state);
|
||||
}
|
||||
powerControl(state, _POWER_PIN, _POWER_PINS);
|
||||
}
|
||||
|
||||
void ZBS_interface::enable_debug() {
|
||||
|
||||
Reference in New Issue
Block a user