File: client.py

package info (click to toggle)
python-aiounifi 79-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 660 kB
  • sloc: python: 11,124; sh: 5; makefile: 5
file content (371 lines) | stat: -rw-r--r-- 9,513 bytes parent folder | download
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
"""Clients are devices on a UniFi network."""

from dataclasses import dataclass
from typing import Self, TypedDict, cast

from .api import ApiItem, ApiRequest


class TypedClient(TypedDict):
    """Client type definition."""

    _id: str
    _is_guest_by_uap: bool
    _is_guest_by_ugw: bool
    _is_guest_by_usw: bool
    _last_seen_by_uap: int
    _last_seen_by_ugw: int
    _last_seen_by_usw: int
    _uptime_by_uap: int
    _uptime_by_ugw: int
    _uptime_by_usw: int
    anomalies: int
    ap_mac: str
    assoc_time: int
    authorized: bool
    blocked: bool
    bssid: str
    bytes_r: int
    ccq: int
    channel: int
    dev_cat: int
    dev_family: int
    dev_id: int
    dev_id_override: int
    dev_vendor: int
    device_name: str
    dhcpend_time: int
    disconnect_timestamp: int
    eagerly_discovered: bool
    essid: str
    fingerprint_engine_version: str
    fingerprint_override: bool
    fingerprint_source: int
    first_seen: int
    fixed_ip: str
    fw_version: str
    gw_mac: str
    hostname: str
    hostname_source: str
    idletime: int
    ip: str
    is_11r: bool
    is_guest: bool
    is_wired: bool
    last_seen: bool
    latest_assoc_time: bool
    mac: str
    name: str
    network: str
    network_id: str
    noise: int
    noted: bool
    os_class: int
    os_name: int
    oui: str
    powersave_enabled: bool
    qos_policy_applied: bool
    radio: str
    radio_name: str
    radio_proto: str
    rssi: int
    rx_bytes: int
    rx_packets: int
    rx_rate: int
    satisfaction: int
    score: int
    signal: int
    site_id: str
    sw_depth: int
    sw_mac: str
    sw_port: int
    tx_bytes: int
    tx_packets: int
    tx_power: int
    tx_rate: int
    tx_retries: int
    uptime: int
    use_fixedip: bool
    user_id: str
    usergroup_id: str
    vlan: int
    wifi_tx_attempts: int
    wired_rate_mbps: int
    wired_tx_bytes: int
    wired_rx_bytes: int
    wired_tx_packets: int
    wired_rx_packets: int
    wired_tx_bytes_r: int
    wired_rx_bytes_r: int


@dataclass
class AllClientListRequest(ApiRequest):
    """Request object for all clients list."""

    @classmethod
    def create(cls) -> Self:
        """Create all clients list request."""
        return cls(method="get", path="/rest/user")


@dataclass
class ClientListRequest(ApiRequest):
    """Request object for active client list."""

    @classmethod
    def create(cls) -> Self:
        """Create active client list request."""
        return cls(method="get", path="/stat/sta")


@dataclass
class ClientBlockRequest(ApiRequest):
    """Request object for client block."""

    @classmethod
    def create(cls, mac: str, block: bool) -> Self:
        """Create client block request."""
        return cls(
            method="post",
            path="/cmd/stamgr",
            data={
                "cmd": "block-sta" if block else "unblock-sta",
                "mac": mac,
            },
        )


@dataclass
class ClientReconnectRequest(ApiRequest):
    """Request object for client reconnect."""

    @classmethod
    def create(cls, mac: str) -> Self:
        """Create client reconnect request."""
        return cls(
            method="post",
            path="/cmd/stamgr",
            data={
                "cmd": "kick-sta",
                "mac": mac,
            },
        )


@dataclass
class ClientRemoveRequest(ApiRequest):
    """Request object for client removal."""

    @classmethod
    def create(cls, macs: list[str]) -> Self:
        """Create client removal request."""
        return cls(
            method="post",
            path="/cmd/stamgr",
            data={
                "cmd": "forget-sta",
                "macs": macs,
            },
        )


class Client(ApiItem):
    """Represents a client network device."""

    raw: TypedClient

    @property
    def access_point_mac(self) -> str:
        """MAC address of access point."""
        return self.raw.get("ap_mac", "")

    @property
    def association_time(self) -> int:
        """When was client associated with controller."""
        return self.raw.get("assoc_time", 0)

    @property
    def blocked(self) -> bool:
        """Is client blocked."""
        return self.raw.get("blocked", False)

    @property
    def device_name(self) -> str:
        """Device name of client."""
        return self.raw.get("device_name", "")

    @property
    def essid(self) -> str:
        """ESSID client is connected to."""
        return self.raw.get("essid", "")

    @property
    def firmware_version(self) -> str:
        """Firmware version of client."""
        return self.raw.get("fw_version", "")

    @property
    def first_seen(self) -> int:
        """When was client first seen."""
        return self.raw.get("first_seen", 0)

    @property
    def fixed_ip(self) -> str:
        """List IP if fixed IP is configured."""
        return self.raw.get("fixed_ip", "")

    @property
    def hostname(self) -> str:
        """Hostname of client."""
        return self.raw.get("hostname", "")

    @property
    def idle_time(self) -> int:
        """Idle time of client."""
        return self.raw.get("idletime", 0)

    @property
    def ip(self) -> str:
        """IP of client."""
        return self.raw.get("ip", "")

    @property
    def is_guest(self) -> bool:
        """Is client guest."""
        return self.raw.get("is_guest", False)

    @property
    def is_wired(self) -> bool:
        """Is client wired."""
        return self.raw.get("is_wired", False)

    @property
    def last_seen(self) -> int:
        """When was client last seen."""
        return self.raw.get("last_seen", 0)

    @property
    def last_seen_by_access_point(self) -> int:
        """When was client last seen by access point."""
        return self.raw.get("_last_seen_by_uap", 0)

    @property
    def last_seen_by_gateway(self) -> int:
        """When was client last seen by gateway."""
        return self.raw.get("_last_seen_by_ugw", 0)

    @property
    def last_seen_by_switch(self) -> int:
        """When was client last seen by network switch."""
        return self.raw.get("_last_seen_by_usw", 0)

    @property
    def latest_association_time(self) -> int:
        """When was client last associated with controller."""
        return self.raw.get("latest_assoc_time", 0)

    @property
    def mac(self) -> str:
        """MAC address of client."""
        return self.raw.get("mac", "")

    @property
    def name(self) -> str:
        """Name of client."""
        return self.raw.get("name", "")

    @property
    def oui(self) -> str:
        """Vendor string for client MAC."""
        return self.raw.get("oui", "")

    @property
    def powersave_enabled(self) -> bool | None:
        """Powersave functionality enabled for wireless client."""
        return self.raw.get("powersave_enabled")

    @property
    def site_id(self) -> str:
        """Site ID client belongs to."""
        return self.raw.get("site_id", "")

    @property
    def switch_depth(self) -> int | None:
        """How many layers of switches client is in."""
        return self.raw.get("sw_depth")

    @property
    def switch_mac(self) -> str:
        """MAC for switch client is connected to."""
        return self.raw.get("sw_mac", "")

    @property
    def switch_port(self) -> int | None:
        """Switch port client is connected to."""
        return self.raw.get("sw_port")

    @property
    def rx_bytes(self) -> int:
        """Bytes received over wireless connection."""
        return self.raw.get("rx_bytes", 0)

    @property
    def rx_bytes_r(self) -> float:
        """Bytes recently received over wireless connection."""
        return cast(float, self.raw.get("rx_bytes-r", 0.0))

    @property
    def tx_bytes(self) -> int:
        """Bytes transferred over wireless connection."""
        return self.raw.get("tx_bytes", 0)

    @property
    def tx_bytes_r(self) -> float:
        """Bytes recently transferred over wireless connection."""
        return cast(float, self.raw.get("tx_bytes-r", 0.0))

    @property
    def uptime(self) -> int:
        """Uptime of client."""
        return self.raw.get("uptime", 0)

    @property
    def uptime_by_access_point(self) -> int:
        """Uptime of client observed by access point."""
        return self.raw.get("_uptime_by_uap", 0)

    @property
    def uptime_by_gateway(self) -> int:
        """Uptime of client observed by gateway."""
        return self.raw.get("_uptime_by_ugw", 0)

    @property
    def uptime_by_switch(self) -> int:
        """Uptime of client observed by network switch."""
        return self.raw.get("_uptime_by_usw", 0)

    @property
    def wired_rate_mbps(self) -> int:
        """Wired rate in Mbps."""
        return self.raw.get("wired_rate_mbps", 0)

    @property
    def wired_rx_bytes(self) -> int:
        """Bytes received over wired connection."""
        return cast(int, self.raw.get("wired-rx_bytes", 0))

    @property
    def wired_rx_bytes_r(self) -> float:
        """Bytes recently received over wired connection."""
        return cast(float, self.raw.get("wired-rx_bytes-r", 0.0))

    @property
    def wired_tx_bytes(self) -> int:
        """Bytes transferred over wired connection."""
        return cast(int, self.raw.get("wired-tx_bytes", 0))

    @property
    def wired_tx_bytes_r(self) -> float:
        """Bytes recently transferred over wired connection."""
        return cast(float, self.raw.get("wired-tx_bytes-r", 0.0))