/
api_types.go
194 lines (167 loc) · 4.73 KB
/
api_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package exporter
import (
"strconv"
"time"
)
type rebootResponse struct {
Unixtime int `json:"uTs"`
Reason string `json:"code"`
}
type radioResponse struct {
ID int `json:"id"`
Band string `json:"band"` // enum: { "2.4GHz", "5GHz" }
ChannelWidth string `json:"chWidth"`
Channel string `json:"channel"`
MAC string `json:"mac"`
Power int `json:"pow"`
Quality int `json:"rfqlt"` // percentage points
RxAvg int `json:"rxAvg"` // in kbps
TxAvg int `json:"txAvg"` // in kbps
}
// DeviceAPIResponse holds the data returned from the controller's
// device endpoint.
type DeviceAPIResponse struct {
Model string `json:"model"`
MAC string `json:"mac"`
Serial string `json:"sn"`
SiteName string `json:"tid"`
Config struct {
Name string `json:"name"`
} `json:"cfg"`
System struct {
Online bool `json:"online"`
UpTime int64 `json:"upTime"`
DownTime int64 `json:"dnTime"`
Reboots []rebootResponse `json:"lastRbt"`
} `json:"sys"`
Management struct {
FirmwareVersion string `json:"actSw"`
} `json:"mgmt"`
Radios []radioResponse `json:"radios"`
}
type Radio struct {
Band Band
Channel int // channel number
ChannelWidth int // in MHz
Power int
Quality int // 0..100
Rx int // average rate in kbps
Tx int // average rate in kbps
}
func (radio radioResponse) Normalize() (r Radio) {
r = Radio{
Band: BandUnknown,
Channel: -1,
ChannelWidth: -1,
Rx: radio.RxAvg,
Tx: radio.TxAvg,
Quality: radio.Quality,
Power: radio.Power,
}
switch radio.Band {
case "2.4GHz", "2.4 GHz":
r.Band = BandBGN
case "5GHz", "5 GHz":
r.Band = BandAC
}
if ch, err := strconv.Atoi(radio.Channel); err == nil {
r.Channel = ch
}
if chw, err := strconv.Atoi(radio.ChannelWidth); err == nil {
r.ChannelWidth = chw
}
return
}
type Band string
const (
BandAC = Band("5")
BandBGN = Band("2.4")
BandUnknown = Band("unknown")
)
// Device holds basic metrics for a single WiFi AP.
// It is constructed from a DeviceAPIResponse.
type Device struct {
Model string
MAC string
Serial string
SiteName string
Hostname string
FirmwareVersion string
Uptime *time.Time
Downtime *time.Time
LastRebootAt *time.Time
RebootReason string
Radios []Radio
}
func msToTime(ms int64) time.Time {
ns := time.Duration(ms) * time.Millisecond
return time.Unix(0, int64(ns))
}
func (api *DeviceAPIResponse) Normalize() *Device {
dev := &Device{
Model: api.Model,
MAC: api.MAC,
Serial: api.Serial,
SiteName: api.SiteName,
Hostname: api.Config.Name,
FirmwareVersion: api.Management.FirmwareVersion,
}
if api.System.Online {
t := msToTime(api.System.UpTime)
dev.Uptime = &t
} else {
t := msToTime(api.System.DownTime)
dev.Downtime = &t
}
if len(api.System.Reboots) > 0 {
lastReboot := api.System.Reboots[0]
for _, r := range api.System.Reboots {
if r.Unixtime > lastReboot.Unixtime {
lastReboot = r
}
}
t := time.Unix(int64(lastReboot.Unixtime), 0)
dev.LastRebootAt = &t
dev.RebootReason = lastReboot.Reason
}
for _, radio := range api.Radios {
dev.Radios = append(dev.Radios, radio.Normalize())
}
return dev
}
type APGroupAPIResponse struct {
Name string `json:"name"`
DevicesCount int `json:"deviceCount"`
DevicesOffline int `json:"offlineCount"`
DevicesOutOfSync int `json:"outOfSyncCount"`
ClientCount int `json:"clientCount"`
ClientCount24H int `json:"clientCount24h"`
}
// PortalAPIResponse is returned when asking the API for a list of
// "Guest Access Portals". It also contains a JSON-encoded config string
// (yes, double JSON). We've elected to omit this it here.
type PortalAPIResponse struct {
Name string `json:"name"`
}
type SessionsAPIResponse struct {
Meta struct {
Limit int `json:"limit"`
Offset int `json:"offset"`
Total int `json:"totalCount"`
} `json:"_metadata"`
Sessions []struct {
DeviceMAC string `json:"apMAC"`
// Expiry int `json:"expiry"` // omitted, not measured
// Validity int `json:"validity"` // omitted, not measured
// ClientMAC string `json:"clientMac"` // omitted, PII
// WLAN string `json:"wlan"` // omitted, part of portal config
// PortalName string `json:"portalName"` // omitted, part of the request
// AccessType string `json:"accessType"` // omitted, part of portal config
// VoucherCode string `json:"voucherCode"` // omitted, volatile
} `json:"result"`
}
type PortalSession struct {
DeviceMAC string
PortalName string
Sessions int
}