Compare commits

..

2 Commits

Author SHA1 Message Date
c8c7c9e938
Error Handling
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-14 11:44:20 +02:00
21157e5fb4
Readme angepasst 2023-05-14 11:44:11 +02:00
5 changed files with 105 additions and 56 deletions

View File

@ -1,12 +1,17 @@
# 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
### 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.
@ -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.
* 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
{
@ -56,11 +61,44 @@ Erklärung:
* gateway: Im Normalfall die NodeID des Supernodes (zu finden in der MAP)
* 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
Es gibt 3 Module die Ein/Ausgeschatet werden können:
* UNMS
* Unifi
* 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.

48
main.go
View File

@ -38,12 +38,12 @@ func main() {
// start API processing (runs in a loop)
go func() {
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)
for range tick {
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()
}
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 {
var nodes []node
var links []link
if conf.Unms.Enabled {
log.Println("Processing UNMS")
unmsNodes, unmsLinks := processUNMSAPI()
unmsNodes, unmsLinks, err := processUNMSAPI()
if err != nil {
return err
}
unmsRouters, err := processUNMSAPIRouter()
if err != nil {
return err
@ -84,7 +71,10 @@ func processAPIs() error {
}
if conf.Unifi.Enabled {
log.Println("Processing Unifi")
ucNodes, _ := processUcAPIs()
ucNodes, _, err := processUcAPIs()
if err != nil {
return err
}
nodes = append(nodes, ucNodes...)
}
if conf.Meshviewer.Enabled {
@ -122,6 +112,24 @@ func processAPIs() error {
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
func getFile(url string) []byte {
resp, err := http.Get(url)

View File

@ -133,7 +133,6 @@ func getMeshviewer() ([]node, []link) {
var links []link
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)
if err != nil {
return nodes, links

View File

@ -13,7 +13,7 @@ import (
)
// Unifi Controller API processing
func processUcAPIs() ([]node, []link) {
func processUcAPIs() ([]node, []link, error) {
//get list of Unifi devices to display
var nodes []node
var links []link
@ -22,16 +22,18 @@ func processUcAPIs() ([]node, []link) {
//call Unifi Controller
ucAPI := UnifiNewAPI(conf.Unifi.User, conf.Unifi.Password, conf.Unifi.APIURL)
//login
ucAPI.ucLogin()
if err := ucAPI.ucLogin(); err != nil {
return nil, nil, err
}
//get all Sites from Controller
sites, err := ucAPI.ucGetSites()
if err != nil {
log.Println(err)
return nil, nil, err
}
//get all devices in all sites
devices, err := ucAPI.ucGetDevices(sites)
if err != nil {
log.Println(err)
return nil, nil, err
}
//build nodes struct
@ -39,6 +41,7 @@ func processUcAPIs() ([]node, []link) {
for _, jsonDevice := range d.Devices {
var currentDevice ucDevice
var currentJSONDevice device
isOnline := currentDevice.State == 1
for _, device := range devices {
if strings.EqualFold(device.Mac, jsonDevice.MAC) {
currentDevice = device
@ -53,14 +56,15 @@ func processUcAPIs() ([]node, []link) {
}
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
if err != nil {
fmt.Println("Error: ", currentDevice.Name)
//log.Fatalln(err)
log.Println("Error psrsing CPU load from ", currentDevice.Name)
log.Println(err)
load = 0
}
mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64)
if err != nil {
//log.Fatalln(err)
load = 0
log.Println("Error psrsing CPU load from ", currentDevice.Name)
log.Println(err)
mem = 0
}
var model = lookupModels(currentDevice.Model)
var clients int
@ -101,7 +105,7 @@ func processUcAPIs() ([]node, []link) {
Model: model,
})
}
return nodes, links
return nodes, links, err
}
func UnifiNewAPI(user string, pass string, baseURL string) UnifiAPIData {

42
unms.go
View File

@ -17,19 +17,19 @@ import (
)
// UNMS API processing (Richtfunk)
func processUNMSAPI() ([]node, []link) {
func processUNMSAPI() ([]node, []link, error) {
// Variables for runtime
var links []link
var nodes []node
d := getDevices(conf.Unms.DevicesURL)
// API CALL 1
log.Println("calling API 1")
// API CALL 1 (get Device overview)
log.Println("Starting UISP API Crawler for Rifu devices")
log.Println("Getting device overview from UNMS API")
var u []unifiAPIResponse
err := UnmsCallAPI("/devices", &u)
if err != nil {
log.Fatalln(err)
if err := UnmsCallAPI("/devices", &u); err != nil {
return nil, nil, err
}
for i := range d.Devices {
@ -41,20 +41,22 @@ func processUNMSAPI() ([]node, []link) {
currentDevice = d.Devices[i]
}
}
isOnline := dev.Overview.Status == "active"
// END OF API CALL 1
// API CALL 2
log.Println("calling API 2 for device", d.Devices[i].Name)
// Getting details from UISP
log.Println("Getting device details for: ", d.Devices[i].Name)
var details unifiAPIDetails
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details)
// END OF API CALL 2
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
return nil, nil, err
}
// API CALL 3
log.Println("calling API 3 for device", d.Devices[i].Name)
// Getting details for RiFu
log.Println("Getting details for RiFu Link for: ", d.Devices[i].Name)
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
for i := range airmaxes {
if isRemoteMACpublished(airmaxes[i].DeviceIdentification.MAC, d.Devices) {
@ -98,7 +100,7 @@ func processUNMSAPI() ([]node, []link) {
Model: details.Identification.Model,
})
}
return nodes, links
return nodes, links, nil
}
func processUNMSAPIRouter() ([]node, error) {
@ -107,13 +109,11 @@ func processUNMSAPIRouter() ([]node, error) {
d := getDevices(conf.Unms.RouterURL)
// 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
err := UnmsCallAPI("/devices", &u)
if err != nil {
if err := UnmsCallAPI("/devices", &u); err != nil {
return nil, err
}
// END OF API CALL 1
// Get Information for devices device
for i := range d.Devices {
@ -129,14 +129,14 @@ func processUNMSAPIRouter() ([]node, error) {
isOnline := dev.Overview.Status == "active"
// 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
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
return nil, err
}
// 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
if err := UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics); err != nil {
return nil, err