diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..503c1b2
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,218 @@
+
+
+
+
+
+ LAP
+
+
+
+
+
+
+ Zeus WPI – LED-Automaten-Programmatie
+
+ Voor deze applicatie is helaas JavaScript vereist.
+
+
+
Configuratie
+ Je schuilnaam:
+
+
+
+
LED-strip
+
+ LED-strip wordt geladen...
+
+
+
+
+
Segmentcontrole
+
+ Segment
+ van LED
+ tot
+
+
Toegewezen aan:
+
+
+
+
+
Programma
+
Dit segment is niet van jou. Je kunt de code enkel bekijken.
+
+
+
+
De code wordt niet bestendig bewaard. Sla ze zelf op op je computer. Gebruik dit veld bij voorkeur enkel om naar te kopiëren-en-plakken.
+
+
+
Programmeer je segment in Lua. Voor je code lijkt het alsof je LED 0 tot x hebt. Extra beschikbare functies:
+
+ - led(led_nr, r, g, b)
+ - Stel LED led_nr in op de kleur met gegeven RGB-waarden (0–255)
+ - ledamount(something, probably)
+ - Uhh
+ - delay(ms)
+ - Wacht gedurende ms milliseconden
+ - waitframes(frames)
+ - Wacht gedurende frames frames
+ - print(message)
+ - Stuur message naar de console
+
+
+
+
+
+
+
+
+
diff --git a/frontend/main.js b/frontend/main.js
new file mode 100644
index 0000000..a4c9779
--- /dev/null
+++ b/frontend/main.js
@@ -0,0 +1,231 @@
+var ledStripControl = (function() {
+ "use strict";
+
+ var HOST = "http://localhost:8080";
+
+ var segments = null;
+ var activeSegmentId = null;
+ var us = null;
+
+ function xhr(url, method, data, callback) {
+ var oReq = new XMLHttpRequest();
+
+ if (callback) {
+ function reqListener() {
+ var json = null;
+ try { json = JSON.parse(this.responseText); } catch(e) {}
+ callback(json);
+ }
+ oReq.addEventListener("load", reqListener);
+ }
+
+ oReq.open(method, url);
+ oReq.send(data);
+ }
+
+ function getJson(url, callback) {
+ xhr(url, "GET", "", callback);
+ }
+ function putJson(url, data, callback) {
+ xhr(url, "PUT", JSON.stringify(data), callback);
+ }
+
+ function updateUs() {
+ us = document.getElementById("us").value;
+ showSegments();
+ }
+ updateUs();
+
+ function saveAndShowSegments(segs) {
+ segments = {};
+ for (var i in segs) {
+ segments[segs[i].id] = segs[i];
+ }
+ showSegments();
+ }
+
+ function fetchSegments() {
+ getJson(HOST + "/api/segments.json", saveAndShowSegments);
+ }
+
+ function activateSegment(segment) {
+ activeSegmentId = segment.id;
+ getJson(HOST + "/api/segments.json", saveAndShowSegments);
+ showSegments();
+ document.getElementById("segment-control").style.display = "block";
+ }
+
+ function repeatString(text, amount) {
+ var result = "";
+ for (var i = 0; i < amount; i++) {
+ result += text;
+ }
+ return result;
+ }
+
+ function showSegmentEventListener(e) {
+ if (e.currentTarget.dataset["segment"] !== "true") return;
+
+ var id = e.currentTarget.dataset["id"];
+ activateSegment(segments[id]);
+ e.stopPropagation();
+ }
+ function showOwnerEventListener(e) {
+ if (e.currentTarget.dataset["segment"] !== "true") return;
+
+ var owner = e.currentTarget.dataset["owner"];
+ if (owner) {
+ document.getElementById("owner_label").innerText = owner;
+ } else {
+ document.getElementById("owner_label").innerHTML = "Vrij";
+ }
+ document.getElementById("owner_label").style.display = "block";
+ document.getElementById("owner_label").style.left = (e.currentTarget.clientWidth/2 + e.currentTarget.offsetLeft - document.getElementById("owner_label").clientWidth/2) + "px";
+ document.getElementById("owner_label").style.top = (e.currentTarget.offsetTop - document.getElementById("owner_label").clientHeight - 2) + "px";
+ e.stopPropagation();
+ }
+ function hideOwnerEventListener(e) {
+ if (e.currentTarget.dataset["segment"] !== "true") return;
+
+ document.getElementById("owner_label").innerHTML = "";
+ document.getElementById("owner_label").style.display = "none";
+ }
+
+ function updatePublishButton() {
+ var activeSegment = activeSegmentId !== null ? segments[activeSegmentId] : null;
+ if (document.getElementById("lua_editor").value == activeSegment.code) {
+ document.getElementById("publish-button").innerText = "Gepubliceerd";
+ document.getElementById("publish-button").setAttribute("disabled", "disabled");
+ } else {
+ document.getElementById("publish-button").innerText = "Publiceren";
+ document.getElementById("publish-button").removeAttribute("disabled");
+ }
+ }
+
+ function showSegments() {
+ var segmentsContainer = document.getElementById("segments");
+ segmentsContainer.innerHTML = "";
+
+ var prevSegEnd = 0;
+ if (segments !== null) for (var i in segments) {
+ if (!segments.hasOwnProperty(i)) continue;
+ var seg = segments[i];
+ var color = seg.owner === "" ? "#555" : seg.owner === us ? "#050" : "#700";
+
+ var unsegmented = parseFloat(seg.begin) - prevSegEnd;
+ if (unsegmented > 0) {
+ var unsegmented_el = document.createElement("span");
+ unsegmented_el.className = "unsegmented";
+ unsegmented_el.innerHTML = repeatString("", unsegmented);
+ segmentsContainer.append(unsegmented_el);
+ }
+
+ var rect = document.createElement("a");
+ rect.className = seg.id === activeSegmentId ? "active segment" : "segment";
+ rect.style.backgroundColor = color;
+ rect.id = "segment" + seg.id;
+ rect.href = "#segment" + seg.id;
+ rect.dataset["segment"] = "true";
+ rect.dataset["owner"] = seg.owner;
+ rect.dataset["id"] = seg.id;
+ rect.addEventListener("click", showSegmentEventListener);
+ rect.addEventListener("focus", showOwnerEventListener);
+ rect.addEventListener("blur", hideOwnerEventListener);
+ rect.addEventListener("mouseover", showOwnerEventListener);
+ rect.addEventListener("mouseout", hideOwnerEventListener);
+ rect.innerHTML = repeatString("", seg.length);
+ segmentsContainer.appendChild(rect);
+
+ prevSegEnd = seg.begin + seg.length;
+ }
+
+ var activeSegment = activeSegmentId !== null ? segments[activeSegmentId] : null;
+ if (activeSegment !== null) {
+ document.getElementById("active_segment_id").innerText = activeSegmentId;
+ document.getElementById("active_segment_begin").innerText = activeSegment.begin;
+ document.getElementById("active_segment_end").innerText = activeSegment.begin + activeSegment.length - 1;
+ document.getElementById("active_segment_last_virtual").innerText = activeSegment.length - 1;
+
+ updatePublishButton();
+
+ document.getElementById("lua_editor").value = activeSegment.code;
+
+ if (activeSegment.owner !== "" && activeSegment.owner === us) {
+ document.getElementById("release_button").style.display = "";
+ document.getElementById("release_button").innerText = "Onteigen";
+ document.getElementById("release_button").removeAttribute("disabled");
+
+ document.getElementById("lua_editor").removeAttribute("disabled");
+ document.getElementById("not-your-own").style.display = "none";
+ document.getElementById("program-controls").style.display = "block";
+ document.getElementById("program-instructions").style.display = "block";
+ } else {
+ document.getElementById("release_button").style.display = "none";
+
+ document.getElementById("lua_editor").setAttribute("disabled", "disabled");
+ document.getElementById("not-your-own").style.display = "block";
+ document.getElementById("program-controls").style.display = "none";
+ document.getElementById("program-instructions").style.display = "none";
+ }
+
+ if (activeSegment.owner !== "") {
+ document.getElementById("active_segment_owner").innerText = activeSegment.owner;
+ document.getElementById("claim_button").style.display = "none";
+
+ document.getElementById("program").style.display = "block";
+ } else {
+ document.getElementById("active_segment_owner").innerText = "nog niemand";
+ document.getElementById("claim_button").style.display = "";
+ document.getElementById("claim_button").innerText = "Eigen je toe";
+ document.getElementById("claim_button").removeAttribute("disabled");
+
+ document.getElementById("program").style.display = "none";
+ }
+ }
+ }
+
+ document.getElementById("claim_button").addEventListener("click", function() {
+ document.getElementById("claim_button").innerText = "Bezig met toe-eigenen...";
+ document.getElementById("claim_button").setAttribute("disabled", "disabled");
+ var activeSegment = segments[activeSegmentId];
+ if (!activeSegment) { throw new Error("Trying to claim segment but no segment active"); }
+ putJson(HOST + "/api/code.json", {
+ "id": activeSegmentId,
+ "owner": us,
+ "code": activeSegment.code
+ }, fetchSegments);
+ });
+
+ document.getElementById("release_button").addEventListener("click", function() {
+ document.getElementById("release_button").innerText = "Bezig met onteigenen...";
+ document.getElementById("release_button").setAttribute("disabled", "disabled");
+ var activeSegment = segments[activeSegmentId];
+ if (!activeSegment) { throw new Error("Trying to release segment but no segment active"); }
+ putJson(HOST + "/api/code.json", {
+ "id": activeSegmentId,
+ "owner": "",
+ "code": activeSegment.code
+ }, fetchSegments);
+ });
+
+ document.getElementById("publish-button").addEventListener("click", function() {
+ document.getElementById("publish-button").innerText = "Bezig met publiceren...";
+ document.getElementById("publish-button").setAttribute("disabled", "disabled");
+ var activeSegment = segments[activeSegmentId];
+ if (!activeSegment) { throw new Error("Trying to update code of segment but no segment active"); }
+ putJson(HOST + "/api/code.json", {
+ "id": activeSegmentId,
+ "owner": activeSegment.owner,
+ "code": document.getElementById("lua_editor").value
+ }, fetchSegments);
+ });
+
+ document.getElementById("lua_editor").addEventListener("keyup", updatePublishButton);
+ document.getElementById("lua_editor").addEventListener("change", updatePublishButton);
+
+ fetchSegments();
+
+ return {
+ updateUs: updateUs,
+ };
+})();
diff --git a/main/main.cpp b/main/main.cpp
index 4810696..10508c9 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -280,6 +280,8 @@ int main(int argc, char** argv)
}
svr.Get("/api/segments.json", [](const httplib::Request &, httplib::Response &res) {
+ res.set_header("Access-Control-Allow-Origin", "*");
+ res.set_header("Access-Control-Allow-Methods", "GET");
json j;
int i = 0;
for (LedSegment* ledsegment : ledsegments) {
@@ -296,6 +298,8 @@ int main(int argc, char** argv)
});
svr.Put("/api/code.json", [](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
+ res.set_header("Access-Control-Allow-Origin", "*");
+ res.set_header("Access-Control-Allow-Methods", "PUT");
if (req.is_multipart_form_data()) {
res.set_content("No multipart forms allowed", "text/plain");
return true;
@@ -319,6 +323,12 @@ int main(int argc, char** argv)
return true;
});
+ svr.Options("/api/code.json", [](const httplib::Request &req, httplib::Response &res) {
+ res.set_header("Access-Control-Allow-Origin", "*");
+ res.set_header("Access-Control-Allow-Methods", "PUT");
+ return true;
+ });
+
std::thread httpserverthread(starthttpserver);
ws2811_return_t ret;
@@ -339,4 +349,4 @@ int main(int argc, char** argv)
ws2811_render(&ledstring);
std::this_thread::sleep_for(std::chrono::milliseconds(frametime));
}
-}
\ No newline at end of file
+}
diff --git a/submit.py b/submit.py
old mode 100644
new mode 100755
index 1456c6b..7af2969
--- a/submit.py
+++ b/submit.py
@@ -1,10 +1,12 @@
+#!/usr/bin/env python3
+
+import os
import json
import requests
import time
-
-
+SERVER = os.getenv("LEDSTRIP_SERVER", "http://10.1.0.212:8080")
for i in range(10):
@@ -13,11 +15,12 @@ for i in range(10):
c = codefile.read()
except:
continue
- j = {
+
+ payload = {
"code": c,
"owner": "j",
"id": i
}
- r = requests.put('http://10.1.0.212:8080/api/code.json', json=j)
+ r = requests.put(SERVER + '/api/code.json', json=payload)
print(r)
- print(r.text)
\ No newline at end of file
+ print(r.text)