Compare commits
2 Commits
c9b496d5eb
...
c8c7c9e938
Author | SHA1 | Date | |
---|---|---|---|
c8c7c9e938 | |||
21157e5fb4 |
48
README.md
48
README.md
@ -1,12 +1,17 @@
|
|||||||
# Freifunk Meshviewer Unifi Access Points und Richtfunkstrecken import
|
# Freifunk Meshviewer Unifi Access Points und Richtfunkstrecken import
|
||||||
|
|
||||||
Dieses tool Importiert Nodes für die Freifunk Map aus den APIs UNMS (Richtfunk) & Unifi (Access Points)
|
Dieses tool Importiert Nodes für die Freifunk Map aus den APIs UISP (Richtfunk) & Unifi (Access Points).
|
||||||
|
Ebenfalls ist der Import statischer devices möglich. Da diese alle in unerem Proxmox cluster laufen, werden Statistikdaten aus der Proxmox InfluxDB geholt.
|
||||||
|
|
||||||
|
Alle Config dateien müssen per http erreichbar sein (z.B. in einem Git)
|
||||||
|
Für Troisdorf werden diese Dateien hier gepflegt: https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-api-devices
|
||||||
|
Für die Rhein-Sieg-Map hier: https://git.freifunk-rhein-sieg.net/Freifunk-Rhein-Sieg/ubnt-api-devices
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
### Unifi Access Points (ucDevices.json)
|
### Unifi Access Points (unifi_devices.json)
|
||||||
|
|
||||||
In der Datei ucDevices.json können die Access Points gepflegt werden, die auf der Freifunk Map erscheinen sollen.
|
In der Datei unifi_devices.json können die Access Points gepflegt werden, die auf der Freifunk Map erscheinen sollen.
|
||||||
|
|
||||||
Hierzu muss die Datei im json Format erweitert werden.
|
Hierzu muss die Datei im json Format erweitert werden.
|
||||||
|
|
||||||
@ -32,9 +37,9 @@ Erklärung:
|
|||||||
* linked_to: (Optional) Die MAC Adresse des Routers an dem der AP angeschlossen ist. Normalerweise gateway_nexthop mit Doppelpunkten. Wenn nicht gesetzt wird kein Link auf der Map angezeigt.
|
* linked_to: (Optional) Die MAC Adresse des Routers an dem der AP angeschlossen ist. Normalerweise gateway_nexthop mit Doppelpunkten. Wenn nicht gesetzt wird kein Link auf der Map angezeigt.
|
||||||
* domain: Die Domain in der sich der AP befindet. (tdf, inn, flu)
|
* domain: Die Domain in der sich der AP befindet. (tdf, inn, flu)
|
||||||
|
|
||||||
### UNMS Richtfunkstrecken
|
### UISP Richtfunkstrecken
|
||||||
|
|
||||||
In der Datei devices.json können die Richtfunkstrecken gepflegt werden, die auf der Freifunk Map erscheinen sollen.
|
In der Datei rifu_devices.json können die Richtfunkstrecken gepflegt werden, die auf der Freifunk Map erscheinen sollen.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -56,11 +61,44 @@ Erklärung:
|
|||||||
* gateway: Im Normalfall die NodeID des Supernodes (zu finden in der MAP)
|
* gateway: Im Normalfall die NodeID des Supernodes (zu finden in der MAP)
|
||||||
* domain: Die Domain in der sich der AP befindet. (tdf, inn, flu)
|
* domain: Die Domain in der sich der AP befindet. (tdf, inn, flu)
|
||||||
|
|
||||||
|
### UISP Router
|
||||||
|
|
||||||
|
In dieser datei werden die Router (meist ER-X) gepflegt. Diese Daten werden dann ebenfalls aus der UISP API Importiert.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Rathaus Uplink",
|
||||||
|
"mac": "18:e8:29:ad:9a:34",
|
||||||
|
"gateway_nexthop": "18e8292f7de6",
|
||||||
|
"gateway": "a28cae6ff604",
|
||||||
|
"domain": "tdf",
|
||||||
|
"location": {
|
||||||
|
"longitude":7.149406208,
|
||||||
|
"latitude":50.817093402
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gateways.json
|
||||||
|
|
||||||
|
Hier werden Statische Geräte eingetragen die auf dem Proxmox Cluster laufen.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "VPN01",
|
||||||
|
"fqdn": "vpn01.fftdf.de",
|
||||||
|
"mac": "00:00:00:00:00:01",
|
||||||
|
"domain": "VPN1",
|
||||||
|
"adresses": ["5.9.220.114"]
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
### Config.json
|
### Config.json
|
||||||
|
|
||||||
Es gibt 3 Module die Ein/Ausgeschatet werden können:
|
Es gibt 3 Module die Ein/Ausgeschatet werden können:
|
||||||
* UNMS
|
* UNMS
|
||||||
* Unifi
|
* Unifi
|
||||||
* Meshviewer
|
* Meshviewer
|
||||||
|
* Gateways
|
||||||
|
|
||||||
Die Funktion Meshviewer importiert die vorhandenen meshviewer.json und manipuliert dort die Userzahlen. Sobald ein Access Point einen Node aus einer Meshviwer.json als "gateway_nexthop" eingetragen hat, werden die Clients an dem verbundenen Access Point und nicht mehr am Offloader angezeigt.
|
Die Funktion Meshviewer importiert die vorhandenen meshviewer.json und manipuliert dort die Userzahlen. Sobald ein Access Point einen Node aus einer Meshviwer.json als "gateway_nexthop" eingetragen hat, werden die Clients an dem verbundenen Access Point und nicht mehr am Offloader angezeigt.
|
||||||
|
48
main.go
48
main.go
@ -38,12 +38,12 @@ func main() {
|
|||||||
// start API processing (runs in a loop)
|
// start API processing (runs in a loop)
|
||||||
go func() {
|
go func() {
|
||||||
if err := processAPIs(); err != nil {
|
if err := processAPIs(); err != nil {
|
||||||
log.Fatalln("API processing failed, error is", err)
|
log.Fatalln("API processing failed, error is: ", err)
|
||||||
}
|
}
|
||||||
tick := time.Tick(delay)
|
tick := time.Tick(delay)
|
||||||
for range tick {
|
for range tick {
|
||||||
if err := processAPIs(); err != nil {
|
if err := processAPIs(); err != nil {
|
||||||
log.Fatalln("API processing failed, error is", err)
|
log.Fatalln("API processing failed, error is: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -51,29 +51,16 @@ func main() {
|
|||||||
serveJSON()
|
serveJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadconfig(file string) config {
|
|
||||||
var config config
|
|
||||||
configFile, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
jsonParse := json.NewDecoder(configFile)
|
|
||||||
jsonParse.Decode(&config)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// int to bool converter
|
|
||||||
func itob(i int) bool {
|
|
||||||
return i == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func processAPIs() error {
|
func processAPIs() error {
|
||||||
var nodes []node
|
var nodes []node
|
||||||
var links []link
|
var links []link
|
||||||
|
|
||||||
if conf.Unms.Enabled {
|
if conf.Unms.Enabled {
|
||||||
log.Println("Processing UNMS")
|
log.Println("Processing UNMS")
|
||||||
unmsNodes, unmsLinks := processUNMSAPI()
|
unmsNodes, unmsLinks, err := processUNMSAPI()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
unmsRouters, err := processUNMSAPIRouter()
|
unmsRouters, err := processUNMSAPIRouter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -84,7 +71,10 @@ func processAPIs() error {
|
|||||||
}
|
}
|
||||||
if conf.Unifi.Enabled {
|
if conf.Unifi.Enabled {
|
||||||
log.Println("Processing Unifi")
|
log.Println("Processing Unifi")
|
||||||
ucNodes, _ := processUcAPIs()
|
ucNodes, _, err := processUcAPIs()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
nodes = append(nodes, ucNodes...)
|
nodes = append(nodes, ucNodes...)
|
||||||
}
|
}
|
||||||
if conf.Meshviewer.Enabled {
|
if conf.Meshviewer.Enabled {
|
||||||
@ -122,6 +112,24 @@ func processAPIs() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadconfig(file string) config {
|
||||||
|
var config config
|
||||||
|
configFile, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed loding Config file: ", err)
|
||||||
|
}
|
||||||
|
jsonParse := json.NewDecoder(configFile)
|
||||||
|
if err := jsonParse.Decode(&config); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// int to bool converter
|
||||||
|
func itob(i int) bool {
|
||||||
|
return i == 1
|
||||||
|
}
|
||||||
|
|
||||||
// function to get file from meshviewer
|
// function to get file from meshviewer
|
||||||
func getFile(url string) []byte {
|
func getFile(url string) []byte {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
|
@ -133,7 +133,6 @@ func getMeshviewer() ([]node, []link) {
|
|||||||
var links []link
|
var links []link
|
||||||
|
|
||||||
for i := range conf.Meshviewer.Files {
|
for i := range conf.Meshviewer.Files {
|
||||||
log.Println("Hole Meshviewer JSON von: ", conf.Meshviewer.Files[i].URL)
|
|
||||||
m, err := getMeshviewerJSON(conf.Meshviewer.Files[i].URL)
|
m, err := getMeshviewerJSON(conf.Meshviewer.Files[i].URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nodes, links
|
return nodes, links
|
||||||
|
22
unifi.go
22
unifi.go
@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Unifi Controller API processing
|
// Unifi Controller API processing
|
||||||
func processUcAPIs() ([]node, []link) {
|
func processUcAPIs() ([]node, []link, error) {
|
||||||
//get list of Unifi devices to display
|
//get list of Unifi devices to display
|
||||||
var nodes []node
|
var nodes []node
|
||||||
var links []link
|
var links []link
|
||||||
@ -22,16 +22,18 @@ func processUcAPIs() ([]node, []link) {
|
|||||||
//call Unifi Controller
|
//call Unifi Controller
|
||||||
ucAPI := UnifiNewAPI(conf.Unifi.User, conf.Unifi.Password, conf.Unifi.APIURL)
|
ucAPI := UnifiNewAPI(conf.Unifi.User, conf.Unifi.Password, conf.Unifi.APIURL)
|
||||||
//login
|
//login
|
||||||
ucAPI.ucLogin()
|
if err := ucAPI.ucLogin(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
//get all Sites from Controller
|
//get all Sites from Controller
|
||||||
sites, err := ucAPI.ucGetSites()
|
sites, err := ucAPI.ucGetSites()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
//get all devices in all sites
|
//get all devices in all sites
|
||||||
devices, err := ucAPI.ucGetDevices(sites)
|
devices, err := ucAPI.ucGetDevices(sites)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//build nodes struct
|
//build nodes struct
|
||||||
@ -39,6 +41,7 @@ func processUcAPIs() ([]node, []link) {
|
|||||||
for _, jsonDevice := range d.Devices {
|
for _, jsonDevice := range d.Devices {
|
||||||
var currentDevice ucDevice
|
var currentDevice ucDevice
|
||||||
var currentJSONDevice device
|
var currentJSONDevice device
|
||||||
|
isOnline := currentDevice.State == 1
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
if strings.EqualFold(device.Mac, jsonDevice.MAC) {
|
if strings.EqualFold(device.Mac, jsonDevice.MAC) {
|
||||||
currentDevice = device
|
currentDevice = device
|
||||||
@ -53,14 +56,15 @@ func processUcAPIs() ([]node, []link) {
|
|||||||
}
|
}
|
||||||
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
|
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error: ", currentDevice.Name)
|
log.Println("Error psrsing CPU load from ", currentDevice.Name)
|
||||||
//log.Fatalln(err)
|
log.Println(err)
|
||||||
load = 0
|
load = 0
|
||||||
}
|
}
|
||||||
mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64)
|
mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Fatalln(err)
|
log.Println("Error psrsing CPU load from ", currentDevice.Name)
|
||||||
load = 0
|
log.Println(err)
|
||||||
|
mem = 0
|
||||||
}
|
}
|
||||||
var model = lookupModels(currentDevice.Model)
|
var model = lookupModels(currentDevice.Model)
|
||||||
var clients int
|
var clients int
|
||||||
@ -101,7 +105,7 @@ func processUcAPIs() ([]node, []link) {
|
|||||||
Model: model,
|
Model: model,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nodes, links
|
return nodes, links, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnifiNewAPI(user string, pass string, baseURL string) UnifiAPIData {
|
func UnifiNewAPI(user string, pass string, baseURL string) UnifiAPIData {
|
||||||
|
42
unms.go
42
unms.go
@ -17,19 +17,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// UNMS API processing (Richtfunk)
|
// UNMS API processing (Richtfunk)
|
||||||
func processUNMSAPI() ([]node, []link) {
|
func processUNMSAPI() ([]node, []link, error) {
|
||||||
// Variables for runtime
|
// Variables for runtime
|
||||||
var links []link
|
var links []link
|
||||||
var nodes []node
|
var nodes []node
|
||||||
|
|
||||||
d := getDevices(conf.Unms.DevicesURL)
|
d := getDevices(conf.Unms.DevicesURL)
|
||||||
|
|
||||||
// API CALL 1
|
// API CALL 1 (get Device overview)
|
||||||
log.Println("calling API 1")
|
log.Println("Starting UISP API Crawler for Rifu devices")
|
||||||
|
log.Println("Getting device overview from UNMS API")
|
||||||
var u []unifiAPIResponse
|
var u []unifiAPIResponse
|
||||||
err := UnmsCallAPI("/devices", &u)
|
if err := UnmsCallAPI("/devices", &u); err != nil {
|
||||||
if err != nil {
|
return nil, nil, err
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range d.Devices {
|
for i := range d.Devices {
|
||||||
@ -41,20 +41,22 @@ func processUNMSAPI() ([]node, []link) {
|
|||||||
currentDevice = d.Devices[i]
|
currentDevice = d.Devices[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isOnline := dev.Overview.Status == "active"
|
isOnline := dev.Overview.Status == "active"
|
||||||
// END OF API CALL 1
|
// END OF API CALL 1
|
||||||
|
|
||||||
// API CALL 2
|
// Getting details from UISP
|
||||||
log.Println("calling API 2 for device", d.Devices[i].Name)
|
log.Println("Getting device details for: ", d.Devices[i].Name)
|
||||||
var details unifiAPIDetails
|
var details unifiAPIDetails
|
||||||
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details)
|
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
|
||||||
// END OF API CALL 2
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// API CALL 3
|
// Getting details for RiFu
|
||||||
log.Println("calling API 3 for device", d.Devices[i].Name)
|
log.Println("Getting details for RiFu Link for: ", d.Devices[i].Name)
|
||||||
var airmaxes []unifiAPIAirmax
|
var airmaxes []unifiAPIAirmax
|
||||||
UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes)
|
if err := UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
// check if remote mac address is part of our published network
|
// check if remote mac address is part of our published network
|
||||||
for i := range airmaxes {
|
for i := range airmaxes {
|
||||||
if isRemoteMACpublished(airmaxes[i].DeviceIdentification.MAC, d.Devices) {
|
if isRemoteMACpublished(airmaxes[i].DeviceIdentification.MAC, d.Devices) {
|
||||||
@ -98,7 +100,7 @@ func processUNMSAPI() ([]node, []link) {
|
|||||||
Model: details.Identification.Model,
|
Model: details.Identification.Model,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nodes, links
|
return nodes, links, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processUNMSAPIRouter() ([]node, error) {
|
func processUNMSAPIRouter() ([]node, error) {
|
||||||
@ -107,13 +109,11 @@ func processUNMSAPIRouter() ([]node, error) {
|
|||||||
d := getDevices(conf.Unms.RouterURL)
|
d := getDevices(conf.Unms.RouterURL)
|
||||||
|
|
||||||
// API CALL 1, get all devices list from UNMS
|
// API CALL 1, get all devices list from UNMS
|
||||||
log.Println("Get all devices from UNMS")
|
log.Println("Get all Routers from UISP")
|
||||||
var u []unifiAPIResponse
|
var u []unifiAPIResponse
|
||||||
err := UnmsCallAPI("/devices", &u)
|
if err := UnmsCallAPI("/devices", &u); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// END OF API CALL 1
|
|
||||||
|
|
||||||
// Get Information for devices device
|
// Get Information for devices device
|
||||||
for i := range d.Devices {
|
for i := range d.Devices {
|
||||||
@ -129,14 +129,14 @@ func processUNMSAPIRouter() ([]node, error) {
|
|||||||
isOnline := dev.Overview.Status == "active"
|
isOnline := dev.Overview.Status == "active"
|
||||||
|
|
||||||
// API CALL FOR ROUTER DETAILS (Interface RX/TX)
|
// API CALL FOR ROUTER DETAILS (Interface RX/TX)
|
||||||
log.Println("Getting details of ", d.Devices[i].Name, "from UNMS API")
|
log.Println("Getting details of ", d.Devices[i].Name, "from UISP API")
|
||||||
var details unifiAPIDetails
|
var details unifiAPIDetails
|
||||||
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
|
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// API CALL FOR DEVICE STATISTICS (CPU, RAM)
|
// API CALL FOR DEVICE STATISTICS (CPU, RAM)
|
||||||
log.Println("Getting statistics of ", d.Devices[i].Name, "from UNMS API")
|
log.Println("Getting statistics of ", d.Devices[i].Name, "from UISP API")
|
||||||
var statistics UNMSstatistics
|
var statistics UNMSstatistics
|
||||||
if err := UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics); err != nil {
|
if err := UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user