joa dateien geadded
This commit is contained in:
parent
8cda43f92f
commit
0788b8eafc
|
@ -0,0 +1,15 @@
|
||||||
|
# create_map
|
||||||
|
Dieses kleine Repo beinhaltet ein Pythonskript welches aus dem Spacedirectory
|
||||||
|
spaces auswählt und sie dann 1. auf einer SVG-Karte darstellt die man dann
|
||||||
|
schön Lasercuttern kann und 2. in eine conf.yml tut die dann vom
|
||||||
|
spacepanel_aggregator genutzt werden kann.
|
||||||
|
|
||||||
|
Wenn ich meinen Code noch halbwegs richtig verstehe läuft das Programm
|
||||||
|
folgendermaßen:
|
||||||
|
|
||||||
|
1. Alle Spaces aus dem Spacedirectory runterladen
|
||||||
|
2. Check auf Erreichbarkeit des API Endpoints
|
||||||
|
3. Im API-Output checken ob der Doorstatus sinnvolle Dinge ausgibt
|
||||||
|
4. Checken ob der Space in Germany liegt
|
||||||
|
5. Spaces die zu nah aneinander liegen werden automatically gemerged (zum
|
||||||
|
Beispiel in Berlin oder Hamburg)
|
|
@ -0,0 +1,142 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import pickle
|
||||||
|
import os.path
|
||||||
|
import svgwrite
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
import concurrent.futures
|
||||||
|
|
||||||
|
URL = "https://directory.spaceapi.io/"
|
||||||
|
NORTHERNMOST = 55.05
|
||||||
|
EASTERNMOST = 15.033333
|
||||||
|
SOUTHERNMOST = 47.270108
|
||||||
|
WESTERNMOST = 5.866667
|
||||||
|
threshold = 0.10
|
||||||
|
YSPAN = NORTHERNMOST - SOUTHERNMOST
|
||||||
|
XSPAN = EASTERNMOST - WESTERNMOST
|
||||||
|
locations = {}
|
||||||
|
ignorelist = ["Chaostreff Salzburg", "DevLoL", "CCC Basel", "Chaostreff Zürich",
|
||||||
|
"ChaosStuff", "Level2", "Bastli", "Maakplek", "TkkrLab", "Hack42",
|
||||||
|
"Hackerspace Nijmegen", "TDvenlo", "ACKspace"]
|
||||||
|
|
||||||
|
|
||||||
|
def dist(n1, n2):
|
||||||
|
y = n1[0] - n2[0]
|
||||||
|
x = n1[1] - n2[1]
|
||||||
|
return math.sqrt(math.pow(x, 2) + math.pow(y, 2))
|
||||||
|
|
||||||
|
|
||||||
|
def conflict(targetlist, node):
|
||||||
|
returner = None
|
||||||
|
for element in targetlist:
|
||||||
|
if dist(node, targetlist[element]) < threshold:
|
||||||
|
returner = element
|
||||||
|
continue
|
||||||
|
return returner
|
||||||
|
|
||||||
|
|
||||||
|
def merge(n1, n2):
|
||||||
|
lat = (n1[0] + n2[0]) / 2
|
||||||
|
lon = (n1[1] + n2[1]) / 2
|
||||||
|
returner = []
|
||||||
|
returner.append(lat)
|
||||||
|
returner.append(lon)
|
||||||
|
for i in range(2, len(n1)):
|
||||||
|
returner.append(n1[i])
|
||||||
|
for i in range(2, len(n2)):
|
||||||
|
returner.append(n2[i])
|
||||||
|
return returner
|
||||||
|
|
||||||
|
|
||||||
|
def get_space_location(space):
|
||||||
|
try:
|
||||||
|
spacerequest = requests.get(url=data[space], timeout=1)
|
||||||
|
spacedata = spacerequest.json()
|
||||||
|
except requests.exceptions.RequestException as _:
|
||||||
|
return
|
||||||
|
except json.JSONDecodeError as _:
|
||||||
|
return
|
||||||
|
if "location" in spacedata:
|
||||||
|
if "lat" in spacedata["location"]:
|
||||||
|
lat = spacedata["location"]["lat"]
|
||||||
|
lon = spacedata["location"]["lon"]
|
||||||
|
return [float(lat), float(lon), data[space]]
|
||||||
|
|
||||||
|
|
||||||
|
if os.path.isfile('locations.bin'):
|
||||||
|
print("using offline data...", file=sys.stderr)
|
||||||
|
with open("locations.bin", "rb") as f:
|
||||||
|
locations = pickle.load(f)
|
||||||
|
else:
|
||||||
|
print("offline data not available, downloading...", file=sys.stderr)
|
||||||
|
r = requests.get(url=URL)
|
||||||
|
data = r.json()
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
|
||||||
|
futures = {}
|
||||||
|
for space in data:
|
||||||
|
futures[space] = executor.submit(get_space_location, space)
|
||||||
|
for space in data:
|
||||||
|
location = futures[space].result()
|
||||||
|
if location:
|
||||||
|
locations[space] = location
|
||||||
|
print("done loading space data", file=sys.stderr)
|
||||||
|
|
||||||
|
for space in locations:
|
||||||
|
print(space + " " + str(locations[space]))
|
||||||
|
with open("locations.bin", "wb") as f:
|
||||||
|
pickle.dump(locations, f, pickle.HIGHEST_PROTOCOL)
|
||||||
|
|
||||||
|
print("Removing non-german points...", file=sys.stderr)
|
||||||
|
german_locations = locations.copy()
|
||||||
|
for space in locations:
|
||||||
|
if locations[space][0] > NORTHERNMOST:
|
||||||
|
del german_locations[space]
|
||||||
|
elif locations[space][0] < SOUTHERNMOST:
|
||||||
|
del german_locations[space]
|
||||||
|
elif locations[space][1] < WESTERNMOST:
|
||||||
|
del german_locations[space]
|
||||||
|
elif locations[space][1] > EASTERNMOST:
|
||||||
|
del german_locations[space]
|
||||||
|
|
||||||
|
for space in ignorelist:
|
||||||
|
del german_locations[space]
|
||||||
|
|
||||||
|
finallist = {}
|
||||||
|
while german_locations:
|
||||||
|
n1 = next(iter(german_locations))
|
||||||
|
conflictnode = conflict(finallist, german_locations[n1])
|
||||||
|
if conflictnode == None:
|
||||||
|
finallist.update({n1: german_locations[n1]})
|
||||||
|
del german_locations[n1]
|
||||||
|
else:
|
||||||
|
mergenode = merge(german_locations[n1], finallist[conflictnode])
|
||||||
|
del german_locations[n1]
|
||||||
|
del finallist[conflictnode]
|
||||||
|
german_locations.update(
|
||||||
|
{"MERGED: " + n1 + " " + conflictnode: mergenode})
|
||||||
|
|
||||||
|
for space in finallist:
|
||||||
|
print(str(finallist[space][0]) + " " + str(finallist[space][1]) + " {" +
|
||||||
|
space + "}")
|
||||||
|
|
||||||
|
dwg = svgwrite.Drawing('dots.svg', profile='tiny')
|
||||||
|
dwg.add(svgwrite.image.Image(href="Karte_Deutschland.svg", size=(586, 793)))
|
||||||
|
for space in finallist:
|
||||||
|
ypoint = (793 - (((finallist[space][0] - SOUTHERNMOST) / YSPAN) * 793))
|
||||||
|
xpoint = ((finallist[space][1] - WESTERNMOST) / XSPAN) * 586
|
||||||
|
dwg.add(dwg.circle(center=(xpoint, ypoint), r=5, fill='green'))
|
||||||
|
dwg.add(dwg.text(space, insert=(xpoint + 5, ypoint), font_size=5))
|
||||||
|
|
||||||
|
dwg.save()
|
||||||
|
|
||||||
|
|
||||||
|
ledconf = open("conf.yml", "w")
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for space in finallist:
|
||||||
|
ledconf.write("#led" + str(i) + ":\n-\n")
|
||||||
|
for u in range(2, len(finallist[space])):
|
||||||
|
ledconf.write(" - " + finallist[space][u] + "\n")
|
||||||
|
i = i + 1
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266HTTPClient.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define PIN 2
|
||||||
|
#define NUMPIXELS 12
|
||||||
|
const char* ssid = "CTDO-LEGACY";
|
||||||
|
const char* password = "******";
|
||||||
|
const char* apiEndpoint = "http://spacepanel.stablerock.de/leds";
|
||||||
|
const int pollInterval = 10000;
|
||||||
|
HTTPClient http;
|
||||||
|
|
||||||
|
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
int delayval = 500;
|
||||||
|
|
||||||
|
void setLED(int i, String value) {
|
||||||
|
String value_short = value.substring(1);
|
||||||
|
char charbuf[8];
|
||||||
|
value_short.toCharArray(charbuf,8);
|
||||||
|
long int rgb = strtol(charbuf,0,16); //=>rgb=0x001234FE;
|
||||||
|
byte r=(byte)(rgb>>16);
|
||||||
|
byte g=(byte)(rgb>>8);
|
||||||
|
byte b=(byte)(rgb);
|
||||||
|
|
||||||
|
Serial.print(value_short);
|
||||||
|
Serial.print("-> ");
|
||||||
|
Serial.print(r);
|
||||||
|
Serial.print(", ");
|
||||||
|
Serial.print(g);
|
||||||
|
Serial.print(", ");
|
||||||
|
Serial.println(b);
|
||||||
|
pixels.setPixelColor(i, pixels.Color(r/255,g/255,b/255));
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
Serial.println(WiFi.macAddress());
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(1000);
|
||||||
|
Serial.println("Connecting...");
|
||||||
|
}
|
||||||
|
Serial.println("Connected.");
|
||||||
|
|
||||||
|
pixels.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println("Sending request...");
|
||||||
|
http.begin(apiEndpoint);
|
||||||
|
int httpCode = http.GET();
|
||||||
|
Serial.println("Success.");
|
||||||
|
if (httpCode == 200) {
|
||||||
|
String json = http.getString();
|
||||||
|
const size_t capacity = JSON_ARRAY_SIZE(NUMPIXELS) + 510;
|
||||||
|
DynamicJsonDocument doc(capacity);
|
||||||
|
deserializeJson(doc, json);
|
||||||
|
for (int i = 0; i < NUMPIXELS; i++) {
|
||||||
|
Serial.print("LED" + String(i) + ": ");
|
||||||
|
const char* element = doc[i];
|
||||||
|
String value = String(element);
|
||||||
|
setLED(i, value);
|
||||||
|
Serial.print("LED" );
|
||||||
|
Serial.print(i);
|
||||||
|
Serial.print("Color: ");
|
||||||
|
Serial.println(value);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.println("Error: Statuscode" + httpCode);
|
||||||
|
}
|
||||||
|
delay(pollInterval);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
module repos.ctdo.de/mamu/spacepanel_aggregator
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.5.0
|
||||||
|
github.com/valyala/fastjson v1.4.5
|
||||||
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
|
)
|
|
@ -0,0 +1,47 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
|
||||||
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
|
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
|
||||||
|
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||||
|
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
|
||||||
|
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
||||||
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/valyala/fastjson v1.4.5 h1:uSuLfXk2LzRtzwd3Fy5zGRBe0Vs7zhs11vjdko32xb4=
|
||||||
|
github.com/valyala/fastjson v1.4.5/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,76 @@
|
||||||
|
package spacepanel_aggregator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/valyala/fastjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PollWorker(url string, led int) {
|
||||||
|
for {
|
||||||
|
err := Worker(url)
|
||||||
|
if err != nil {
|
||||||
|
SetSpaceState(url, Unknown)
|
||||||
|
fmt.Println("LED", led, "URL:", url, err.Error())
|
||||||
|
}
|
||||||
|
time.Sleep(sleeptime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
insecureTransport = &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
client = &http.Client{
|
||||||
|
Transport: insecureTransport,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func Worker(url string) error {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := fastjson.ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !value.Exists("state", "open") {
|
||||||
|
return errors.New("no space state existing")
|
||||||
|
}
|
||||||
|
|
||||||
|
state := value.GetBool("state", "open")
|
||||||
|
|
||||||
|
if state {
|
||||||
|
SetSpaceState(url, Open)
|
||||||
|
} else {
|
||||||
|
SetSpaceState(url, Close)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSpaceState(url string, s State) {
|
||||||
|
lock.Lock()
|
||||||
|
spacestates[url] = s
|
||||||
|
lock.Unlock()
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package spacepanel_aggregator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
io "io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var listen = ":8080"
|
||||||
|
var conffile = "conf.yml"
|
||||||
|
var sleeptime time.Duration = 60000000000 // nanoseconds
|
||||||
|
var leds [][]string
|
||||||
|
var spacestates map[string]State
|
||||||
|
var lock = sync.RWMutex{}
|
||||||
|
|
||||||
|
func SetConf(s string) {
|
||||||
|
conffile = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetIf(s string) {
|
||||||
|
listen = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start() {
|
||||||
|
fmt.Println("Welcome to Spacepanel Aggregator!\n")
|
||||||
|
fmt.Println("Listen Interface: ", listen)
|
||||||
|
fmt.Println("Config-File: ", conffile)
|
||||||
|
bytes, err := io.ReadFile(conffile)
|
||||||
|
if err != nil {
|
||||||
|
ce(err)
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(bytes, &leds)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ce(err)
|
||||||
|
panic("An error occured while parsing the conffile, quitting...")
|
||||||
|
}
|
||||||
|
spacestates = make(map[string]State)
|
||||||
|
for i := 0; i < len(leds); i++ {
|
||||||
|
for j := 0; j < len(leds[i]); j++ {
|
||||||
|
spacestates[leds[i][j]] = Unknown
|
||||||
|
go PollWorker(leds[i][j], i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Loaded", len(leds), "LED-configs and", len(spacestates), "spaces.")
|
||||||
|
|
||||||
|
r := setupRouter()
|
||||||
|
_ = r.Run(listen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBestState(states []string) State {
|
||||||
|
returner := Unknown
|
||||||
|
for i := 0; i < len(states); i++ {
|
||||||
|
if spacestates[states[i]] < returner {
|
||||||
|
returner = spacestates[states[i]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returner
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLedStates(c *gin.Context) {
|
||||||
|
returner := make([]string, len(leds))
|
||||||
|
for i := 0; i < len(leds); i++ {
|
||||||
|
returner[i] = colors[getBestState(leds[i])]
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, returner)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRouter() *gin.Engine {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
r := gin.Default()
|
||||||
|
// Ping test
|
||||||
|
//r.GET("/leds", getLedStates())
|
||||||
|
r.GET("/leds", getLedStates)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func ce(err error) {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("ERROR: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
sa "repos.ctdo.de/mamu/spacepanel_aggregator"
|
||||||
|
)
|
||||||
|
|
||||||
|
const helptext string = "spacepanel_aggregator usage: \n\n -l IF:port default: *:8080 \n -f config-file default: conf.yml \n -h print help and exit\n"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conf := true
|
||||||
|
for i := 1; i < len(os.Args); i++ {
|
||||||
|
switch os.Args[i] {
|
||||||
|
case "-l":
|
||||||
|
i++
|
||||||
|
if i < len(os.Args) {
|
||||||
|
sa.SetIf(os.Args[i])
|
||||||
|
} else {
|
||||||
|
conf = false
|
||||||
|
}
|
||||||
|
case "-f":
|
||||||
|
i++
|
||||||
|
if i < len(os.Args) {
|
||||||
|
sa.SetConf(os.Args[i])
|
||||||
|
} else {
|
||||||
|
conf = false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
conf = false
|
||||||
|
i = len(os.Args)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if conf {
|
||||||
|
sa.Start()
|
||||||
|
} else {
|
||||||
|
printHelp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHelp() {
|
||||||
|
fmt.Printf(helptext)
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
#led0:
|
||||||
|
-
|
||||||
|
- https://www.devtal.de/api/
|
||||||
|
#led1:
|
||||||
|
-
|
||||||
|
- https://www.binary-kitchen.de/spaceapi.php
|
||||||
|
#led2:
|
||||||
|
-
|
||||||
|
- https://status.aachen.ccc.de/spaceapi
|
||||||
|
#led3:
|
||||||
|
-
|
||||||
|
- https://schalter.ccchb.de/spaceapi.json
|
||||||
|
#led4:
|
||||||
|
-
|
||||||
|
- https://api.koeln.ccc.de
|
||||||
|
#led5:
|
||||||
|
-
|
||||||
|
- https://www.ccc-mannheim.de/spaceapi/spaceapi.json
|
||||||
|
#led6:
|
||||||
|
-
|
||||||
|
- http://cccfr.de/status/spaceapi.py
|
||||||
|
#led7:
|
||||||
|
-
|
||||||
|
- http://chaos-consulting.de/api/space.api
|
||||||
|
#led8:
|
||||||
|
-
|
||||||
|
- https://status.chaospott.de/status.json
|
||||||
|
#led9:
|
||||||
|
-
|
||||||
|
- https://chaoschemnitz.de/chch.json
|
||||||
|
#led10:
|
||||||
|
-
|
||||||
|
- https://www.ccc-p.org/spaceapi.json
|
||||||
|
#led11:
|
||||||
|
-
|
||||||
|
- http://doorstatus.c3re.de/status/json
|
||||||
|
#led12:
|
||||||
|
-
|
||||||
|
- http://status.ctdo.de/api/spaceapi/v13
|
||||||
|
#led13:
|
||||||
|
-
|
||||||
|
- https://status.diyww.de/status.json
|
||||||
|
#led14:
|
||||||
|
-
|
||||||
|
- http://club.entropia.de/spaceapi
|
||||||
|
#led15:
|
||||||
|
-
|
||||||
|
- https://fablab.fau.de/spaceapi/
|
||||||
|
#led16:
|
||||||
|
-
|
||||||
|
- https://spaceapi.futev.de/spaceapi.json
|
||||||
|
#led17:
|
||||||
|
-
|
||||||
|
- https://freieslabor.org/api/info
|
||||||
|
#led18:
|
||||||
|
-
|
||||||
|
- https://hackerspace-bielefeld.de/spacestatus/status.json
|
||||||
|
#led19:
|
||||||
|
-
|
||||||
|
- https://hacklabor.de/api/space/v1/
|
||||||
|
#led20:
|
||||||
|
-
|
||||||
|
- http://spaceapi.hacksaar.de/status.json
|
||||||
|
#led21:
|
||||||
|
-
|
||||||
|
- https://status.hasi.it/spaceapi
|
||||||
|
#led22:
|
||||||
|
-
|
||||||
|
- https://status.kraut.space/api
|
||||||
|
#led23:
|
||||||
|
-
|
||||||
|
- http://status.leinelab.org/api/spaceapi.json
|
||||||
|
#led24:
|
||||||
|
-
|
||||||
|
- http://status.mainframe.io/api/spaceInfo
|
||||||
|
#led25:
|
||||||
|
-
|
||||||
|
- http://spaceapi.n39.eu/json
|
||||||
|
#led26:
|
||||||
|
-
|
||||||
|
- http://netzladen.org/api/status.json
|
||||||
|
#led27:
|
||||||
|
-
|
||||||
|
- https://api.nerd2nerd.org/status.json
|
||||||
|
#led28:
|
||||||
|
-
|
||||||
|
- https://cccgoe.de/spaceapi.php
|
||||||
|
#led29:
|
||||||
|
-
|
||||||
|
- http://api.openlab-augsburg.de/data.json
|
||||||
|
#led30:
|
||||||
|
-
|
||||||
|
- https://werkraum.freiraumzittau.de/spaceapi/13/
|
||||||
|
#led31:
|
||||||
|
-
|
||||||
|
- https://spaceapi.reaktor23.org
|
||||||
|
#led32:
|
||||||
|
-
|
||||||
|
- http://status.stratum0.org/status.json
|
||||||
|
#led33:
|
||||||
|
-
|
||||||
|
- https://api.warpzone.ms/spaceapi
|
||||||
|
#led34:
|
||||||
|
-
|
||||||
|
- https://hsmr.cc/spaceapi.json
|
||||||
|
#led35:
|
||||||
|
-
|
||||||
|
- https://status.bckspc.de/spacestatus.php
|
||||||
|
#led36:
|
||||||
|
-
|
||||||
|
- http://stats.bytewerk.org/status.json
|
||||||
|
#led37:
|
||||||
|
-
|
||||||
|
- https://api.flipdot.org/
|
||||||
|
#led38:
|
||||||
|
-
|
||||||
|
- https://spaceapi.hackzogtum-coburg.de
|
||||||
|
#led39:
|
||||||
|
-
|
||||||
|
- https://state.maglab.space/spaceapi.json
|
||||||
|
#led40:
|
||||||
|
-
|
||||||
|
- http://nobreakspace.org/status/spaceapi.json
|
||||||
|
#led41:
|
||||||
|
-
|
||||||
|
- https://bodensee.space/spaceapi/see-base.json
|
||||||
|
#led42:
|
||||||
|
-
|
||||||
|
- https://api.shackspace.de/v1/spaceapi
|
||||||
|
#led43:
|
||||||
|
-
|
||||||
|
- https://verschwoerhaus.de/feed/spaceapi
|
||||||
|
#led44:
|
||||||
|
-
|
||||||
|
- https://vspace.one/spaceapi.json
|
||||||
|
#led45:
|
||||||
|
-
|
||||||
|
- https://keinanschluss.un-hack-bar.de/spaceapi.json
|
||||||
|
#led46:
|
||||||
|
-
|
||||||
|
- https://www.hackerspace-sw.de/spaceapi.json
|
||||||
|
#led47:
|
||||||
|
-
|
||||||
|
- https://hamburg.ccc.de/dooris/status.json
|
||||||
|
- http://blog.attraktor.org/spaceapi/spaceapi.json
|
||||||
|
#led48:
|
||||||
|
-
|
||||||
|
- https://status.makerspace-erfurt.de/status.json
|
||||||
|
- http://status.bytespeicher.org/status.json
|
||||||
|
#led49:
|
||||||
|
-
|
||||||
|
- http://status.munichmakerlab.de/spaceapi.php
|
||||||
|
- http://api.muc.ccc.de/spaceapi.json
|
||||||
|
#led50:
|
||||||
|
-
|
||||||
|
- http://api.terminal21.de
|
||||||
|
- http://api.terminal21.de/status_ebk.json
|
||||||
|
#led51:
|
||||||
|
-
|
||||||
|
- https://fnord.istsystemrelevant.de/spaceapi.json
|
||||||
|
- https://chaosdorf.de/space_api.json
|
||||||
|
#led52:
|
||||||
|
-
|
||||||
|
- http://spaceapi.nordlab-ev.de
|
||||||
|
- https://api.chaostreff-flensburg.de/
|
||||||
|
#led53:
|
||||||
|
-
|
||||||
|
- http://www.space-left.org/spaceapi13.json
|
||||||
|
- https://das-labor.org/status/api
|
||||||
|
#led54:
|
||||||
|
-
|
||||||
|
- http://www.turmlabor.de/spaces.api
|
||||||
|
- https://www.c3d2.de/spaceapi.json
|
||||||
|
#led55:
|
||||||
|
-
|
||||||
|
- http://spaceapi.k4cg.org/spaceapi.json
|
||||||
|
- http://api.fablab-nuernberg.de/spaceapi.php
|
||||||
|
- https://status.nerdberg.de/api/space
|
||||||
|
#led56:
|
||||||
|
-
|
||||||
|
- https://x-hain.de/spaceapi-0.13.json
|
||||||
|
- http://www.c-base.org/status.json
|
||||||
|
- https://spaceapi.motionlab.berlin/
|
||||||
|
- https://spaceapi.afra-berlin.de/v1/status.json
|
|
@ -0,0 +1,239 @@
|
||||||
|
package spacepanel_aggregator
|
||||||
|
|
||||||
|
type State int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Open = State(iota)
|
||||||
|
Close
|
||||||
|
Outdated
|
||||||
|
Unknown
|
||||||
|
)
|
||||||
|
|
||||||
|
var colors = [4]string{"#00ff00", "#ff0000", "#0000ff", "#000000"}
|
||||||
|
|
||||||
|
type V13 struct {
|
||||||
|
API string `json:"api"`
|
||||||
|
Cache struct {
|
||||||
|
Schedule string `json:"schedule"`
|
||||||
|
} `json:"cache"`
|
||||||
|
Cam []string `json:"cam"`
|
||||||
|
Contact struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Facebook string `json:"facebook"`
|
||||||
|
Foursquare string `json:"foursquare"`
|
||||||
|
Google struct {
|
||||||
|
Plus string `json:"plus"`
|
||||||
|
} `json:"google"`
|
||||||
|
Identica string `json:"identica"`
|
||||||
|
Irc string `json:"irc"`
|
||||||
|
IssueMail string `json:"issue_mail"`
|
||||||
|
Jabber string `json:"jabber"`
|
||||||
|
Keymasters []struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
IrcNick string `json:"irc_nick"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Twitter string `json:"twitter"`
|
||||||
|
} `json:"keymasters"`
|
||||||
|
Ml string `json:"ml"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Sip string `json:"sip"`
|
||||||
|
Twitter string `json:"twitter"`
|
||||||
|
} `json:"contact"`
|
||||||
|
Events []struct {
|
||||||
|
Extra string `json:"extra"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Timestamp float64 `json:"timestamp"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
} `json:"events"`
|
||||||
|
Feeds struct {
|
||||||
|
Blog struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"blog"`
|
||||||
|
Calendar struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"calendar"`
|
||||||
|
Flickr struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"flickr"`
|
||||||
|
Wiki struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"wiki"`
|
||||||
|
} `json:"feeds"`
|
||||||
|
IssueReportChannels []string `json:"issue_report_channels"`
|
||||||
|
Location struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
Lat float64 `json:"lat"`
|
||||||
|
Lon float64 `json:"lon"`
|
||||||
|
} `json:"location"`
|
||||||
|
Logo string `json:"logo"`
|
||||||
|
Projects []string `json:"projects"`
|
||||||
|
RadioShow []struct {
|
||||||
|
End string `json:"end"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Start string `json:"start"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"radio_show"`
|
||||||
|
Sensors struct {
|
||||||
|
AccountBalance []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"account_balance"`
|
||||||
|
Barometer []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"barometer"`
|
||||||
|
BeverageSupply []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"beverage_supply"`
|
||||||
|
DoorLocked []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value bool `json:"value"`
|
||||||
|
} `json:"door_locked"`
|
||||||
|
Humidity []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"humidity"`
|
||||||
|
NetworkConnections []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Machines []struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"machines"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"network_connections"`
|
||||||
|
PeopleNowPresent []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Names []string `json:"names"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"people_now_present"`
|
||||||
|
PowerConsumption []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"power_consumption"`
|
||||||
|
Radiation struct {
|
||||||
|
Alpha []struct {
|
||||||
|
ConversionFactor float64 `json:"conversion_factor"`
|
||||||
|
DeadTime float64 `json:"dead_time"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"alpha"`
|
||||||
|
Beta []struct {
|
||||||
|
ConversionFactor float64 `json:"conversion_factor"`
|
||||||
|
DeadTime float64 `json:"dead_time"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"beta"`
|
||||||
|
BetaGamma []struct {
|
||||||
|
ConversionFactor float64 `json:"conversion_factor"`
|
||||||
|
DeadTime float64 `json:"dead_time"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"beta_gamma"`
|
||||||
|
Gamma []struct {
|
||||||
|
ConversionFactor float64 `json:"conversion_factor"`
|
||||||
|
DeadTime float64 `json:"dead_time"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"gamma"`
|
||||||
|
} `json:"radiation"`
|
||||||
|
Temperature []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"temperature"`
|
||||||
|
TotalMemberCount []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"total_member_count"`
|
||||||
|
Wind []struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Properties struct {
|
||||||
|
Direction struct {
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"direction"`
|
||||||
|
Elevation struct {
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"elevation"`
|
||||||
|
Gust struct {
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"gust"`
|
||||||
|
Speed struct {
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
} `json:"speed"`
|
||||||
|
} `json:"properties"`
|
||||||
|
} `json:"wind"`
|
||||||
|
} `json:"sensors"`
|
||||||
|
Space string `json:"space"`
|
||||||
|
Spacefed struct {
|
||||||
|
Spacenet bool `json:"spacenet"`
|
||||||
|
Spacephone bool `json:"spacephone"`
|
||||||
|
Spacesaml bool `json:"spacesaml"`
|
||||||
|
} `json:"spacefed"`
|
||||||
|
State struct {
|
||||||
|
Icon struct {
|
||||||
|
Closed string `json:"closed"`
|
||||||
|
Open string `json:"open"`
|
||||||
|
} `json:"icon"`
|
||||||
|
Lastchange float64 `json:"lastchange"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Open interface{} `json:"open"`
|
||||||
|
TriggerPerson string `json:"trigger_person"`
|
||||||
|
} `json:"state"`
|
||||||
|
Stream struct {
|
||||||
|
M4 string `json:"m4"`
|
||||||
|
Mjpeg string `json:"mjpeg"`
|
||||||
|
Ustream string `json:"ustream"`
|
||||||
|
} `json:"stream"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
Loading…
Reference in New Issue