Compare commits
No commits in common. "c8c7c9e9383ae4a173b0c0c66ac80445d3dd9b58" and "c9b496d5eb3b3982f1c1260b18a6494617a8ee39" have entirely different histories.
c8c7c9e938
...
c9b496d5eb
48
README.md
48
README.md
@ -1,17 +1,12 @@
|
|||||||
# 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 UISP (Richtfunk) & Unifi (Access Points).
|
Dieses tool Importiert Nodes für die Freifunk Map aus den APIs UNMS (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 (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.
|
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.
|
* 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)
|
||||||
|
|
||||||
### 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
|
```json
|
||||||
{
|
{
|
||||||
@ -61,44 +56,11 @@ 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,16 +51,29 @@ 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, err := processUNMSAPI()
|
unmsNodes, unmsLinks := processUNMSAPI()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
unmsRouters, err := processUNMSAPIRouter()
|
unmsRouters, err := processUNMSAPIRouter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,10 +84,7 @@ func processAPIs() error {
|
|||||||
}
|
}
|
||||||
if conf.Unifi.Enabled {
|
if conf.Unifi.Enabled {
|
||||||
log.Println("Processing Unifi")
|
log.Println("Processing Unifi")
|
||||||
ucNodes, _, err := processUcAPIs()
|
ucNodes, _ := processUcAPIs()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nodes = append(nodes, ucNodes...)
|
nodes = append(nodes, ucNodes...)
|
||||||
}
|
}
|
||||||
if conf.Meshviewer.Enabled {
|
if conf.Meshviewer.Enabled {
|
||||||
@ -112,24 +122,6 @@ 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,6 +133,7 @@ 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, error) {
|
func processUcAPIs() ([]node, []link) {
|
||||||
//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,18 +22,16 @@ func processUcAPIs() ([]node, []link, error) {
|
|||||||
//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
|
||||||
if err := ucAPI.ucLogin(); err != nil {
|
ucAPI.ucLogin()
|
||||||
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 {
|
||||||
return nil, nil, err
|
log.Println(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 {
|
||||||
return nil, nil, err
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//build nodes struct
|
//build nodes struct
|
||||||
@ -41,7 +39,6 @@ func processUcAPIs() ([]node, []link, error) {
|
|||||||
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
|
||||||
@ -56,15 +53,14 @@ func processUcAPIs() ([]node, []link, error) {
|
|||||||
}
|
}
|
||||||
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
|
load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error psrsing CPU load from ", currentDevice.Name)
|
fmt.Println("Error: ", currentDevice.Name)
|
||||||
log.Println(err)
|
//log.Fatalln(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.Println("Error psrsing CPU load from ", currentDevice.Name)
|
//log.Fatalln(err)
|
||||||
log.Println(err)
|
load = 0
|
||||||
mem = 0
|
|
||||||
}
|
}
|
||||||
var model = lookupModels(currentDevice.Model)
|
var model = lookupModels(currentDevice.Model)
|
||||||
var clients int
|
var clients int
|
||||||
@ -105,7 +101,7 @@ func processUcAPIs() ([]node, []link, error) {
|
|||||||
Model: model,
|
Model: model,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nodes, links, err
|
return nodes, links
|
||||||
}
|
}
|
||||||
|
|
||||||
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, error) {
|
func processUNMSAPI() ([]node, []link) {
|
||||||
// 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 (get Device overview)
|
// API CALL 1
|
||||||
log.Println("Starting UISP API Crawler for Rifu devices")
|
log.Println("calling API 1")
|
||||||
log.Println("Getting device overview from UNMS API")
|
|
||||||
var u []unifiAPIResponse
|
var u []unifiAPIResponse
|
||||||
if err := UnmsCallAPI("/devices", &u); err != nil {
|
err := UnmsCallAPI("/devices", &u)
|
||||||
return nil, nil, err
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range d.Devices {
|
for i := range d.Devices {
|
||||||
@ -41,22 +41,20 @@ func processUNMSAPI() ([]node, []link, error) {
|
|||||||
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
|
||||||
|
|
||||||
// Getting details from UISP
|
// API CALL 2
|
||||||
log.Println("Getting device details for: ", d.Devices[i].Name)
|
log.Println("calling API 2 for device", d.Devices[i].Name)
|
||||||
var details unifiAPIDetails
|
var details unifiAPIDetails
|
||||||
if err := UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details); err != nil {
|
UnmsCallAPI("/devices/erouters/"+dev.Identification.ID, &details)
|
||||||
return nil, nil, err
|
// END OF API CALL 2
|
||||||
}
|
|
||||||
|
|
||||||
// Getting details for RiFu
|
// API CALL 3
|
||||||
log.Println("Getting details for RiFu Link for: ", d.Devices[i].Name)
|
log.Println("calling API 3 for device", d.Devices[i].Name)
|
||||||
var airmaxes []unifiAPIAirmax
|
var airmaxes []unifiAPIAirmax
|
||||||
if err := UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes); err != nil {
|
UnmsCallAPI("/devices/airmaxes/"+dev.Identification.ID+"/stations", &airmaxes)
|
||||||
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) {
|
||||||
@ -100,7 +98,7 @@ func processUNMSAPI() ([]node, []link, error) {
|
|||||||
Model: details.Identification.Model,
|
Model: details.Identification.Model,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nodes, links, nil
|
return nodes, links
|
||||||
}
|
}
|
||||||
|
|
||||||
func processUNMSAPIRouter() ([]node, error) {
|
func processUNMSAPIRouter() ([]node, error) {
|
||||||
@ -109,11 +107,13 @@ 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 Routers from UISP")
|
log.Println("Get all devices from UNMS")
|
||||||
var u []unifiAPIResponse
|
var u []unifiAPIResponse
|
||||||
if err := UnmsCallAPI("/devices", &u); err != nil {
|
err := UnmsCallAPI("/devices", &u)
|
||||||
|
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 UISP API")
|
log.Println("Getting details of ", d.Devices[i].Name, "from UNMS 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 UISP API")
|
log.Println("Getting statistics of ", d.Devices[i].Name, "from UNMS 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