Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/LEDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
#define M_PI 3.14159265f
#endif

#if defined(BOARD_ESP32_S3)
#if defined(BOARD_S3_DEVKITC)
LEDManager::LEDManager()
: _initialized(false), _taskStarted(false), _pixel(1, 0, NEO_GRB + NEO_KHZ800) {}
#elif defined(BOARD_ESP32_S3)
LEDManager::LEDManager()
: _initialized(false), _taskStarted(false), _pixel(1, 0, NEO_RGB + NEO_KHZ800) {}
#else
Expand All @@ -21,7 +24,9 @@ LEDManager::LEDManager()
#endif

void LEDManager::begin(uint8_t pin) {
#if defined(BOARD_ESP32_S3)
#if defined(BOARD_S3_DEVKITC)
_pixel.updateType(NEO_GRB + NEO_KHZ800);
#elif defined(BOARD_ESP32_S3)
_pixel.updateType(NEO_RGB + NEO_KHZ800);
#else
_pixel.updateType(NEO_GRBW + NEO_KHZ800);
Expand Down
170 changes: 19 additions & 151 deletions src/OpenPrintTagWriterHTML.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,13 @@ const char OPENPRINTTAG_WRITER_HTML[] PROGMEM = R"rawliteral(

<script src="/js/shared.js"></script>
<script>
var createView = document.getElementById('createView');
var statusView = document.getElementById('statusView');
var writerForm = document.getElementById('writerForm');

var materialTypeEl = document.getElementById('material_type');
var materialSearchEl = document.getElementById('material_search');
var materialListEl = document.getElementById('material-list');
var materialNameEl = document.getElementById('material_name');

var backBtn = document.getElementById('backBtn');
var anotherBtn = document.getElementById('anotherBtn');

var STEP_IDS = ['step-wait', 'step-detect', 'step-format', 'step-write', 'step-verify'];

syncColorPicker('colorPicker', 'colorHex');

// Pre-fill from scanned tag if present
Expand Down Expand Up @@ -364,16 +357,9 @@ const char OPENPRINTTAG_WRITER_HTML[] PROGMEM = R"rawliteral(
});
});

function showStatusView() {
createView.classList.add('hidden');
statusView.classList.remove('hidden');
backBtn.classList.add('hidden');
anotherBtn.classList.add('hidden');
}

function showCreateView() {
statusView.classList.add('hidden');
createView.classList.remove('hidden');
document.getElementById('statusView').classList.add('hidden');
document.getElementById('createView').classList.remove('hidden');
}

function syncMaterialNameFromSelection() {
Expand Down Expand Up @@ -478,95 +464,6 @@ const char OPENPRINTTAG_WRITER_HTML[] PROGMEM = R"rawliteral(
return checks.length > 0 && checks.every(Boolean);
}

async function writeFlow() {
resetAllSteps(STEP_IDS);
showStatusView();

try {
setStepState('step-wait', 'active');
setBanner('statusBanner', 'Waiting for tag\u2026');
setResult('resultBox', 'Place and hold the tag on the scanner.', '');

var presentStatus = null;
var deadline = Date.now() + 8000;
while (Date.now() < deadline) {
var s = await api('/api/status');
if (s.present) { presentStatus = s; break; }
await sleep(500);
}
if (!presentStatus) {
setStepState('step-wait', 'error');
throw new Error('No tag detected. Place the tag on the scanner and try again.');
}
setStepState('step-wait', 'done');

setStepState('step-detect', 'active');
setBanner('statusBanner', 'Tag detected.');
setResult('resultBox', 'UID: ' + (presentStatus.uid || 'Unknown'), '');
await sleep(250);
setStepState('step-detect', 'done');

var payload = buildPayload(presentStatus.uid);

if (presentStatus.tag_data_valid === false) {
setStepState('step-format', 'active');
setBanner('statusBanner', 'Formatting blank tag\u2026');
setResult('resultBox', 'Blank tag detected. Initializing NDEF structure.', '');
await api('/api/format-tag', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ uid: presentStatus.uid })
});
await sleep(1000);
setStepState('step-format', 'done');
} else {
setStepState('step-format', 'done');
}

setStepState('step-write', 'active');
setBanner('statusBanner', 'Writing data\u2026');
setResult('resultBox', 'Sending OpenPrintTag payload to scanner.', '');
await api('/api/write-tag', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
setStepState('step-write', 'done');

setStepState('step-verify', 'active');
setBanner('statusBanner', 'Verifying write\u2026');
setResult('resultBox', 'Reading tag back to confirm fields match.', '');

var verifyDeadline = Date.now() + 15000;
while (Date.now() < verifyDeadline) {
await sleep(500);
var status = await api('/api/status');
if (status.present && valuesMatch(status, payload)) {
setStepState('step-verify', 'done');
setBanner('statusBanner', 'Write successful.');
setResult('resultBox', 'OpenPrintTag data verified successfully.', 'success');
backBtn.classList.remove('hidden');
anotherBtn.classList.remove('hidden');
return;
}
}

setStepState('step-verify', 'error');
throw new Error('Write timed out. Keep the tag on the scanner and try again.');
} catch (err) {
var msg = err && err.message ? err.message : 'Write failed';
setBanner('statusBanner', 'Write failed.');
setResult('resultBox', msg, 'error');

STEP_IDS.forEach(function(id) {
var el = document.getElementById(id);
if (el && el.classList.contains('active')) setStepState(id, 'error');
});

backBtn.classList.remove('hidden');
}
}

materialSearchEl.addEventListener('input', syncMaterialNameFromSelection);

materialNameEl.addEventListener('input', function() {
Expand All @@ -583,14 +480,22 @@ const char OPENPRINTTAG_WRITER_HTML[] PROGMEM = R"rawliteral(
}, 0);
});

document.getElementById('backBtn').addEventListener('click', showCreateView);
document.getElementById('anotherBtn').addEventListener('click', showCreateView);

writerForm.addEventListener('submit', function(e) {
e.preventDefault();
writeFlow();
sharedWriteFlow({
stepIds: ['step-wait', 'step-detect', 'step-format', 'step-write', 'step-verify'],
endpoint: '/api/write-tag',
formatName: 'OpenPrintTag',
buildPayload: buildPayload,
verify: function(status, payload) { return valuesMatch(status, payload); },
formatCheck: function(status) { return status.tag_data_valid === false; },
formatEndpoint: '/api/format-tag'
});
});

backBtn.addEventListener('click', showCreateView);
anotherBtn.addEventListener('click', showCreateView);

syncMaterialNameFromSelection();

(async function init() {
Expand All @@ -616,48 +521,11 @@ const char OPENPRINTTAG_WRITER_HTML[] PROGMEM = R"rawliteral(
spoolman_id: 'spoolman_id'
});

var readBtn = document.getElementById('readBtn');
var writeBtn = document.getElementById('writeBtn');
var readWaiting = false;

function setReadWaiting(active) {
readWaiting = active;
writeBtn.disabled = active;
if (active) {
readBtn.textContent = 'Cancel';
readBtn.onclick = cancelRead;
document.getElementById('readPrompt').classList.remove('hidden');
} else {
readBtn.textContent = 'Read';
readBtn.onclick = startRead;
document.getElementById('readPrompt').classList.add('hidden');
}
}

function cancelRead() {
readWaiting = false;
setReadWaiting(false);
}

async function startRead() {
setReadWaiting(true);
var deadline = Date.now() + 30000;
while (readWaiting && Date.now() < deadline) {
try {
var status = await fetch('/api/status').then(r => r.json());
if (status.present && status.tag_kind === 'OpenPrintTag') {
prefillFromStatus(status);
break;
} else if (status.present) {
break; // wrong format
}
} catch(e) {}
await new Promise(r => setTimeout(r, 500));
}
setReadWaiting(false);
}

readBtn.onclick = startRead;
setupReadButton({
expectedKind: 'OpenPrintTag',
wrongKindMsg: 'wrong format \u2014 expected OpenPrintTag',
fillForm: function(status) { prefillFromStatus(status); }
});
</script>
</body>
</html>
Expand Down
Loading