Compare commits

..

No commits in common. "c8c7c9e9383ae4a173b0c0c66ac80445d3dd9b58" and "c9b496d5eb3b3982f1c1260b18a6494617a8ee39" have entirely different histories.

5 changed files with 56 additions and 105 deletions

View File

@ -1,17 +1,12 @@
# Freifunk Meshviewer Unifi Access Points und Richtfunkstrecken import
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
Dieses tool Importiert Nodes für die Freifunk Map aus den APIs UNMS (Richtfunk) & Unifi (Access Points)
## Config
### Unifi Access Points (unifi_devices.json)
### Unifi Access Points (ucDevices.json)
In der Datei unifi_devices.json können die Access Points gepflegt werden, die auf der Freifunk Map erscheinen sollen.
In der Datei ucDevices.json können die Access Points gepflegt werden, die auf der Freifunk Map erscheinen sollen.
Hierzu muss die Datei im json Format erweitert werden.
@ -37,9 +32,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)
### UISP Richtfunkstrecken
### UNMS Richtfunkstrecken
In der Datei rifu_devices.json können die Richtfunkstrecken gepflegt werden, die auf der Freifunk Map erscheinen sollen.
In der Datei devices.json können die Richtfunkstrecken gepflegt werden, die auf der Freifunk Map erscheinen sollen.
```json
{
@ -61,44 +56,11 @@ 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,16 +51,29 @@ 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, err := processUNMSAPI()
if err != nil {
return err
}
unmsNodes, unmsLinks := processUNMSAPI()
unmsRouters, err := processUNMSAPIRouter()
if err != nil {
return err
@ -71,10 +84,7 @@ func processAPIs() error {
}
if conf.Unifi.Enabled {
log.Println("Processing Unifi")
ucNodes, _, err := processUcAPIs()
if err != nil {
return err
}
ucNodes, _ := processUcAPIs()
nodes = append(nodes, ucNodes...)
}
if conf.Meshviewer.Enabled {
@ -112,24 +122,6 @@ 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,6 +133,7 @@ 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, error) {
func processUcAPIs() ([]node, []link) {
//get list of Unifi devices to display
var nodes []node
var links []link
@ -22,18 +22,16 @@ func processUcAPIs() ([]node, []link, error) {
//call Unifi Controller
ucAPI := UnifiNewAPI(conf.Unifi.User, conf.Unifi.Password, conf.Unifi.APIURL)
//login
if err := ucAPI.ucLogin(); err != nil {
return nil, nil, err
}
ucAPI.ucLogin()
//get all Sites from Controller
sites, err := ucAPI.ucGetSites()
if err != nil {
return nil, nil, err
log.Println(err)
}
//get all devices in all sites
devices, err := ucAPI.ucGetDevices(sites)
if err != nil {
return nil, nil, err
log.Println(err)
}
//build nodes struct
@ -41,7 +39,6 @@ func processUcAPIs() ([]node, []link, error) {
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
@ -56,15 +53,14 @@ func processUcAPIs() ([]node, []link, error) {
}
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
if err != nil {
log.Println("Error psrsing CPU load from ", currentDevice.Name)
log.Println(err)
fmt.Println("Error: ", currentDevice.Name)
//log.Fatalln(err)
load = 0
}
mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64)
if err != nil {
log.Println("Error psrsing CPU load from ", currentDevice.Name)
log.Println(err)
mem = 0
//log.Fatalln(err)
load = 0
}
var model = lookupModels(currentDevice.Model)
var clients int
@ -105,7 +101,7 @@ func processUcAPIs() ([]node, []link, error) {
Model: model,
})
}
return nodes, links, err
return nodes, links
}
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, error) {
func processUNMSAPI() ([]node, []link) {
// Variables for runtime
var links []link
var nodes []node
d := getDevices(conf.Unms.DevicesURL)
// API CALL 1 (get Device overview)
log.Println("Starting UISP API Crawler for Rifu devices")
log.Println("Getting device overview from UNMS API")
// API CALL 1
log.Println("calling API 1")
var u []unifiAPIResponse
if err := UnmsCallAPI("/devices", &u); err != nil {
return nil, nil, err
err := UnmsCallAPI("/devices", &u)
if err != nil {
log.Fatalln(err)
}
for i := range d.Devices {
@ -41,22 +41,20 @@ func processUNMSAPI() ([]node, []link, error) {
currentDevice = d.Devices[i]
}
}
isOnline := dev.Overview.Status == "active"
// END OF API CALL 1
// Getting details from UISP
log.Println("Getting device details for: ", d.Devices[i].Name)
// API CALL 2
log.Println("calling API 2 for device", d.Devices[i].Name)
var details unifiAPIDetails
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
return nil, nil, err
}
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details)
// END OF API CALL 2
// Getting details for RiFu
log.Println("Getting details for RiFu Link for: ", d.Devices[i].Name)
// API CALL 3
log.Println("calling API 3 for device", d.Devices[i].Name)
var airmaxes []unifiAPIAirmax
if err := UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes); err != nil {
return nil, nil, err
}
UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes)
// check if remote mac address is part of our published network
for i := range airmaxes {
if isRemoteMACpublished(airmaxes[i].DeviceIdentification.MAC, d.Devices) {
@ -100,7 +98,7 @@ func processUNMSAPI() ([]node, []link, error) {
Model: details.Identification.Model,
})
}
return nodes, links, nil
return nodes, links
}
func processUNMSAPIRouter() ([]node, error) {
@ -109,11 +107,13 @@ func processUNMSAPIRouter() ([]node, error) {
d := getDevices(conf.Unms.RouterURL)
// API CALL 1, get all devices list from UNMS
log.Println("Get all Routers from UISP")
log.Println("Get all devices from UNMS")
var u []unifiAPIResponse
if err := UnmsCallAPI("/devices", &u); err != nil {
err := UnmsCallAPI("/devices", &u)
if 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 UISP API")
log.Println("Getting details of ", d.Devices[i].Name, "from UNMS 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 UISP API")
log.Println("Getting statistics of ", d.Devices[i].Name, "from UNMS API")
var statistics UNMSstatistics
if err := UnmsCallAPI("/devices/"+dev.Identification.ID+"/statistics?interval=hour", &statistics); err != nil {
return nil, err