Refactor nearly everything
This commit is contained in:
parent
a792ae367a
commit
df71c89b9f
|
@ -1,183 +1,126 @@
|
||||||
#led0:
|
led0:
|
||||||
-
|
|
||||||
- https://www.devtal.de/api/
|
- https://www.devtal.de/api/
|
||||||
#led1:
|
led1:
|
||||||
-
|
|
||||||
- https://www.binary-kitchen.de/spaceapi.php
|
- https://www.binary-kitchen.de/spaceapi.php
|
||||||
#led2:
|
led2:
|
||||||
-
|
|
||||||
- https://status.aachen.ccc.de/spaceapi
|
- https://status.aachen.ccc.de/spaceapi
|
||||||
#led3:
|
led3:
|
||||||
-
|
|
||||||
- https://schalter.ccchb.de/spaceapi.json
|
- https://schalter.ccchb.de/spaceapi.json
|
||||||
#led4:
|
led4:
|
||||||
-
|
|
||||||
- https://api.koeln.ccc.de
|
- https://api.koeln.ccc.de
|
||||||
#led5:
|
led5:
|
||||||
-
|
|
||||||
- https://www.ccc-mannheim.de/spaceapi/spaceapi.json
|
- https://www.ccc-mannheim.de/spaceapi/spaceapi.json
|
||||||
#led6:
|
led6:
|
||||||
-
|
|
||||||
- http://cccfr.de/status/spaceapi.py
|
- http://cccfr.de/status/spaceapi.py
|
||||||
#led7:
|
led7:
|
||||||
-
|
|
||||||
- http://chaos-consulting.de/api/space.api
|
- http://chaos-consulting.de/api/space.api
|
||||||
#led8:
|
led8:
|
||||||
-
|
|
||||||
- https://status.chaospott.de/status.json
|
- https://status.chaospott.de/status.json
|
||||||
#led9:
|
led9:
|
||||||
-
|
|
||||||
- https://chaoschemnitz.de/chch.json
|
- https://chaoschemnitz.de/chch.json
|
||||||
#led10:
|
led10:
|
||||||
-
|
|
||||||
- https://www.ccc-p.org/spaceapi.json
|
- https://www.ccc-p.org/spaceapi.json
|
||||||
#led11:
|
led11:
|
||||||
-
|
|
||||||
- http://doorstatus.c3re.de/status/json
|
- http://doorstatus.c3re.de/status/json
|
||||||
#led12:
|
led12:
|
||||||
-
|
|
||||||
- http://status.ctdo.de/api/spaceapi/v13
|
- http://status.ctdo.de/api/spaceapi/v13
|
||||||
#led13:
|
led13:
|
||||||
-
|
|
||||||
- https://status.diyww.de/status.json
|
- https://status.diyww.de/status.json
|
||||||
#led14:
|
led14:
|
||||||
-
|
|
||||||
- http://club.entropia.de/spaceapi
|
- http://club.entropia.de/spaceapi
|
||||||
#led15:
|
led15:
|
||||||
-
|
|
||||||
- https://fablab.fau.de/spaceapi/
|
- https://fablab.fau.de/spaceapi/
|
||||||
#led16:
|
led16:
|
||||||
-
|
|
||||||
- https://spaceapi.futev.de/spaceapi.json
|
- https://spaceapi.futev.de/spaceapi.json
|
||||||
#led17:
|
led17:
|
||||||
-
|
|
||||||
- https://freieslabor.org/api/info
|
- https://freieslabor.org/api/info
|
||||||
#led18:
|
led18:
|
||||||
-
|
|
||||||
- https://hackerspace-bielefeld.de/spacestatus/status.json
|
- https://hackerspace-bielefeld.de/spacestatus/status.json
|
||||||
#led19:
|
led19:
|
||||||
-
|
|
||||||
- https://hacklabor.de/api/space/v1/
|
- https://hacklabor.de/api/space/v1/
|
||||||
#led20:
|
led20:
|
||||||
-
|
|
||||||
- http://spaceapi.hacksaar.de/status.json
|
- http://spaceapi.hacksaar.de/status.json
|
||||||
#led21:
|
led21:
|
||||||
-
|
|
||||||
- https://status.hasi.it/spaceapi
|
- https://status.hasi.it/spaceapi
|
||||||
#led22:
|
led22:
|
||||||
-
|
|
||||||
- https://status.kraut.space/api
|
- https://status.kraut.space/api
|
||||||
#led23:
|
led23:
|
||||||
-
|
|
||||||
- http://status.leinelab.org/api/spaceapi.json
|
- http://status.leinelab.org/api/spaceapi.json
|
||||||
#led24:
|
led24:
|
||||||
-
|
|
||||||
- http://status.mainframe.io/api/spaceInfo
|
- http://status.mainframe.io/api/spaceInfo
|
||||||
#led25:
|
led25:
|
||||||
-
|
|
||||||
- http://spaceapi.n39.eu/json
|
- http://spaceapi.n39.eu/json
|
||||||
#led26:
|
led26:
|
||||||
-
|
|
||||||
- http://netzladen.org/api/status.json
|
- http://netzladen.org/api/status.json
|
||||||
#led27:
|
led27:
|
||||||
-
|
|
||||||
- https://api.nerd2nerd.org/status.json
|
- https://api.nerd2nerd.org/status.json
|
||||||
#led28:
|
led28:
|
||||||
-
|
|
||||||
- https://cccgoe.de/spaceapi.php
|
- https://cccgoe.de/spaceapi.php
|
||||||
#led29:
|
led29:
|
||||||
-
|
|
||||||
- http://api.openlab-augsburg.de/data.json
|
- http://api.openlab-augsburg.de/data.json
|
||||||
#led30:
|
led30:
|
||||||
-
|
|
||||||
- https://werkraum.freiraumzittau.de/spaceapi/13/
|
- https://werkraum.freiraumzittau.de/spaceapi/13/
|
||||||
#led31:
|
led31:
|
||||||
-
|
|
||||||
- https://spaceapi.reaktor23.org
|
- https://spaceapi.reaktor23.org
|
||||||
#led32:
|
led32:
|
||||||
-
|
|
||||||
- http://status.stratum0.org/status.json
|
- http://status.stratum0.org/status.json
|
||||||
#led33:
|
led33:
|
||||||
-
|
|
||||||
- https://api.warpzone.ms/spaceapi
|
- https://api.warpzone.ms/spaceapi
|
||||||
#led34:
|
led34:
|
||||||
-
|
|
||||||
- https://hsmr.cc/spaceapi.json
|
- https://hsmr.cc/spaceapi.json
|
||||||
#led35:
|
led35:
|
||||||
-
|
|
||||||
- https://status.bckspc.de/spacestatus.php
|
- https://status.bckspc.de/spacestatus.php
|
||||||
#led36:
|
led36:
|
||||||
-
|
|
||||||
- http://stats.bytewerk.org/status.json
|
- http://stats.bytewerk.org/status.json
|
||||||
#led37:
|
led37:
|
||||||
-
|
|
||||||
- https://api.flipdot.org/
|
- https://api.flipdot.org/
|
||||||
#led38:
|
led38:
|
||||||
-
|
|
||||||
- https://spaceapi.hackzogtum-coburg.de
|
- https://spaceapi.hackzogtum-coburg.de
|
||||||
#led39:
|
led39:
|
||||||
-
|
|
||||||
- https://state.maglab.space/spaceapi.json
|
- https://state.maglab.space/spaceapi.json
|
||||||
#led40:
|
led40:
|
||||||
-
|
|
||||||
- http://nobreakspace.org/status/spaceapi.json
|
- http://nobreakspace.org/status/spaceapi.json
|
||||||
#led41:
|
led41:
|
||||||
-
|
|
||||||
- https://bodensee.space/spaceapi/see-base.json
|
- https://bodensee.space/spaceapi/see-base.json
|
||||||
#led42:
|
led42:
|
||||||
-
|
|
||||||
- https://api.shackspace.de/v1/spaceapi
|
- https://api.shackspace.de/v1/spaceapi
|
||||||
#led43:
|
led43:
|
||||||
-
|
|
||||||
- https://verschwoerhaus.de/feed/spaceapi
|
- https://verschwoerhaus.de/feed/spaceapi
|
||||||
#led44:
|
led44:
|
||||||
-
|
|
||||||
- https://vspace.one/spaceapi.json
|
- https://vspace.one/spaceapi.json
|
||||||
#led45:
|
led45:
|
||||||
-
|
|
||||||
- https://keinanschluss.un-hack-bar.de/spaceapi.json
|
- https://keinanschluss.un-hack-bar.de/spaceapi.json
|
||||||
#led46:
|
led46:
|
||||||
-
|
|
||||||
- https://www.hackerspace-sw.de/spaceapi.json
|
- https://www.hackerspace-sw.de/spaceapi.json
|
||||||
#led47:
|
led47:
|
||||||
-
|
|
||||||
- https://hamburg.ccc.de/dooris/status.json
|
- https://hamburg.ccc.de/dooris/status.json
|
||||||
- http://blog.attraktor.org/spaceapi/spaceapi.json
|
- http://blog.attraktor.org/spaceapi/spaceapi.json
|
||||||
#led48:
|
led48:
|
||||||
-
|
|
||||||
- https://status.makerspace-erfurt.de/status.json
|
- https://status.makerspace-erfurt.de/status.json
|
||||||
- http://status.bytespeicher.org/status.json
|
- http://status.bytespeicher.org/status.json
|
||||||
#led49:
|
led49:
|
||||||
-
|
|
||||||
- http://status.munichmakerlab.de/spaceapi.php
|
- http://status.munichmakerlab.de/spaceapi.php
|
||||||
- http://api.muc.ccc.de/spaceapi.json
|
- http://api.muc.ccc.de/spaceapi.json
|
||||||
#led50:
|
led50:
|
||||||
-
|
|
||||||
- http://api.terminal21.de
|
- http://api.terminal21.de
|
||||||
- http://api.terminal21.de/status_ebk.json
|
- http://api.terminal21.de/status_ebk.json
|
||||||
#led51:
|
led51:
|
||||||
-
|
|
||||||
- https://fnord.istsystemrelevant.de/spaceapi.json
|
- https://fnord.istsystemrelevant.de/spaceapi.json
|
||||||
- https://chaosdorf.de/space_api.json
|
- https://chaosdorf.de/space_api.json
|
||||||
#led52:
|
led52:
|
||||||
-
|
|
||||||
- http://spaceapi.nordlab-ev.de
|
- http://spaceapi.nordlab-ev.de
|
||||||
- https://api.chaostreff-flensburg.de/
|
- https://api.chaostreff-flensburg.de/
|
||||||
#led53:
|
led53:
|
||||||
-
|
|
||||||
- http://www.space-left.org/spaceapi13.json
|
- http://www.space-left.org/spaceapi13.json
|
||||||
- https://das-labor.org/status/api
|
- https://das-labor.org/status/api
|
||||||
#led54:
|
led54:
|
||||||
-
|
|
||||||
- http://www.turmlabor.de/spaces.api
|
- http://www.turmlabor.de/spaces.api
|
||||||
- https://www.c3d2.de/spaceapi.json
|
- https://www.c3d2.de/spaceapi.json
|
||||||
#led55:
|
led55:
|
||||||
-
|
|
||||||
- http://spaceapi.k4cg.org/spaceapi.json
|
- http://spaceapi.k4cg.org/spaceapi.json
|
||||||
- http://api.fablab-nuernberg.de/spaceapi.php
|
- http://api.fablab-nuernberg.de/spaceapi.php
|
||||||
- https://status.nerdberg.de/api/space
|
- https://status.nerdberg.de/api/space
|
||||||
#led56:
|
led56:
|
||||||
-
|
|
||||||
- https://x-hain.de/spaceapi-0.13.json
|
- https://x-hain.de/spaceapi-0.13.json
|
||||||
- http://www.c-base.org/status.json
|
- http://www.c-base.org/status.json
|
||||||
- https://spaceapi.motionlab.berlin/
|
- https://spaceapi.motionlab.berlin/
|
2
go.mod
2
go.mod
|
@ -4,6 +4,8 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.5.0
|
github.com/gin-gonic/gin v1.5.0
|
||||||
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/valyala/fastjson v1.4.5
|
github.com/valyala/fastjson v1.4.5
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
)
|
)
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -14,6 +14,7 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
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 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
||||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
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 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
|
@ -24,7 +25,11 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
@ -34,6 +39,7 @@ 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/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 h1:uSuLfXk2LzRtzwd3Fy5zGRBe0Vs7zhs11vjdko32xb4=
|
||||||
github.com/valyala/fastjson v1.4.5/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=
|
github.com/valyala/fastjson v1.4.5/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
io "io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
configFile string
|
||||||
|
addr string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&configFile, "config", "conf.yml", "")
|
||||||
|
flag.StringVar(&addr, "addr", ":8080", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if _, err := os.Stat(configFile); err == os.ErrNotExist {
|
||||||
|
logrus.Fatal("Config file not found")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Println("Welcome to Spacepanel Aggregator!")
|
||||||
|
logrus.Println()
|
||||||
|
logrus.Printf("Listen Address: %s", addr)
|
||||||
|
logrus.Printf("Config-File: %s", configFile)
|
||||||
|
|
||||||
|
bytes, err := io.ReadFile(configFile)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ledSpaceMap map[string][]string
|
||||||
|
err = yaml.Unmarshal(bytes, &ledSpaceMap)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Error loading config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceCount := 0
|
||||||
|
for _, spaces := range ledSpaceMap {
|
||||||
|
spaceCount += len(spaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Loaded", len(ledSpaceMap), "LED-configs and", spaceCount, "spaces.")
|
||||||
|
|
||||||
|
aggregator := NewStateAggregator(ledSpaceMap)
|
||||||
|
|
||||||
|
server := http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/leds", func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
data, err := json.Marshal(aggregator.GetLedStates())
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
writer.WriteHeader(503)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Write(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logrus.Infof("Request: %s %s %s", r.RemoteAddr, r.Method, r.URL)
|
||||||
|
http.DefaultServeMux.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
|
logrus.Fatal(server.ListenAndServe())
|
||||||
|
}
|
|
@ -1,26 +1,19 @@
|
||||||
package spacepanel_aggregator
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/valyala/fastjson"
|
"github.com/valyala/fastjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
func PollWorker(url string, led int) {
|
const (
|
||||||
for {
|
SleepTime = 60 * time.Minute
|
||||||
err := Worker(url)
|
)
|
||||||
if err != nil {
|
|
||||||
SetSpaceState(url, Unknown)
|
|
||||||
fmt.Println("LED", led, "URL:", url, err.Error())
|
|
||||||
}
|
|
||||||
time.Sleep(sleeptime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
insecureTransport = &http.Transport{
|
insecureTransport = &http.Transport{
|
||||||
|
@ -32,45 +25,48 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func Worker(url string) error {
|
func StartPollWorker(space *Space) {
|
||||||
|
for {
|
||||||
|
state, err := requestSpaceState(space.URL)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("URL: %s, Err: %v", space.URL, err)
|
||||||
|
}
|
||||||
|
space.State = state
|
||||||
|
time.Sleep(SleepTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestSpaceState(url string) (State, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Unknown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Unknown, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Unknown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := fastjson.ParseBytes(data)
|
value, err := fastjson.ParseBytes(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Unknown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !value.Exists("state", "open") {
|
if !value.Exists("state", "open") {
|
||||||
return errors.New("no space state existing")
|
return Unknown, errors.New("no space state existing")
|
||||||
}
|
}
|
||||||
|
|
||||||
state := value.GetBool("state", "open")
|
state := value.GetBool("state", "open")
|
||||||
|
|
||||||
if state {
|
if state {
|
||||||
SetSpaceState(url, Open)
|
return Open, nil
|
||||||
} else {
|
|
||||||
SetSpaceState(url, Close)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return Close, nil
|
||||||
}
|
|
||||||
|
|
||||||
func SetSpaceState(url string, s State) {
|
|
||||||
lock.Lock()
|
|
||||||
spacestates[url] = s
|
|
||||||
lock.Unlock()
|
|
||||||
}
|
}
|
86
setup.go
86
setup.go
|
@ -1,86 +0,0 @@
|
||||||
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,75 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type State int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unknown = State(iota)
|
||||||
|
Outdated
|
||||||
|
Close
|
||||||
|
Open
|
||||||
|
)
|
||||||
|
|
||||||
|
var ColorMap = map[State]string{
|
||||||
|
Unknown: "#000000",
|
||||||
|
Outdated: "#0000ff",
|
||||||
|
Close: "#ff0000",
|
||||||
|
Open: "#00ff00",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Space struct {
|
||||||
|
State State
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
type StateAggregator struct {
|
||||||
|
ledList map[int][]*Space
|
||||||
|
mtx sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStateAggregator(spaceList map[string][]string) *StateAggregator {
|
||||||
|
s := &StateAggregator{
|
||||||
|
ledList: make(map[int][]*Space),
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, spaceUrls := range spaceList {
|
||||||
|
for _, url := range spaceUrls {
|
||||||
|
space := &Space{
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
|
|
||||||
|
go StartPollWorker(space)
|
||||||
|
s.ledList[i] = append(s.ledList[i], space)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBestStateFromList(spaces []*Space) State {
|
||||||
|
state := Unknown
|
||||||
|
for _, space := range spaces {
|
||||||
|
if space.State > state {
|
||||||
|
state = space.State
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StateAggregator) GetLedStates() map[int]string {
|
||||||
|
states := make(map[int]string)
|
||||||
|
|
||||||
|
s.mtx.RLock()
|
||||||
|
for i, spaceList := range s.ledList {
|
||||||
|
states[i] = ColorMap[GetBestStateFromList(spaceList)]
|
||||||
|
}
|
||||||
|
s.mtx.RUnlock()
|
||||||
|
|
||||||
|
return states
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
239
types.go
239
types.go
|
@ -1,239 +0,0 @@
|
||||||
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