package main import ( "encoding/json" "fmt" "net/http" "time" "git.tordarus.net/tordarus/channel" "git.tordarus.net/tordarus/envvars" "git.tordarus.net/tordarus/gmath" omada "git.tordarus.net/tordarus/omada-api" omadamodel "git.tordarus.net/tordarus/omada-api/model" "git.tordarus.net/tordarus/slices" ) var ( // flags FlagSiteNames = envvars.StringSlice("SITES", ",", []string{}) FlagOmadaURL = envvars.String("OMADA_URL", "http://localhost:8088") FlagOmadaID = envvars.String("OMADA_ID", "") FlagOmadaClientID = envvars.String("OMADA_CLIENT_ID", "") FlagOmadaClientSecret = envvars.String("OMADA_CLIENT_SECRET", "") FlagOmadaUsername = envvars.String("OMADA_USERNAME", "") FlagOmadaPassword = envvars.String("OMADA_PASSWORD", "") FlagRefreshInterval = envvars.Duration("REFRESH_INTERVAL", 30*time.Second) FlagRefreshBeforeExpiration = envvars.Duration("REFRESH_BEFORE", time.Minute) FlagHttpInterface = envvars.String("HTTP_INTERFACE", "") FlagHttpPort = envvars.Uint16("HTTP_PORT", 8080) ) var MinRefreshInterval = 30 * time.Second var CurrentTraffic = &TrafficStats{} func main() { FlagRefreshInterval = gmath.Max(FlagRefreshInterval, MinRefreshInterval) api, err := omada.NewApi(omada.ApiConfig{ BasePath: FlagOmadaURL, OmadaID: FlagOmadaID, ClientID: FlagOmadaClientID, ClientSecret: FlagOmadaClientSecret, Username: FlagOmadaUsername, Password: FlagOmadaPassword, }) if err != nil { panic(err) } go StartHttpServer() sites := slices.Ref(slices.Filter( channel.ToSlice(channel.Map(api.GetSites(), channel.Result[omadamodel.Site].GetUnsafe)), FilterSitesByName(FlagSiteNames...), )) ticker := time.NewTicker(FlagRefreshInterval) lastTick := time.Now() CalculateSiteTraffic(api, sites, 0) for now := range ticker.C { CurrentTraffic = CalculateSiteTraffic(api, sites, now.Sub(lastTick)) lastTick = now } } func CalculateSiteTraffic(api *omada.Api, sites []*omadamodel.Site, duration time.Duration) *TrafficStats { siteTraffics := map[string]*SiteTraffic{} for _, site := range sites { trafficByClient := map[string]TrafficRate{} clientRequests := channel.ToSlice(api.GetClients(site.ID)) for _, clientReq := range clientRequests { client, err := clientReq.Get() if err != nil { panic(err) } traffic := CalculateClientTraffic(site, &client, duration) trafficByClient[client.Name] = traffic } siteTraffics[site.Name] = NewSiteTraffic(trafficByClient) } return NewTrafficStats(siteTraffics) } func FilterSitesByName(allowedSiteNames ...string) func(site omadamodel.Site) bool { if len(allowedSiteNames) == 0 { return func(site omadamodel.Site) bool { return true } } siteNames := slices.ToStructMap(allowedSiteNames) return func(site omadamodel.Site) bool { _, ok := siteNames[site.Name] return ok } } func StartHttpServer() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if err := json.NewEncoder(w).Encode(CurrentTraffic); err != nil { w.WriteHeader(http.StatusInternalServerError) } }) connString := fmt.Sprintf("%s:%d", FlagHttpInterface, FlagHttpPort) if err := http.ListenAndServe(connString, nil); err != nil { panic(err) } }