initial commit
This commit is contained in:
commit
751ddc2436
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*_test.go
|
33
ap_info.go
Normal file
33
ap_info.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package omadaapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.tordarus.net/tordarus/ezhttp"
|
||||||
|
"git.tordarus.net/tordarus/omada-api/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *Api) GetApInfo(siteID model.SiteID, macAddress string) (*model.ApInfo, error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("GET"),
|
||||||
|
ezhttp.AppendPath(
|
||||||
|
fmt.Sprintf("/openapi/v1/%s/sites/%s/aps/%s",
|
||||||
|
api.config.OmadaID,
|
||||||
|
siteID,
|
||||||
|
macAddress)),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.Response[model.ApInfo]](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response.Result, nil
|
||||||
|
}
|
151
api.go
Normal file
151
api.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package omadaapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.tordarus.net/tordarus/ezhttp"
|
||||||
|
"git.tordarus.net/tordarus/omada-api/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Api struct {
|
||||||
|
tmpl *http.Request
|
||||||
|
|
||||||
|
config ApiConfig
|
||||||
|
|
||||||
|
accessToken string
|
||||||
|
refreshToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiConfig struct {
|
||||||
|
BasePath string
|
||||||
|
OmadaID string
|
||||||
|
ClientID string
|
||||||
|
ClientSecret string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApi(config ApiConfig) (*Api, error) {
|
||||||
|
tmpl := ezhttp.Request(ezhttp.URL(config.BasePath))
|
||||||
|
|
||||||
|
api := &Api{
|
||||||
|
tmpl: tmpl,
|
||||||
|
config: config,
|
||||||
|
}
|
||||||
|
|
||||||
|
loginResponse, err := api.Login()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("login request failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loginResponse.ErrorCode != 0 {
|
||||||
|
return nil, fmt.Errorf("login request failed: %s", loginResponse.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
authCodeResponse, err := api.AuthCode(loginResponse.Result.CsrfToken, loginResponse.Result.SessionID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("auth code request failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if authCodeResponse.ErrorCode != 0 {
|
||||||
|
return nil, fmt.Errorf("auth code request failed: %s", authCodeResponse.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
authTokenResponse, err := api.AuthToken(*authCodeResponse.Result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("auth token request failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if authTokenResponse.ErrorCode != 0 {
|
||||||
|
return nil, fmt.Errorf("auth token request failed: %s", authTokenResponse.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
api.accessToken = authTokenResponse.Result.AccessToken
|
||||||
|
api.refreshToken = authTokenResponse.Result.RefreshToken
|
||||||
|
|
||||||
|
api.tmpl = ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Headers("Authorization", "AccessToken="+api.accessToken),
|
||||||
|
)
|
||||||
|
|
||||||
|
return api, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) Login() (*model.LoginResponse, error) {
|
||||||
|
reqBody := model.LoginRequest{
|
||||||
|
Username: api.config.Username,
|
||||||
|
Password: api.config.Password,
|
||||||
|
}
|
||||||
|
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("POST"),
|
||||||
|
ezhttp.AppendPath("/openapi/authorize/login"),
|
||||||
|
ezhttp.Query("client_id", api.config.ClientID, "omadac_id", api.config.OmadaID),
|
||||||
|
ezhttp.Body(ezhttp.JSON(reqBody)),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.LoginResponse](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) AuthCode(csrfToken, sessionID string) (*model.AuthCodeResponse, error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("POST"),
|
||||||
|
ezhttp.AppendPath("/openapi/authorize/code"),
|
||||||
|
ezhttp.Query("client_id", api.config.ClientID, "omadac_id", api.config.OmadaID, "response_type", "code"),
|
||||||
|
ezhttp.Headers("Csrf-Token", csrfToken, "Cookie", fmt.Sprintf("TPOMADA_SESSIONID=%s", sessionID)),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.AuthCodeResponse](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) AuthToken(authCode string) (*model.AuthTokenResponse, error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("POST"),
|
||||||
|
ezhttp.AppendPath("/openapi/authorize/token"),
|
||||||
|
ezhttp.Query(
|
||||||
|
"code", authCode,
|
||||||
|
"grant_type", "authorization_code",
|
||||||
|
"client_id", api.config.ClientID,
|
||||||
|
"client_secret", api.config.ClientSecret,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.AuthTokenResponse](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
59
client.go
Normal file
59
client.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package omadaapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.tordarus.net/tordarus/ezhttp"
|
||||||
|
"git.tordarus.net/tordarus/omada-api/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *Api) GetClients(siteID model.SiteID) <-chan *model.Client {
|
||||||
|
out := make(chan *model.Client, 1000)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(out)
|
||||||
|
|
||||||
|
for page := 1; ; page++ {
|
||||||
|
resp, err := api.getClients(page, siteID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range resp.Result.Data {
|
||||||
|
out <- &v
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Result.CurrentPage*resp.Result.CurrentSize >= resp.Result.TotalRows {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) getClients(page int, siteID model.SiteID) (*model.PagedResponse[model.Client], error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("GET"),
|
||||||
|
ezhttp.AppendPath(fmt.Sprintf("/openapi/v1/%s/sites/%s/clients", api.config.OmadaID, siteID)),
|
||||||
|
ezhttp.Query(
|
||||||
|
"page", strconv.Itoa(page),
|
||||||
|
"pageSize", "100",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.PagedResponse[model.Client]](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
59
device.go
Normal file
59
device.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package omadaapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.tordarus.net/tordarus/ezhttp"
|
||||||
|
"git.tordarus.net/tordarus/omada-api/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *Api) GetDevices(siteID model.SiteID) <-chan *model.Device {
|
||||||
|
out := make(chan *model.Device, 1000)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(out)
|
||||||
|
|
||||||
|
for page := 1; ; page++ {
|
||||||
|
resp, err := api.getDevices(page, siteID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range resp.Result.Data {
|
||||||
|
out <- &v
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Result.CurrentPage*resp.Result.CurrentSize >= resp.Result.TotalRows {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) getDevices(page int, siteID model.SiteID) (*model.PagedResponse[model.Device], error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("GET"),
|
||||||
|
ezhttp.AppendPath(fmt.Sprintf("/openapi/v1/%s/sites/%s/devices", api.config.OmadaID, siteID)),
|
||||||
|
ezhttp.Query(
|
||||||
|
"page", strconv.Itoa(page),
|
||||||
|
"pageSize", "100",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.PagedResponse[model.Device]](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module git.tordarus.net/tordarus/omada-api
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require git.tordarus.net/tordarus/ezhttp v0.0.3
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
git.tordarus.net/tordarus/ezhttp v0.0.3 h1:K6IlLmqkAFUF68HJsOTKcP3ejco7qfm+MuEagohoouo=
|
||||||
|
git.tordarus.net/tordarus/ezhttp v0.0.3/go.mod h1:Zq9o0Hibny61GqSCwJHa0PfGjVoUFv/zt2PjiQHXvmY=
|
40
model/ap_info.go
Normal file
40
model/ap_info.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type ApInfo struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
MacAddress string `json:"mac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
IPv6 []string `json:"ipv6List"`
|
||||||
|
WlanGroupID string `json:"wlanId"`
|
||||||
|
WirelessUplinkInfo *ApWirelessUplinkInfo `json:"wirelessUplink"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
FirmwareVersion string `json:"firmwareVersion"`
|
||||||
|
CpuUtil int `json:"cpuUtil"`
|
||||||
|
MemUtil int `json:"memoryUtil"`
|
||||||
|
UptimeSeconds int `json:"uptimeLong"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i ApInfo) String() string {
|
||||||
|
data, _ := json.MarshalIndent(i, "", "\t")
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApWirelessUplinkInfo struct {
|
||||||
|
UplinkMacAddress string `json:"uplinkMac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Channel int `json:"channel"`
|
||||||
|
SignalStrengh int `json:"rssi"`
|
||||||
|
SignalNoiseRatio int `json:"snr"`
|
||||||
|
TransferRate string `json:"txRate"`
|
||||||
|
TransferRateMbps int `json:"txRateInt"`
|
||||||
|
ReceiveRate string `json:"rxRate"`
|
||||||
|
ReceiveRateMbps int `json:"rxRateInt"`
|
||||||
|
UpBytes int `json:"upBytes"`
|
||||||
|
DownBytes int `json:"downBytes"`
|
||||||
|
UpPackets int `json:"upPackets"`
|
||||||
|
DownPackets int `json:"downPackets"`
|
||||||
|
Activity int `json:"activity"`
|
||||||
|
}
|
209
model/client.go
Normal file
209
model/client.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
MacAddress string `json:"mac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Hostname string `json:"hostName"`
|
||||||
|
Vendor string `json:"vendor"`
|
||||||
|
DeviceType string `json:"deviceType"`
|
||||||
|
DeviceCategory string `json:"deviceCategory"`
|
||||||
|
OsName string `json:"osName"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
IPv6List []string `json:"ipv6List"`
|
||||||
|
ConnectionType ConnectionType `json:"connectType"`
|
||||||
|
ConnectionDevType ConnectionDeviceType `json:"connectDevType"`
|
||||||
|
ConnectedToWirelessRouter bool `json:"connectedToWirelessRouter"`
|
||||||
|
Wireless bool `json:"wireless"`
|
||||||
|
SSID string `json:"ssid"`
|
||||||
|
SignalLevel int `json:"signalLevel"`
|
||||||
|
HealthScore int `json:"healthScore"`
|
||||||
|
SignalRank int `json:"signalRank"`
|
||||||
|
WifiMode WifiMode `json:"wifiMode"`
|
||||||
|
ApName string `json:"apName"`
|
||||||
|
ApMac string `json:"apMac"`
|
||||||
|
RadioID RadioID `json:"radioId"`
|
||||||
|
Channel int `json:"channel"`
|
||||||
|
ReceiveRateKbits int `json:"rxRate"`
|
||||||
|
TransferRateKbits int `json:"txRate"`
|
||||||
|
PowerSave bool `json:"powerSave"`
|
||||||
|
SignalStrengh int `json:"rssi"`
|
||||||
|
SignalNoiseRatio int `json:"snr"`
|
||||||
|
SwitchMac string `json:"switchMac"`
|
||||||
|
SwitchName string `json:"switchName"`
|
||||||
|
GatewayMac string `json:"gatewayMac"`
|
||||||
|
GatewayName string `json:"gatewayName"`
|
||||||
|
VLanID int `json:"vid"`
|
||||||
|
NetworkName string `json:"networkName"`
|
||||||
|
Dot1xIdentity string `json:"dot1xIdentity"`
|
||||||
|
Dot1xVlan int `json:"dot1xVlan"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
LagID int `json:"lagId"`
|
||||||
|
Activity int `json:"activity"`
|
||||||
|
TrafficDownBytes int `json:"trafficDown"`
|
||||||
|
TrafficUpBytes int `json:"trafficUp"`
|
||||||
|
UptimeSeconds int `json:"uptime"`
|
||||||
|
LastSeen int `json:"lastSeen"`
|
||||||
|
AuthStatus AuthStatus `json:"authStatus"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
Guest bool `json:"guest"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Manager bool `json:"manager"`
|
||||||
|
IpSetting *ClientIpSetting `json:"ipSetting"`
|
||||||
|
DownPacket int `json:"downPacket"`
|
||||||
|
UpPacket int `json:"upPacket"`
|
||||||
|
RateLimit *ClientRateLimit `json:"rateLimit"`
|
||||||
|
ClientLockToApSetting *ClientLockToApSetting `json:"clientLockToApSetting"`
|
||||||
|
MultiLink []*ClientMultiFrequencyInfo `json:"multiLink"`
|
||||||
|
Unit int `json:"unit"`
|
||||||
|
StandardPort string `json:"standardPort"`
|
||||||
|
BlockDisable bool `json:"blockDisable"`
|
||||||
|
DhcpLeaseTimeSeconds int `json:"dhcpLeaseTime"`
|
||||||
|
SystemName string `json:"systemName"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Capabilities []string `json:"capabilities"`
|
||||||
|
ClientStat *ClientStat `json:"clientStat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) String() string {
|
||||||
|
data, _ := json.MarshalIndent(c, "", "\t")
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectionType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConnectionTypeWirelessGuest ConnectionType = iota
|
||||||
|
ConnectionTypeWirelessUser
|
||||||
|
ConnectionTypeWiredUser
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnectionDeviceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConnectionDeviceTypeAP ConnectionDeviceType = "ap"
|
||||||
|
ConnectionDeviceTypeSwitch ConnectionDeviceType = "switch"
|
||||||
|
ConnectionDeviceTypeGateway ConnectionDeviceType = "gateway"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WifiMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
WifiMode11a WifiMode = iota
|
||||||
|
WifiMode11b
|
||||||
|
WifiMode11g
|
||||||
|
WifiMode11na
|
||||||
|
WifiMode11ng
|
||||||
|
WifiMode11ac
|
||||||
|
WifiMode11axa
|
||||||
|
WifiMode11axg
|
||||||
|
WifiMode11beg
|
||||||
|
WifiMode11bea
|
||||||
|
)
|
||||||
|
|
||||||
|
type RadioID int
|
||||||
|
|
||||||
|
const (
|
||||||
|
RadioID_2_4G RadioID = iota
|
||||||
|
RadioID_5G RadioID = iota
|
||||||
|
RadioID_5G2 RadioID = iota
|
||||||
|
RadioID_6G RadioID = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthStatusConnected AuthStatus = iota
|
||||||
|
AuthStatusPending
|
||||||
|
AuthStatusAuthorized
|
||||||
|
AuthStatusAuthFree
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientIpSetting struct {
|
||||||
|
UseFixedAddr bool `json:"useFixedAddr"`
|
||||||
|
NetID string `json:"netId"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientRateLimit struct {
|
||||||
|
Mode RateLimitMode `json:"mode"`
|
||||||
|
RateLimitProfileID string `json:"rateLimitProfileId"`
|
||||||
|
CustomRateLimit *CustomRateLimit `json:"customRateLimit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RateLimitMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
RateLimitModeCustom RateLimitMode = iota
|
||||||
|
RateLimitModeProfile
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomRateLimit struct {
|
||||||
|
UpEnable bool `json:"upEnable"`
|
||||||
|
UpUnit SpeedUnit `json:"upUnit"`
|
||||||
|
UpLimit int `json:"upLimit"`
|
||||||
|
DownEnable bool `json:"downEnable"`
|
||||||
|
DownUnit SpeedUnit `json:"downUnit"`
|
||||||
|
DownLimit int `json:"downLimit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpeedUnit int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SpeedUnitKbps SpeedUnit = iota
|
||||||
|
SpeedUnitMbps
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientLockToApSetting struct {
|
||||||
|
Enable bool `json:"enable"`
|
||||||
|
APs []*ApBriefInfo `json:"aps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApBriefInfo struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MacAddress string `json:"mac"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientMultiFrequencyInfo struct {
|
||||||
|
RadioID int `json:"radioId"`
|
||||||
|
WifiMode WifiMode `json:"wifiMode"`
|
||||||
|
Channel int `json:"channel"`
|
||||||
|
ReceiveRateKbits int `json:"rxRate"`
|
||||||
|
TransferRateKbits int `json:"txRate"`
|
||||||
|
PowerSave bool `json:"powerSave"`
|
||||||
|
SignalStrengh int `json:"rssi"`
|
||||||
|
SignalNoiseRatio int `json:"snr"`
|
||||||
|
SignalLevel int `json:"signalLevel"`
|
||||||
|
SignalRank int `json:"signalRank"`
|
||||||
|
UpPacket int `json:"upPacket"`
|
||||||
|
DownPacket int `json:"downPacket"`
|
||||||
|
TrafficDownBytes int `json:"trafficDown"`
|
||||||
|
TrafficUpBytes int `json:"trafficUp"`
|
||||||
|
Activity int `json:"activity"`
|
||||||
|
SignalLevelAndRank int `json:"signalLevelAndRank"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientStat struct {
|
||||||
|
Total int `json:"total"`
|
||||||
|
Wireless int `json:"wireless"`
|
||||||
|
Wired int `json:"wired"`
|
||||||
|
Num2G int `json:"num2g"`
|
||||||
|
Num5G int `json:"num5g"`
|
||||||
|
Num6G int `json:"num6g"`
|
||||||
|
NumUser int `json:"numUser"`
|
||||||
|
NumGuest int `json:"numGuest"`
|
||||||
|
NumWirelessUser int `json:"numWirelessUser"`
|
||||||
|
NumWirelessGuest int `json:"numWirelessGuest"`
|
||||||
|
Num2gUser int `json:"num2gUser"`
|
||||||
|
Num5gUser int `json:"num5gUser"`
|
||||||
|
Num6gUser int `json:"num6gUser"`
|
||||||
|
Num2gGuest int `json:"num2gGuest"`
|
||||||
|
Num5gGuest int `json:"num5gGuest"`
|
||||||
|
Num6gGuest int `json:"num6gGuest"`
|
||||||
|
Poor int `json:"poor"`
|
||||||
|
Fair int `json:"fair"`
|
||||||
|
NoData int `json:"noData"`
|
||||||
|
Good int `json:"good"`
|
||||||
|
}
|
45
model/device.go
Normal file
45
model/device.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
MacAddress string `json:"mac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type DeviceType `json:"type"`
|
||||||
|
Subtype string `json:"subtype"`
|
||||||
|
DeviceSeriesType int `json:"deviceSeriesType"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
IPv6 []string `json:"ipv6"`
|
||||||
|
Uptime string `json:"uptime"`
|
||||||
|
Status DeviceStatus `json:"status"`
|
||||||
|
LastSeen int `json:"lastSeen"`
|
||||||
|
CpuUtil int `json:"cpuUtil"`
|
||||||
|
MemUtil int `json:"memUtil"`
|
||||||
|
SerialNumber string `json:"sn"`
|
||||||
|
LicenseStatus int `json:"licenseStatus"`
|
||||||
|
TagName string `json:"tagName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Device) String() string {
|
||||||
|
data, _ := json.MarshalIndent(d, "", "\t")
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DeviceStatusDisconnected DeviceStatus = iota
|
||||||
|
DeviceStatusConnected
|
||||||
|
DeviceStatusPending
|
||||||
|
DeviceStatusHeartbeatMissed
|
||||||
|
DeviceStatusIsolated
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeviceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DeviceTypeAP DeviceType = "ap"
|
||||||
|
)
|
26
model/login.go
Normal file
26
model/login.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type LoginRequest struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginResponse Response[LoginResponseResult]
|
||||||
|
type LoginResponseResult struct {
|
||||||
|
CsrfToken string `json:"csrfToken"`
|
||||||
|
SessionID string `json:"sessionId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthCodeResponse struct {
|
||||||
|
ErrorCode int `json:"errorCode"`
|
||||||
|
Message string `json:"msg"`
|
||||||
|
Result *string `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthTokenResponse Response[AuthTokenResponseResult]
|
||||||
|
type AuthTokenResponseResult struct {
|
||||||
|
AccessToken string `json:"accessToken"`
|
||||||
|
TokenType string `json:"tokenType"`
|
||||||
|
ExpiresIn int `json:"expiresIn"`
|
||||||
|
RefreshToken string `json:"refreshToken"`
|
||||||
|
}
|
15
model/response.go
Normal file
15
model/response.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Response[T any] struct {
|
||||||
|
ErrorCode int `json:"errorCode"`
|
||||||
|
Message string `json:"msg"`
|
||||||
|
Result T `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PagedResponse[T any] Response[PagedResponseResult[T]]
|
||||||
|
type PagedResponseResult[T any] struct {
|
||||||
|
TotalRows int `json:"totalRows"`
|
||||||
|
CurrentPage int `json:"currentPage"`
|
||||||
|
CurrentSize int `json:"currentSize"`
|
||||||
|
Data []T `json:"data"`
|
||||||
|
}
|
22
model/site.go
Normal file
22
model/site.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type SiteID string
|
||||||
|
type Site struct {
|
||||||
|
ID SiteID `json:"siteId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
TagIDs []string `json:"tagIds"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
TimeZone string `json:"timeZone"`
|
||||||
|
Scenario string `json:"scenario"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Type int `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Site) String() string {
|
||||||
|
data, _ := json.MarshalIndent(s, "", "\t")
|
||||||
|
return string(data)
|
||||||
|
}
|
59
site.go
Normal file
59
site.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package omadaapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.tordarus.net/tordarus/ezhttp"
|
||||||
|
"git.tordarus.net/tordarus/omada-api/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *Api) GetSites() <-chan *model.Site {
|
||||||
|
out := make(chan *model.Site, 1000)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(out)
|
||||||
|
|
||||||
|
for page := 1; ; page++ {
|
||||||
|
resp, err := api.getSites(page)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range resp.Result.Data {
|
||||||
|
out <- &v
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Result.CurrentPage*resp.Result.CurrentSize >= resp.Result.TotalRows {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Api) getSites(page int) (*model.PagedResponse[model.Site], error) {
|
||||||
|
req := ezhttp.Request(
|
||||||
|
ezhttp.Template(api.tmpl),
|
||||||
|
ezhttp.Method("GET"),
|
||||||
|
ezhttp.AppendPath(fmt.Sprintf("/openapi/v1/%s/sites", api.config.OmadaID)),
|
||||||
|
ezhttp.Query(
|
||||||
|
"page", strconv.Itoa(page),
|
||||||
|
"pageSize", "100",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
resp, err := ezhttp.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
response, err := ezhttp.ParseJsonResponse[model.PagedResponse[model.Site]](resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user