Compare commits
	
		
			2 Commits
		
	
	
		
			6ee0cb4cf1
			...
			7d27e69400
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 7d27e69400 | ||
|  | aebb7729ba | 
							
								
								
									
										394
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										394
									
								
								main.go
									
									
									
									
									
								
							| @ -1,6 +1,7 @@ | |||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"flag" | 	"flag" | ||||||
| @ -8,7 +9,9 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"log" | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/http/cookiejar" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| @ -16,12 +19,15 @@ import ( | |||||||
| // types
 | // types
 | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	baseURL = "https://unifi.freifunk-troisdorf.de/v2.1" | 	baseURL   = "https://unifi.freifunk-troisdorf.de/v2.1" | ||||||
| 	iso8601 = "2006-01-02T15:04:05-0700" | 	ucBaseURL = "https://unifi.freifunk-troisdorf.de:8443" | ||||||
|  | 	iso8601   = "2006-01-02T15:04:05-0700" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // flags
 | // flags
 | ||||||
| var token = flag.String("token", "", "Defines the x-auth-token") | var token = flag.String("token", "", "Defines the x-auth-token") | ||||||
|  | var ucUser = flag.String("ucUser", "", "Defines the Unifi API User") | ||||||
|  | var ucPass = flag.String("ucPass", "", "Defines the Unifi API Password") | ||||||
| var version = "development" | var version = "development" | ||||||
| var delay time.Duration = 60 * time.Second | var delay time.Duration = 60 * time.Second | ||||||
| 
 | 
 | ||||||
| @ -33,7 +39,12 @@ func main() { | |||||||
| 	if *token == "" { | 	if *token == "" { | ||||||
| 		log.Fatalln("Please specify an API token via the flag '-token'") | 		log.Fatalln("Please specify an API token via the flag '-token'") | ||||||
| 	} | 	} | ||||||
| 
 | 	if *ucPass == "" { | ||||||
|  | 		log.Fatalln("Please specify an API Password via the flag '-ucPass'") | ||||||
|  | 	} | ||||||
|  | 	if *ucUser == "" { | ||||||
|  | 		log.Fatalln("Please specify an API User via the flag '-ucUser'") | ||||||
|  | 	} | ||||||
| 	// start API processing (runs in a loop)
 | 	// start API processing (runs in a loop)
 | ||||||
| 	go processAPIs() | 	go processAPIs() | ||||||
| 
 | 
 | ||||||
| @ -41,95 +52,215 @@ func main() { | |||||||
| 	serveJSON() | 	serveJSON() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func lookupModels(model string) string { | ||||||
|  | 	switch model { | ||||||
|  | 	case "BZ2", "U2S48", "U2Sv2": | ||||||
|  | 		return "Unifi AP" | ||||||
|  | 	case "BZ2LR", "U2L48", "U2Lv2": | ||||||
|  | 		return "UniFi AP-LR" | ||||||
|  | 	case "U7E", "U7Ev2": | ||||||
|  | 		return "UniFi AP-AC" | ||||||
|  | 	case "U7HD", "U7SHD": | ||||||
|  | 		return "UniFi AP-HD" | ||||||
|  | 	case "UXSDM": | ||||||
|  | 		return "UniFi AP-BaseStationXG" | ||||||
|  | 	case "UCMSH": | ||||||
|  | 		return "AP-MeshXG" | ||||||
|  | 	case "U7MP": | ||||||
|  | 		return "AP-AC-Mesh-Pro" | ||||||
|  | 	case "U7LR": | ||||||
|  | 		return "UniFi AP-AC-LR" | ||||||
|  | 	case "U7LT": | ||||||
|  | 		return "UniFi AP-AC-Lite" | ||||||
|  | 	case "U7P": | ||||||
|  | 		return "UniFi AP-Pro" | ||||||
|  | 	case "U7MSH": | ||||||
|  | 		return "UniFi AP-AC-Mesh" | ||||||
|  | 	case "U7PG2": | ||||||
|  | 		return "UniFi AP-AC-Pro" | ||||||
|  | 	default: | ||||||
|  | 		return "Unifi Gerät" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func itob(i int) bool { | ||||||
|  | 	if i == 1 { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func processUcAPIs() []node { | ||||||
|  | 	var nodes []node | ||||||
|  | 	d, err := getDevices("ucDevices.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  | 	ucAPI := newAPI(*ucUser, *ucPass, ucBaseURL) | ||||||
|  | 	ucAPI.ucLogin() | ||||||
|  | 	sites, err := ucAPI.ucGetSites() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	devices, err := ucAPI.ucGetDevices(sites) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	for _, jsonDevice := range d.Devices { | ||||||
|  | 		var currentDevice ucDevice | ||||||
|  | 		var currentJSONDevice device | ||||||
|  | 		for _, device := range devices { | ||||||
|  | 			if strings.ToUpper(device.Mac) == strings.ToUpper(jsonDevice.MAC) { | ||||||
|  | 				currentDevice = device | ||||||
|  | 				currentJSONDevice = jsonDevice | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 		mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		nodes = append(nodes, node{ | ||||||
|  | 			Firstseen:      "0", | ||||||
|  | 			Lastseen:       time.Unix(int64(currentDevice.LastSeen), 0).Format(iso8601), | ||||||
|  | 			IsOnline:       itob(currentDevice.State), | ||||||
|  | 			IsGateway:      false, | ||||||
|  | 			Clients:        0, | ||||||
|  | 			ClientsWifi24:  0, | ||||||
|  | 			ClientsWifi5:   0, | ||||||
|  | 			ClientsOther:   0, | ||||||
|  | 			RootFSUsage:    0, | ||||||
|  | 			LoadAVG:        load / 100, | ||||||
|  | 			MemoryUsage:    mem / 100, | ||||||
|  | 			Uptime:         time.Now().Add(-1 * time.Second * time.Duration(currentDevice.Uptime)).Format(iso8601), | ||||||
|  | 			GatewayNexthop: currentJSONDevice.GatewayNexthop, | ||||||
|  | 			Gateway:        currentJSONDevice.Gateway, | ||||||
|  | 			Location:       currentJSONDevice.Location, | ||||||
|  | 			NodeID:         strings.ReplaceAll(currentDevice.Mac, ":", ""), | ||||||
|  | 			MAC:            currentDevice.Mac, | ||||||
|  | 			Adresses:       []string{currentDevice.IP}, | ||||||
|  | 			Domain:         currentJSONDevice.Domain, | ||||||
|  | 			Hostname:       "[Unifi] " + currentDevice.Name, | ||||||
|  | 			Owner:          "Freifunk Rhein-Sieg", | ||||||
|  | 			Firmware: firmware{ | ||||||
|  | 				Base:    "Ubiquiti - Stock", | ||||||
|  | 				Release: currentDevice.Version, | ||||||
|  | 			}, | ||||||
|  | 			Autoupdater: autoupdater{ | ||||||
|  | 				Enabled: false, | ||||||
|  | 				Branch:  "stable", | ||||||
|  | 			}, | ||||||
|  | 			NProc: 1, | ||||||
|  | 			Model: lookupModels(currentDevice.Model), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	return nodes | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func processUNMSAPI() ([]node, []link) { | ||||||
|  | 	// Variables for runtime
 | ||||||
|  | 	var links []link | ||||||
|  | 	var nodes []node | ||||||
|  | 
 | ||||||
|  | 	d, err := getDevices("devices.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// API CALL 1
 | ||||||
|  | 	log.Println("calling API 1") | ||||||
|  | 	var u []unifiAPIResponse | ||||||
|  | 	err = callUnifiAPI("/devices", &u) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i := range d.Devices { | ||||||
|  | 		var dev unifiAPIResponse | ||||||
|  | 		var currentDevice device | ||||||
|  | 		for j := range u { | ||||||
|  | 			if strings.ToUpper(u[j].Identification.MAC) == strings.ToUpper(d.Devices[i].MAC) { | ||||||
|  | 				dev = u[j] | ||||||
|  | 				currentDevice = d.Devices[i] | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		var isOnline bool = false | ||||||
|  | 		if dev.Overview.Status == "active" { | ||||||
|  | 			isOnline = true | ||||||
|  | 		} | ||||||
|  | 		// END OF API CALL 1
 | ||||||
|  | 
 | ||||||
|  | 		// API CALL 2
 | ||||||
|  | 		log.Println("calling API 2 for device", d.Devices[i].Name) | ||||||
|  | 		var details unifiAPIDetails | ||||||
|  | 		callUnifiAPI("/devices/erouters/"+dev.Identification.ID, &details) | ||||||
|  | 		// END OF API CALL 2
 | ||||||
|  | 
 | ||||||
|  | 		// API CALL 3
 | ||||||
|  | 		log.Println("calling API 3 for device", d.Devices[i].Name) | ||||||
|  | 		var airmaxes []unifiAPIAirmax | ||||||
|  | 		callUnifiAPI("/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) == true { | ||||||
|  | 				links = addLink(dev, airmaxes[i], links) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// END OF API CALL 3
 | ||||||
|  | 
 | ||||||
|  | 		// Get info from json file (static)
 | ||||||
|  | 		nodes = append(nodes, node{ | ||||||
|  | 			Firstseen:      dev.Overview.CreatedAt.Format(iso8601), | ||||||
|  | 			Lastseen:       dev.Overview.LastSeen.Format(iso8601), | ||||||
|  | 			IsOnline:       isOnline, | ||||||
|  | 			IsGateway:      false, | ||||||
|  | 			Clients:        0, | ||||||
|  | 			ClientsWifi24:  0, | ||||||
|  | 			ClientsWifi5:   0, | ||||||
|  | 			ClientsOther:   0, | ||||||
|  | 			RootFSUsage:    0, | ||||||
|  | 			LoadAVG:        details.Overview.CPU / 100, | ||||||
|  | 			MemoryUsage:    details.Overview.RAM / 100, | ||||||
|  | 			Uptime:         dev.Identification.Started.Format(iso8601), | ||||||
|  | 			GatewayNexthop: currentDevice.GatewayNexthop, | ||||||
|  | 			Gateway:        currentDevice.Gateway, | ||||||
|  | 			Location:       currentDevice.Location, | ||||||
|  | 			NodeID:         strings.ReplaceAll(dev.Identification.MAC, ":", ""), | ||||||
|  | 			MAC:            dev.Identification.MAC, | ||||||
|  | 			Adresses:       getAddresses(details.IPAddress), | ||||||
|  | 			Domain:         currentDevice.Domain, | ||||||
|  | 			Hostname:       "[RiFu] " + details.Identification.Name, | ||||||
|  | 			Owner:          "Freifunk Rhein-Sieg", | ||||||
|  | 			Firmware: firmware{ | ||||||
|  | 				Base:    "Ubiquiti - Stock", | ||||||
|  | 				Release: details.Firmware.Current, | ||||||
|  | 			}, | ||||||
|  | 			Autoupdater: autoupdater{ | ||||||
|  | 				Enabled: false, | ||||||
|  | 				Branch:  "stable", | ||||||
|  | 			}, | ||||||
|  | 			NProc: 1, | ||||||
|  | 			Model: details.Identification.Model, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	return nodes, links | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func processAPIs() { | func processAPIs() { | ||||||
| 	tick := time.Tick(delay) | 	tick := time.Tick(delay) | ||||||
| 	for range tick { | 	for range tick { | ||||||
| 		// Variables for runtime
 |  | ||||||
| 		var links []link |  | ||||||
| 		var nodes []node | 		var nodes []node | ||||||
|  | 		var links []link | ||||||
| 
 | 
 | ||||||
| 		d, err := getDevices() | 		unmsNodes, links := processUNMSAPI() | ||||||
| 		if err != nil { | 		ucNodes := processUcAPIs() | ||||||
| 			log.Fatalln(err) | 		nodes = append(nodes, unmsNodes...) | ||||||
| 		} | 		nodes = append(nodes, ucNodes...) | ||||||
| 
 |  | ||||||
| 		// API CALL 1
 |  | ||||||
| 		log.Println("calling API 1") |  | ||||||
| 		var u []unifiAPIResponse |  | ||||||
| 		err = callUnifiAPI("/devices", &u) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalln(err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for i := range d.Devices { |  | ||||||
| 			var dev unifiAPIResponse |  | ||||||
| 			var currentDevice device |  | ||||||
| 			for j := range u { |  | ||||||
| 				if strings.ToUpper(u[j].Identification.MAC) == strings.ToUpper(d.Devices[i].MAC) { |  | ||||||
| 					dev = u[j] |  | ||||||
| 					currentDevice = d.Devices[i] |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			var isOnline bool = false |  | ||||||
| 			if dev.Overview.Status == "active" { |  | ||||||
| 				isOnline = true |  | ||||||
| 			} |  | ||||||
| 			// END OF API CALL 1
 |  | ||||||
| 
 |  | ||||||
| 			// API CALL 2
 |  | ||||||
| 			log.Println("calling API 2 for device", d.Devices[i].Name) |  | ||||||
| 			var details unifiAPIDetails |  | ||||||
| 			callUnifiAPI("/devices/erouters/"+dev.Identification.ID, &details) |  | ||||||
| 			// END OF API CALL 2
 |  | ||||||
| 
 |  | ||||||
| 			// API CALL 3
 |  | ||||||
| 			log.Println("calling API 3 for device", d.Devices[i].Name) |  | ||||||
| 			var airmaxes []unifiAPIAirmax |  | ||||||
| 			callUnifiAPI("/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) == true { |  | ||||||
| 					links = addLink(dev, airmaxes[i], links) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			// END OF API CALL 3
 |  | ||||||
| 
 |  | ||||||
| 			// Get info from json file (static)
 |  | ||||||
| 			nodes = append(nodes, node{ |  | ||||||
| 				Firstseen:      dev.Overview.CreatedAt.Format(iso8601), |  | ||||||
| 				Lastseen:       dev.Overview.LastSeen.Format(iso8601), |  | ||||||
| 				IsOnline:       isOnline, |  | ||||||
| 				IsGateway:      false, |  | ||||||
| 				Clients:        0, |  | ||||||
| 				ClientsWifi24:  0, |  | ||||||
| 				ClientsWifi5:   0, |  | ||||||
| 				ClientsOther:   0, |  | ||||||
| 				RootFSUsage:    0, |  | ||||||
| 				LoadAVG:        details.Overview.CPU / 100, |  | ||||||
| 				MemoryUsage:    details.Overview.RAM / 100, |  | ||||||
| 				Uptime:         dev.Identification.Started.Format(iso8601), |  | ||||||
| 				GatewayNexthop: currentDevice.GatewayNexthop, |  | ||||||
| 				Gateway:        currentDevice.Gateway, |  | ||||||
| 				Location:       currentDevice.Location, |  | ||||||
| 				NodeID:         strings.ReplaceAll(dev.Identification.MAC, ":", ""), |  | ||||||
| 				MAC:            dev.Identification.MAC, |  | ||||||
| 				Adresses:       getAddresses(details.IPAddress), |  | ||||||
| 				Domain:         currentDevice.Domain, |  | ||||||
| 				Hostname:       "[RiFu] " + details.Identification.Name, |  | ||||||
| 				Owner:          "Freifunk Rhein-Sieg", |  | ||||||
| 				Firmware: firmware{ |  | ||||||
| 					Base:    "Ubiquiti - Stock", |  | ||||||
| 					Release: details.Firmware.Current, |  | ||||||
| 				}, |  | ||||||
| 				Autoupdater: autoupdater{ |  | ||||||
| 					Enabled: false, |  | ||||||
| 					Branch:  "stable", |  | ||||||
| 				}, |  | ||||||
| 				NProc: 1, |  | ||||||
| 				Model: details.Identification.Model, |  | ||||||
| 			}) |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		// assemble final struct
 | 		// assemble final struct
 | ||||||
| 		o := output{ | 		o := output{ | ||||||
| @ -150,9 +281,9 @@ func processAPIs() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getDevices() (devices, error) { | func getDevices(file string) (devices, error) { | ||||||
| 	// get devices from JSON file
 | 	// get devices from JSON file
 | ||||||
| 	jsonFile, err := os.Open("devices.json") | 	jsonFile, err := os.Open(file) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return devices{}, errors.New("can't open devices.json") | 		return devices{}, errors.New("can't open devices.json") | ||||||
| 	} | 	} | ||||||
| @ -242,3 +373,88 @@ func serveJSON() { | |||||||
| 		log.Fatalln(err) | 		log.Fatalln(err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func httpClient() *http.Client { | ||||||
|  | 	jar, err := cookiejar.New(nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	client := &http.Client{Jar: jar} | ||||||
|  | 	return client | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newAPI(user string, pass string, baseURL string) ucAPIData { | ||||||
|  | 	return ucAPIData{ | ||||||
|  | 		user:    user, | ||||||
|  | 		pass:    pass, | ||||||
|  | 		baseURL: baseURL, | ||||||
|  | 		client:  httpClient(), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *ucAPIData) ucCallAPI(url string, method string, body *bytes.Buffer, output interface{}) error { | ||||||
|  | 	req, err := http.NewRequest(method, u.baseURL+url, body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("can't set request %s", u.baseURL+url) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	req.Header.Set("Content-Type", "application/json") | ||||||
|  | 	response, err := u.client.Do(req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("can't login %s", u.baseURL+url) | ||||||
|  | 	} | ||||||
|  | 	defer response.Body.Close() | ||||||
|  | 	if response.StatusCode != 200 { | ||||||
|  | 		return fmt.Errorf("Login failed %s", u.baseURL+url) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	data, err := ioutil.ReadAll(response.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = json.Unmarshal(data, &output) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *ucAPIData) ucLogin() error { | ||||||
|  | 	var loginData = []byte(`{"username":"` + u.user + `","password":"` + u.pass + `"}`) | ||||||
|  | 
 | ||||||
|  | 	url := "/api/login" | ||||||
|  | 	err := u.ucCallAPI(url, http.MethodPost, bytes.NewBuffer(loginData), nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *ucAPIData) ucGetSites() ([]ucSite, error) { | ||||||
|  | 	var d struct { | ||||||
|  | 		Data []ucSite `json:"data"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	url := "/api/self/sites" | ||||||
|  | 	err := u.ucCallAPI(url, http.MethodGet, bytes.NewBuffer([]byte{}), &d) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return []ucSite{}, err | ||||||
|  | 	} | ||||||
|  | 	return d.Data, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *ucAPIData) ucGetDevices(sites []ucSite) ([]ucDevice, error) { | ||||||
|  | 	var d struct { | ||||||
|  | 		Data []ucDevice `json:"data"` | ||||||
|  | 	} | ||||||
|  | 	var s []ucDevice | ||||||
|  | 
 | ||||||
|  | 	for _, site := range sites { | ||||||
|  | 		url := "/api/s/" + site.ID + "/stat/device" | ||||||
|  | 		u.ucCallAPI(url, http.MethodGet, bytes.NewBuffer([]byte{}), &d) | ||||||
|  | 		s = append(s, d.Data...) | ||||||
|  | 	} | ||||||
|  | 	return s, nil | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								types.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								types.go
									
									
									
									
									
								
							| @ -4,7 +4,9 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -142,3 +144,36 @@ type apiResponse struct { | |||||||
| 	Error      string `json:"error"` | 	Error      string `json:"error"` | ||||||
| 	Message    string `json:"message"` | 	Message    string `json:"message"` | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type jar struct { | ||||||
|  | 	lk      sync.Mutex | ||||||
|  | 	cookies map[string][]*http.Cookie | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ucSite struct { | ||||||
|  | 	Name string `json:"desc"` | ||||||
|  | 	ID   string `json:"name"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ucDevice struct { | ||||||
|  | 	IP       string `json:"ip"` | ||||||
|  | 	Mac      string `json:"mac"` | ||||||
|  | 	Model    string `json:"model"` | ||||||
|  | 	Version  string `json:"version"` | ||||||
|  | 	Gateway  string `json:"gateway_mac"` | ||||||
|  | 	Name     string `json:"name"` | ||||||
|  | 	State    int    `json:"state"` | ||||||
|  | 	LastSeen int    `json:"last_seen"` | ||||||
|  | 	Uptime   int    `json:"uptime"` | ||||||
|  | 	Sysstats struct { | ||||||
|  | 		CPU    string `json:"cpu"` | ||||||
|  | 		Memory string `json:"mem"` | ||||||
|  | 	} `json:"system-stats"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ucAPIData struct { | ||||||
|  | 	user    string | ||||||
|  | 	pass    string | ||||||
|  | 	baseURL string | ||||||
|  | 	client  *http.Client | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								ucDevices.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								ucDevices.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | { | ||||||
|  |     "devices":[ | ||||||
|  |       { | ||||||
|  |         "name": "UAP-AC-M_S03", | ||||||
|  |         "mac": "18:e8:29:56:6d:9e", | ||||||
|  |         "gateway_nexthop": "18e8292f7de6", | ||||||
|  |         "gateway": "a28cae6ff604", | ||||||
|  |         "domain": "unifi", | ||||||
|  |         "location": { | ||||||
|  |           "longitude":7.148406208, | ||||||
|  |           "latitude":50.817093402 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         "name": "Am-Krausacker-2", | ||||||
|  |         "mac": "18:e8:29:a0:6f:23", | ||||||
|  |         "gateway_nexthop": "18e8292f7de6", | ||||||
|  |         "gateway": "a28cae6ff604", | ||||||
|  |         "domain": "unifi", | ||||||
|  |         "location": { | ||||||
|  |           "longitude":7.148406208, | ||||||
|  |           "latitude":50.817093402 | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user